From 84b2ae3e8f52b7d5d227bb63e470c824e3aa0910 Mon Sep 17 00:00:00 2001 From: Jaime Bernardo Date: Fri, 1 Oct 2021 14:59:52 +0100 Subject: [PATCH] [PT Run] Add setting to use centralized keyboard hook (#13557) * [PT Run] Add setting to use centralized hook * Add UI separator --- src/common/interop/interop.cpp | 4 ++ src/common/interop/shared_constants.h | 2 + .../launcher/Microsoft.Launcher/dllmain.cpp | 38 +++++++++---- .../launcher/PowerLauncher/App.xaml.cs | 2 +- .../launcher/PowerLauncher/SettingsReader.cs | 5 ++ .../PowerLauncher/ViewModel/MainViewModel.cs | 55 +++++++++++++------ .../UserSettings/PowerToysRunSettings.cs | 21 ++++++- .../PowerLauncherProperties.cs | 4 ++ .../ViewModels/PowerLauncherViewModel.cs | 17 ++++++ .../Strings/en-us/Resources.resw | 3 + .../Views/PowerLauncherPage.xaml | 2 + 11 files changed, 124 insertions(+), 29 deletions(-) diff --git a/src/common/interop/interop.cpp b/src/common/interop/interop.cpp index 6a6169d8d2..f616c0c1de 100644 --- a/src/common/interop/interop.cpp +++ b/src/common/interop/interop.cpp @@ -171,6 +171,10 @@ public return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT); } + static String ^ PowerLauncherCentralizedHookSharedEvent() { + return gcnew String(CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT); + } + static String ^ RunSendSettingsTelemetryEvent() { return gcnew String(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT); } diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h index 8547703c92..0cb38f97f9 100644 --- a/src/common/interop/shared_constants.h +++ b/src/common/interop/shared_constants.h @@ -15,6 +15,8 @@ namespace CommonSharedConstants // Path to the event used by PowerLauncher const wchar_t POWER_LAUNCHER_SHARED_EVENT[] = L"Local\\PowerToysRunInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab"; + const wchar_t POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT[] = L"Local\\PowerToysRunCentralizedHookInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab"; + const wchar_t RUN_SEND_SETTINGS_TELEMETRY_EVENT[] = L"Local\\PowerToysRunInvokeEvent-638ec522-0018-4b96-837d-6bd88e06f0d6"; const wchar_t RUN_EXIT_EVENT[] = L"Local\\PowerToysRunExitEvent-3e38e49d-a762-4ef1-88f2-fd4bc7481516"; diff --git a/src/modules/launcher/Microsoft.Launcher/dllmain.cpp b/src/modules/launcher/Microsoft.Launcher/dllmain.cpp index 7bc0a625f1..4981307650 100644 --- a/src/modules/launcher/Microsoft.Launcher/dllmain.cpp +++ b/src/modules/launcher/Microsoft.Launcher/dllmain.cpp @@ -25,6 +25,7 @@ namespace const wchar_t JSON_KEY_SHIFT[] = L"shift"; const wchar_t JSON_KEY_CODE[] = L"code"; const wchar_t JSON_KEY_OPEN_POWERLAUNCHER[] = L"open_powerlauncher"; + const wchar_t JSON_KEY_USE_CENTRALIZED_KEYBOARD_HOOK[] = L"use_centralized_keyboard_hook"; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) @@ -73,11 +74,15 @@ private: // Hotkey to invoke the module Hotkey m_hotkey = { .key = 0 }; + // If the centralized keyboard hook should be used to activate PowerToys Run + bool m_use_centralized_keyboard_hook = false; + // Helper function to extract the hotkey from the settings void parse_hotkey(PowerToysSettings::PowerToyValues& settings); // Handle to event used to invoke the Runner HANDLE m_hEvent; + HANDLE m_hCentralizedKeyboardHookEvent; HANDLE send_telemetry_event; @@ -115,6 +120,8 @@ public: init_settings(); m_hEvent = CreateDefaultEvent(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT); + m_hCentralizedKeyboardHookEvent = CreateDefaultEvent(CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT); + send_telemetry_event = CreateDefaultEvent(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT); }; @@ -199,7 +206,7 @@ public: { Logger::info("Microsoft_Launcher::enable()"); m_enabled = true; - ResetEvent(m_hEvent); + ResetEvent(m_hCentralizedKeyboardHookEvent); ResetEvent(send_telemetry_event); unsigned long powertoys_pid = GetCurrentProcessId(); @@ -210,7 +217,7 @@ public: std::wstring executable_args; executable_args += L" -powerToysPid "; executable_args += std::to_wstring(powertoys_pid); - executable_args += L" --centralized-kb-hook"; + executable_args += L" --started-from-runner"; SHELLEXECUTEINFOW sei{ sizeof(sei) }; sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; @@ -234,7 +241,7 @@ public: std::wstring runExecutablePath = get_module_folderpath(); std::wstring params; params += L" -powerToysPid " + std::to_wstring(powertoys_pid) + L" "; - params += L"--centralized-kb-hook "; + params += L"--started-from-runner "; runExecutablePath += L"\\modules\\launcher\\PowerLauncher.exe"; if (RunNonElevatedEx(runExecutablePath, params)) { @@ -268,6 +275,7 @@ public: TerminateRunningInstance(); processStarted = false; ResetEvent(m_hEvent); + ResetEvent(m_hCentralizedKeyboardHookEvent); ResetEvent(send_telemetry_event); } @@ -310,13 +318,13 @@ public: enable(); } - /* Before we used the central keyboard hook to trigger PowerToys Run. - * Now, PowerToys Run uses a global hotkey so that it can get focus. - * This means we can't return true so that the hotkey can propagate to PowerToys Run. - Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT"); - SetEvent(m_hEvent); - return true; - */ + /* Now, PowerToys Run uses a global hotkey so that it can get focus. + * Activate it with the centralized keyboard hook only if the setting is on.*/ + if (m_use_centralized_keyboard_hook) { + Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT"); + SetEvent(m_hCentralizedKeyboardHookEvent); + return true; + } } return false; @@ -360,6 +368,7 @@ void Microsoft_Launcher::init_settings() void Microsoft_Launcher::parse_hotkey(PowerToysSettings::PowerToyValues& settings) { + m_use_centralized_keyboard_hook = false; auto settingsObject = settings.get_raw_json(); if (settingsObject.GetView().Size()) { @@ -376,6 +385,15 @@ void Microsoft_Launcher::parse_hotkey(PowerToysSettings::PowerToyValues& setting { Logger::error("Failed to initialize PT Run start shortcut"); } + try + { + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES); + m_use_centralized_keyboard_hook = (bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_USE_CENTRALIZED_KEYBOARD_HOOK); + } + catch (...) + { + Logger::warn("Failed to get centralized keyboard hook setting"); + } } else { diff --git a/src/modules/launcher/PowerLauncher/App.xaml.cs b/src/modules/launcher/PowerLauncher/App.xaml.cs index 801df1db24..d7491a6bfa 100644 --- a/src/modules/launcher/PowerLauncher/App.xaml.cs +++ b/src/modules/launcher/PowerLauncher/App.xaml.cs @@ -112,7 +112,7 @@ namespace PowerLauncher _settingsVM = new SettingWindowViewModel(); _settings = _settingsVM.Settings; - _settings.UsePowerToysRunnerKeyboardHook = e.Args.Contains("--centralized-kb-hook"); + _settings.StartedFromPowerToysRunner = e.Args.Contains("--started-from-runner"); _stringMatcher = new StringMatcher(); StringMatcher.Instance = _stringMatcher; diff --git a/src/modules/launcher/PowerLauncher/SettingsReader.cs b/src/modules/launcher/PowerLauncher/SettingsReader.cs index 368c707f81..3ddde63316 100644 --- a/src/modules/launcher/PowerLauncher/SettingsReader.cs +++ b/src/modules/launcher/PowerLauncher/SettingsReader.cs @@ -100,6 +100,11 @@ namespace PowerLauncher _settings.Hotkey = openPowerlauncher; } + if (_settings.UseCentralizedKeyboardHook != overloadSettings.Properties.UseCentralizedKeyboardHook) + { + _settings.UseCentralizedKeyboardHook = overloadSettings.Properties.UseCentralizedKeyboardHook; + } + if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults) { _settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults; diff --git a/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs b/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs index bb92343299..9c89d1af3c 100644 --- a/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs +++ b/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs @@ -88,9 +88,15 @@ namespace PowerLauncher.ViewModel // Allow OOBE to call PowerToys Run. NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey); + if (_settings.StartedFromPowerToysRunner) + { + // Allow runner to call PowerToys Run from the centralized keyboard hook. + NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherCentralizedHookSharedEvent(), OnCentralizedKeyboardHookHotKey); + } + _settings.PropertyChanged += (s, e) => { - if (e.PropertyName == nameof(PowerToysRunSettings.Hotkey)) + if (e.PropertyName == nameof(PowerToysRunSettings.Hotkey) || e.PropertyName == nameof(PowerToysRunSettings.UseCentralizedKeyboardHook)) { Application.Current.Dispatcher.Invoke(() => { @@ -741,26 +747,33 @@ namespace PowerLauncher.ViewModel Log.Info("Unregistering previous low level key handler", GetType()); } - _globalHotKeyVK = hotkey.Key; - _globalHotKeyFSModifiers = VKModifiersFromHotKey(hotkey); - if (NativeMethods.RegisterHotKey(hwnd, _globalHotKeyId, _globalHotKeyFSModifiers, _globalHotKeyVK)) + if (_settings.StartedFromPowerToysRunner && _settings.UseCentralizedKeyboardHook) { - // Using global hotkey registered through the native RegisterHotKey method. - _globalHotKeyHwnd = hwnd; - _usingGlobalHotKey = true; - Log.Info("Registered global hotkey", GetType()); - return; + Log.Info("Using the Centralized Keyboard Hook for the HotKey.", GetType()); } - - Log.Warn("Registering global shortcut failed. Will use low-level keyboard hook instead.", GetType()); - - // Using fallback low-level keyboard hook through HotkeyManager. - if (HotkeyManager == null) + else { - HotkeyManager = new HotkeyManager(); - } + _globalHotKeyVK = hotkey.Key; + _globalHotKeyFSModifiers = VKModifiersFromHotKey(hotkey); + if (NativeMethods.RegisterHotKey(hwnd, _globalHotKeyId, _globalHotKeyFSModifiers, _globalHotKeyVK)) + { + // Using global hotkey registered through the native RegisterHotKey method. + _globalHotKeyHwnd = hwnd; + _usingGlobalHotKey = true; + Log.Info("Registered global hotkey", GetType()); + return; + } - _hotkeyHandle = HotkeyManager.RegisterHotkey(hotkey, action); + Log.Warn("Registering global shortcut failed. Will use low-level keyboard hook instead.", GetType()); + + // Using fallback low-level keyboard hook through HotkeyManager. + if (HotkeyManager == null) + { + HotkeyManager = new HotkeyManager(); + } + + _hotkeyHandle = HotkeyManager.RegisterHotkey(hotkey, action); + } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception) @@ -817,6 +830,14 @@ namespace PowerLauncher.ViewModel } */ + private void OnCentralizedKeyboardHookHotKey() + { + if (_settings.StartedFromPowerToysRunner && _settings.UseCentralizedKeyboardHook) + { + OnHotkey(); + } + } + private void OnHotkey() { Application.Current.Dispatcher.Invoke(() => diff --git a/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs b/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs index ed9234699c..5ee3d9da0f 100644 --- a/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs +++ b/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs @@ -42,6 +42,25 @@ namespace Wox.Infrastructure.UserSettings } } + private bool _useCentralizedKeyboardHook; + + public bool UseCentralizedKeyboardHook + { + get + { + return _useCentralizedKeyboardHook; + } + + set + { + if (_useCentralizedKeyboardHook != value) + { + _useCentralizedKeyboardHook = value; + OnPropertyChanged(nameof(UseCentralizedKeyboardHook)); + } + } + } + public string Language { get; set; } = "en"; public Theme Theme { get; set; } = Theme.System; @@ -172,7 +191,7 @@ namespace Wox.Infrastructure.UserSettings public bool IgnoreHotkeysOnFullscreen { get; set; } - public bool UsePowerToysRunnerKeyboardHook { get; set; } + public bool StartedFromPowerToysRunner { get; set; } public HttpProxy Proxy { get; set; } = new HttpProxy(); diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs index d4191871aa..aa42cd5e6a 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs @@ -48,6 +48,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("startupPosition")] public StartupPosition Position { get; set; } + [JsonPropertyName("use_centralized_keyboard_hook")] + public bool UseCentralizedKeyboardHook { get; set; } + public PowerLauncherProperties() { OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32); @@ -61,6 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library MaximumNumberOfResults = 4; Theme = Theme.System; Position = StartupPosition.Cursor; + UseCentralizedKeyboardHook = false; } } } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs index f226efda48..c23ed10a6e 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs @@ -275,6 +275,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels } } + public bool UseCentralizedKeyboardHook + { + get + { + return settings.Properties.UseCentralizedKeyboardHook; + } + + set + { + if (settings.Properties.UseCentralizedKeyboardHook != value) + { + settings.Properties.UseCentralizedKeyboardHook = value; + UpdateSettings(); + } + } + } + public HotkeySettings OpenFileLocation { get diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw index 7846c92c72..20b1e2d44f 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw @@ -401,6 +401,9 @@ Ignore shortcuts in fullscreen mode + + Use centralized keyboard hook (try it if there are issues with the shortcut) + Clear the previous query on launch diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml index f3b77683de..32256fdacf 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml @@ -45,6 +45,8 @@ + +