mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Use Function Pointer to handle the low level keyboard proc
This commit is contained in:
parent
b51e5d2583
commit
1c60b8e586
5 changed files with 18 additions and 35 deletions
|
|
@ -9,13 +9,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey
|
|||
/// Listens keyboard globally.
|
||||
/// <remarks>Uses WH_KEYBOARD_LL.</remarks>
|
||||
/// </summary>
|
||||
public class GlobalHotkey : IDisposable
|
||||
public unsafe static class GlobalHotkey
|
||||
{
|
||||
private static GlobalHotkey instance;
|
||||
private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
|
||||
private IntPtr hookId = IntPtr.Zero;
|
||||
private static readonly IntPtr hookId;
|
||||
|
||||
|
||||
|
||||
public delegate bool KeyboardCallback(KeyEvent keyEvent, int vkCode, SpecialKeyState state);
|
||||
public event KeyboardCallback hookedKeyboardCallback;
|
||||
internal static Func<KeyEvent, int, SpecialKeyState, bool> hookedKeyboardCallback;
|
||||
|
||||
//Modifier key constants
|
||||
private const int VK_SHIFT = 0x10;
|
||||
|
|
@ -23,27 +24,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey
|
|||
private const int VK_ALT = 0x12;
|
||||
private const int VK_WIN = 91;
|
||||
|
||||
public static GlobalHotkey Instance
|
||||
static GlobalHotkey()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new GlobalHotkey();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalHotkey()
|
||||
{
|
||||
// We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
|
||||
hookedLowLevelKeyboardProc = LowLevelKeyboardProc;
|
||||
// Set the hook
|
||||
hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc);
|
||||
hookId = InterceptKeys.SetHook(& LowLevelKeyboardProc);
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose();
|
||||
}
|
||||
|
||||
public SpecialKeyState CheckModifiers()
|
||||
public static SpecialKeyState CheckModifiers()
|
||||
{
|
||||
SpecialKeyState state = new SpecialKeyState();
|
||||
if ((InterceptKeys.GetKeyState(VK_SHIFT) & 0x8000) != 0)
|
||||
|
|
@ -71,7 +59,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
|
||||
private static IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
bool continues = true;
|
||||
|
||||
|
|
@ -94,12 +82,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
|
|||
return (IntPtr)1;
|
||||
}
|
||||
|
||||
~GlobalHotkey()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public static void Dispose()
|
||||
{
|
||||
InterceptKeys.UnhookWindowsHookEx(hookId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace Flow.Launcher.Infrastructure.Hotkey
|
||||
{
|
||||
internal static class InterceptKeys
|
||||
internal static unsafe class InterceptKeys
|
||||
{
|
||||
public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
|
||||
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
|
||||
public static IntPtr SetHook(LowLevelKeyboardProc proc)
|
||||
public static IntPtr SetHook(delegate*<int, UIntPtr, IntPtr, IntPtr> proc)
|
||||
{
|
||||
using (Process curProcess = Process.GetCurrentProcess())
|
||||
using (ProcessModule curModule = curProcess.MainModule)
|
||||
|
|
@ -20,7 +20,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
|
|||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
|
||||
public static extern IntPtr SetWindowsHookEx(int idHook, delegate*<int, UIntPtr, IntPtr, IntPtr> lpfn, IntPtr hMod, uint dwThreadId);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace Flow.Launcher
|
|||
//when alt is pressed, the real key should be e.SystemKey
|
||||
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
|
||||
|
||||
SpecialKeyState specialKeyState = GlobalHotkey.Instance.CheckModifiers();
|
||||
SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers();
|
||||
|
||||
var hotkeyModel = new HotkeyModel(
|
||||
specialKeyState.AltPressed,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace Flow.Launcher
|
|||
_settingsVM = settingsVM;
|
||||
_mainVM = mainVM;
|
||||
_alphabet = alphabet;
|
||||
GlobalHotkey.Instance.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||
GlobalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||
WebRequest.RegisterPrefix("data", new DataWebRequestFactory());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ namespace Flow.Launcher.ViewModel
|
|||
{
|
||||
bool hideWindow = result.Action != null && result.Action(new ActionContext
|
||||
{
|
||||
SpecialKeyState = GlobalHotkey.Instance.CheckModifiers()
|
||||
SpecialKeyState = GlobalHotkey.CheckModifiers()
|
||||
});
|
||||
|
||||
if (hideWindow)
|
||||
|
|
|
|||
Loading…
Reference in a new issue