Skip to content

Commit

Permalink
Fix #715: add 1s timeout before any previewing request
Browse files Browse the repository at this point in the history
  • Loading branch information
xupefei committed Aug 23, 2020
1 parent 80d95db commit dd02575
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 44 deletions.
8 changes: 3 additions & 5 deletions QuickLook/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -80,7 +78,7 @@ private void Application_Startup(object sender, StartupEventArgs e)
Shutdown();
return;
}

CheckUpdate();
RunListener(e);

Expand Down Expand Up @@ -115,7 +113,7 @@ private void RunListener(StartupEventArgs e)

PluginManager.GetInstance();
ViewWindowManager.GetInstance();
BackgroundListener.GetInstance();
KeystrokeDispatcher.GetInstance();
PipeServerManager.GetInstance();
}

Expand All @@ -128,7 +126,7 @@ private void App_OnExit(object sender, ExitEventArgs e)

PipeServerManager.GetInstance().Dispose();
TrayIconManager.GetInstance().Dispose();
BackgroundListener.GetInstance().Dispose();
KeystrokeDispatcher.GetInstance().Dispose();
ViewWindowManager.GetInstance().Dispose();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Windows.Input;
using QuickLook.Common.NativeMethods;
using KeyEventArgs = System.Windows.Forms.KeyEventArgs;
using KeyEventHandler = System.Windows.Forms.KeyEventHandler;

namespace QuickLook
namespace QuickLook.Helpers
{
internal class GlobalKeyboardHook : IDisposable
{
private static GlobalKeyboardHook _instance;

private User32.KeyboardHookProc _callback;
private IntPtr _hhook = IntPtr.Zero;
internal List<Keys> HookedKeys = new List<Keys>();

protected GlobalKeyboardHook()
{
Expand Down Expand Up @@ -72,25 +70,23 @@ private void Unhook()

private int HookProc(int code, int wParam, ref User32.KeyboardHookStruct lParam)
{
if (code >= 0)
if (!IsWindowsKeyPressed())
{
var key = (Keys) lParam.vkCode;
if (HookedKeys.Contains(key))
{
key = AddModifiers(key);

var kea = new KeyEventArgs(key);
if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN)
KeyDown?.Invoke(this, kea);
if (wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP)
KeyUp?.Invoke(this, kea);
if (kea.Handled)
return 1;
}
}

return User32.CallNextHookEx(_hhook, code, wParam, ref lParam);
if (code < 0)
return User32.CallNextHookEx(_hhook, code, wParam, ref lParam);

if (IsWindowsKeyPressed())
return User32.CallNextHookEx(_hhook, code, wParam, ref lParam);

var key = (Keys) lParam.vkCode;
key = AddModifiers(key);

var kea = new KeyEventArgs(key);

if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN)
KeyDown?.Invoke(this, kea);
else if (wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP)
KeyUp?.Invoke(this, kea);

return kea.Handled ? 1 : User32.CallNextHookEx(_hhook, code, wParam, ref lParam);
}

private bool IsWindowsKeyPressed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,35 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
using QuickLook.Common.Helpers;
using QuickLook.Helpers;

namespace QuickLook
{
internal class BackgroundListener : IDisposable
internal class KeystrokeDispatcher : IDisposable
{
private static BackgroundListener _instance;
private static KeystrokeDispatcher _instance;

private static HashSet<Keys> _validKeys;

private GlobalKeyboardHook _hook;
private bool _isKeyDownInDesktopOrShell;
private long _lastInvalidKeyPressTick;

private const long VALID_KEY_PRESS_DELAY = TimeSpan.TicksPerSecond * 1;

protected BackgroundListener()
protected KeystrokeDispatcher()
{
InstallKeyHook(KeyDownEventHandler, KeyUpEventHandler);

_validKeys = new HashSet<Keys>(new[]
{
Keys.Up, Keys.Down, Keys.Left, Keys.Right,
Keys.Enter, Keys.Space, Keys.Escape
});
}

public void Dispose()
Expand All @@ -55,7 +68,7 @@ private void CallViewWindowManagerInvokeRoutine(KeyEventArgs e, bool isKeyDown)
if (e.Modifiers != Keys.None)
return;

// set variable only when KeyDown
// check if the window is valid at the time of pressing a key, used for case 1
if (isKeyDown)
{
_isKeyDownInDesktopOrShell = NativeMethods.QuickLook.GetFocusedWindowType() !=
Expand All @@ -64,17 +77,32 @@ private void CallViewWindowManagerInvokeRoutine(KeyEventArgs e, bool isKeyDown)
_isKeyDownInDesktopOrShell |= WindowHelper.IsForegroundWindowBelongToSelf();
}

// call InvokeRoutine only when the KeyDown is valid
// call InvokeRoutine only when:
// (1) user released a key which was pressed in a valid window, or
// (2) user pressed a key in a valid window
if (_isKeyDownInDesktopOrShell)
InvokeRoutine(e.KeyCode, isKeyDown);

// reset variable only when KeyUp
// in case 2, reset the variable
if (!isKeyDown)
_isKeyDownInDesktopOrShell = false;
}

private void InvokeRoutine(Keys key, bool isKeyDown)
{
if (!_validKeys.Contains(key))
{
Debug.WriteLine($"Invalid keypress: key={key},down={isKeyDown}, time={_lastInvalidKeyPressTick}");

_lastInvalidKeyPressTick = DateTime.Now.Ticks;
return;
}

if (DateTime.Now.Ticks - _lastInvalidKeyPressTick < VALID_KEY_PRESS_DELAY)
return;

_lastInvalidKeyPressTick = 0L;

Debug.WriteLine($"InvokeRoutine: key={key},down={isKeyDown}");

if (isKeyDown)
Expand Down Expand Up @@ -110,20 +138,13 @@ private void InstallKeyHook(KeyEventHandler downHandler, KeyEventHandler upHandl
{
_hook = GlobalKeyboardHook.GetInstance();

_hook.HookedKeys.Add(Keys.Enter);
_hook.HookedKeys.Add(Keys.Space);
_hook.HookedKeys.Add(Keys.Escape);
_hook.HookedKeys.Add(Keys.Up);
_hook.HookedKeys.Add(Keys.Down);
_hook.HookedKeys.Add(Keys.Left);
_hook.HookedKeys.Add(Keys.Right);
_hook.KeyDown += downHandler;
_hook.KeyUp += upHandler;
}

internal static BackgroundListener GetInstance()
internal static KeystrokeDispatcher GetInstance()
{
return _instance ?? (_instance = new BackgroundListener());
return _instance ?? (_instance = new KeystrokeDispatcher());
}
}
}
4 changes: 2 additions & 2 deletions QuickLook/QuickLook.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="BackgroundListener.cs" />
<Compile Include="GlobalKeyboardHook.cs" />
<Compile Include="KeystrokeDispatcher.cs" />
<Compile Include="Helpers\GlobalKeyboardHook.cs" />
<Compile Include="ViewerWindow.xaml.cs">
<DependentUpon>ViewerWindow.xaml</DependentUpon>
<SubType>Code</SubType>
Expand Down

0 comments on commit dd02575

Please sign in to comment.