From 1c60b8e586c54d2a3e6969fd1815bcb0ae3dc857 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sat, 27 Nov 2021 13:50:22 -0600 Subject: [PATCH 01/14] Use Function Pointer to handle the low level keyboard proc --- .../Hotkey/GlobalHotkey.cs | 41 ++++++------------- .../Hotkey/InterceptKeys.cs | 6 +-- Flow.Launcher/HotkeyControl.xaml.cs | 2 +- Flow.Launcher/PublicAPIInstance.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 5 files changed, 18 insertions(+), 35 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index e92a93c12..3ea8915f7 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -9,13 +9,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey /// Listens keyboard globally. /// Uses WH_KEYBOARD_LL. /// - 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 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); } diff --git a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs index c45e685f3..7fec3c383 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs @@ -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* 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* lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 2b6e275df..a20537e3a 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -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, diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e90a53fc3..562db43f1 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -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()); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index d7bbaf1cd..9d6b124a0 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -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) From d3d1f6faa75a6a182b847e6f1db0d2f4b51e2015 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sat, 27 Nov 2021 14:26:20 -0600 Subject: [PATCH 02/14] Fix Unexpected Intercept result when multiple plugin register the global hotkey event --- .../Hotkey/GlobalHotkey.cs | 2 +- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 14 ++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 18 ++++++++++++++---- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index 3ea8915f7..afbf58a3e 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -79,7 +79,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey { return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } - return (IntPtr)1; + return (IntPtr)(-1); } public static void Dispose() diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 3abdaf01f..90679fc1c 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -104,7 +104,21 @@ namespace Flow.Launcher.Plugin /// Fired after global keyboard events /// if you want to hook something like Ctrl+R, you should use this event /// + [Obsolete("Unable to Retrieve correct return value")] event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent; + + /// + /// Register a callback for Global Keyboard Event + /// + /// + public void RegisterGlobalKeyboardCallback(Func callback); + + /// + /// Remove a callback for Global Keyboard Event + /// + /// + public void RemoveGlobalKeyboardCallback(Func callback); + /// /// Fuzzy Search the string with the given query. This is the core search mechanism Flow uses diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 562db43f1..0b475f3a5 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -40,7 +40,7 @@ namespace Flow.Launcher _settingsVM = settingsVM; _mainVM = mainVM; _alphabet = alphabet; - GlobalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback; + GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } @@ -190,25 +190,35 @@ namespace Flow.Launcher Arguments = FileName is null ? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) : explorerInfo.FileArgument.Replace("%d", DirectoryPath).Replace("%f", - Path.IsPathRooted(FileName) ? FileName : Path.Combine(DirectoryPath, FileName)) + Path.IsPathRooted(FileName) ? FileName : Path.Combine(DirectoryPath, FileName)) }; explorer.Start(); } public event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent; + private readonly List> _globalKeyboardHandlers = new(); + + public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); + public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback); + #endregion #region Private Methods private bool KListener_hookedKeyboardCallback(KeyEvent keyevent, int vkcode, SpecialKeyState state) { + var continueHook = true; if (GlobalKeyboardEvent != null) { - return GlobalKeyboardEvent((int)keyevent, vkcode, state); + continueHook = GlobalKeyboardEvent((int)keyevent, vkcode, state); + } + foreach (var x in _globalKeyboardHandlers) + { + continueHook &= x((int)keyevent, vkcode, state); } - return true; + return continueHook; } #endregion diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index f9fc239a5..bdc3d69ce 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -300,7 +300,7 @@ namespace Flow.Launcher.Plugin.Shell { this.context = context; _settings = context.API.LoadSettingJsonStorage(); - context.API.GlobalKeyboardEvent += API_GlobalKeyboardEvent; + context.API.RegisterGlobalKeyboardCallback(API_GlobalKeyboardEvent); } bool API_GlobalKeyboardEvent(int keyevent, int vkcode, SpecialKeyState state) From 84fed734b981c210194b55edcf93d1df7e44e61b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 Nov 2021 19:55:35 +1100 Subject: [PATCH 03/14] Shell plugin version bump --- Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json index 6b20eeef9..b71dba2da 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json @@ -4,7 +4,7 @@ "Name": "Shell", "Description": "Provide executing commands from Flow Launcher", "Author": "qianlifeng", - "Version": "1.4.5", + "Version": "1.4.6", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll", From 721e481a0ee8b00db2593a635cd0a4459164c5c5 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sat, 4 Dec 2021 01:58:04 -0600 Subject: [PATCH 04/14] Allow unsafe for release --- .../Flow.Launcher.Infrastructure.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index e01bc1efd..3a3b2d97e 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -32,7 +32,7 @@ TRACE prompt 4 - false + true false From 7d4a9c34946a8e2ffc0fb9b80b7cae0c6e4c3815 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 17:41:02 -0600 Subject: [PATCH 05/14] Reorder modifer --- Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index afbf58a3e..f26348e3d 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -9,7 +9,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey /// Listens keyboard globally. /// Uses WH_KEYBOARD_LL. /// - public unsafe static class GlobalHotkey + public static unsafe class GlobalHotkey { private static readonly IntPtr hookId; From 8f18e2f603ed2567a8384eb7808bb7399769c08f Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 17:47:07 -0600 Subject: [PATCH 06/14] fix an api changed --- Flow.Launcher/ViewModel/MainViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 5583d9e59..506ce8fd8 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -244,8 +244,8 @@ namespace Flow.Launcher.ViewModel autoCompleteText = SelectedResults.SelectedItem.QuerySuggestionText; } - var SpecialKeyState = GlobalHotkey.Instance.CheckModifiers(); - if (SpecialKeyState.ShiftPressed) + var specialKeyState = GlobalHotkey.CheckModifiers(); + if (specialKeyState.ShiftPressed) { autoCompleteText = result.SubTitle; } From 84528ae8a70ed5c4a832ce2a1f9da830808e67e7 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 18:22:41 -0600 Subject: [PATCH 07/14] Use Instance class with static method --- Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index f26348e3d..5f14b7598 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -9,7 +9,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey /// Listens keyboard globally. /// Uses WH_KEYBOARD_LL. /// - public static unsafe class GlobalHotkey + public unsafe class GlobalHotkey : IDisposable { private static readonly IntPtr hookId; @@ -28,7 +28,6 @@ namespace Flow.Launcher.Infrastructure.Hotkey { // Set the hook hookId = InterceptKeys.SetHook(& LowLevelKeyboardProc); - AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose(); } public static SpecialKeyState CheckModifiers() @@ -82,9 +81,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey return (IntPtr)(-1); } - public static void Dispose() + public void Dispose() { InterceptKeys.UnhookWindowsHookEx(hookId); } + + ~GlobalHotkey() + { + Dispose(); + } } } \ No newline at end of file From 5f9036568d53a01b6b0c64be94c3aeb0afad3028 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 21:04:41 -0600 Subject: [PATCH 08/14] Use Safe Delegate Instead --- Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs | 7 ++++--- Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index 5f14b7598..49efc91b8 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -12,8 +12,8 @@ namespace Flow.Launcher.Infrastructure.Hotkey public unsafe class GlobalHotkey : IDisposable { private static readonly IntPtr hookId; - - + + private static InterceptKeys.LowLevelKeyboardProc _hookedKeyboardProc; public delegate bool KeyboardCallback(KeyEvent keyEvent, int vkCode, SpecialKeyState state); internal static Func hookedKeyboardCallback; @@ -26,8 +26,9 @@ namespace Flow.Launcher.Infrastructure.Hotkey static GlobalHotkey() { + _hookedKeyboardProc = LowLevelKeyboardProc; // Set the hook - hookId = InterceptKeys.SetHook(& LowLevelKeyboardProc); + hookId = InterceptKeys.SetHook(_hookedKeyboardProc); } public static SpecialKeyState CheckModifiers() diff --git a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs index 7fec3c383..1203eca42 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs @@ -10,7 +10,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey private const int WH_KEYBOARD_LL = 13; - public static IntPtr SetHook(delegate* proc) + public static IntPtr SetHook(LowLevelKeyboardProc 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, delegate* lpfn, IntPtr hMod, uint dwThreadId); + public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] From 6565b5574667e6624e14cca7e20a125e4319cfa8 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 21:06:33 -0600 Subject: [PATCH 09/14] Use API mainwindow show --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 41c4ae816..de934f3ef 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -340,9 +340,7 @@ namespace Flow.Launcher.Plugin.Shell context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); // show the main window and set focus to the query box - Window mainWindow = Application.Current.MainWindow; - mainWindow.Show(); - mainWindow.Focus(); + context.API.ShowMainWindow(); } public Control CreateSettingPanel() From ec96028f552336b8491d4c2379c40e6767429ddf Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 21:14:01 -0600 Subject: [PATCH 10/14] change query after showing window to make it not selectable --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index de934f3ef..0c539015e 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -337,10 +337,9 @@ namespace Flow.Launcher.Plugin.Shell private void OnWinRPressed() { - context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); - // show the main window and set focus to the query box context.API.ShowMainWindow(); + context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); } public Control CreateSettingPanel() From 21c19b43142ff21151774e5c57910c0b028d25cf Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 21:38:18 -0600 Subject: [PATCH 11/14] Revert "Use Safe Delegate Instead" This reverts commit 5f9036568d53a01b6b0c64be94c3aeb0afad3028. --- Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs | 7 +++---- Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index 49efc91b8..5f14b7598 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -12,8 +12,8 @@ namespace Flow.Launcher.Infrastructure.Hotkey public unsafe class GlobalHotkey : IDisposable { private static readonly IntPtr hookId; - - private static InterceptKeys.LowLevelKeyboardProc _hookedKeyboardProc; + + public delegate bool KeyboardCallback(KeyEvent keyEvent, int vkCode, SpecialKeyState state); internal static Func hookedKeyboardCallback; @@ -26,9 +26,8 @@ namespace Flow.Launcher.Infrastructure.Hotkey static GlobalHotkey() { - _hookedKeyboardProc = LowLevelKeyboardProc; // Set the hook - hookId = InterceptKeys.SetHook(_hookedKeyboardProc); + hookId = InterceptKeys.SetHook(& LowLevelKeyboardProc); } public static SpecialKeyState CheckModifiers() diff --git a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs index 1203eca42..7fec3c383 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs @@ -10,7 +10,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey private const int WH_KEYBOARD_LL = 13; - public static IntPtr SetHook(LowLevelKeyboardProc proc) + public static IntPtr SetHook(delegate* 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* lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] From 055751603d434c52c638379924b6ae72340a0d88 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Sun, 5 Dec 2021 21:49:09 -0600 Subject: [PATCH 12/14] Revise Unsafe Calling Convention --- Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs | 2 +- Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index 5f14b7598..a09185696 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -57,7 +57,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey return state; } - [MethodImpl(MethodImplOptions.NoInlining)] + [UnmanagedCallersOnly] private static IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam) { bool continues = true; diff --git a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs index 7fec3c383..d33bac34c 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs @@ -10,7 +10,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey private const int WH_KEYBOARD_LL = 13; - public static IntPtr SetHook(delegate* proc) + public static IntPtr SetHook(delegate* unmanaged 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, delegate* lpfn, IntPtr hMod, uint dwThreadId); + public static extern IntPtr SetWindowsHookEx(int idHook, delegate* unmanaged lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] From 6fdfbe3263427454ac990bb752bd86a2763e348c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 6 Dec 2021 20:51:52 +1100 Subject: [PATCH 13/14] version bump Shell plugin --- Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json index b71dba2da..2cfcbca2e 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json @@ -4,7 +4,7 @@ "Name": "Shell", "Description": "Provide executing commands from Flow Launcher", "Author": "qianlifeng", - "Version": "1.4.6", + "Version": "1.4.7", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll", From f701c0be9808ebe91cd7f28856c9fab9e21e0431 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Mon, 6 Dec 2021 22:37:18 -0600 Subject: [PATCH 14/14] move allowunsafe property outside build option --- .../Flow.Launcher.Infrastructure.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 3a3b2d97e..40c2cb956 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -11,6 +11,7 @@ false false false + true @@ -21,7 +22,6 @@ DEBUG;TRACE prompt 4 - true false @@ -32,7 +32,6 @@ TRACE prompt 4 - true false