[PT Run] Add setting to use centralized keyboard hook (#13557)

* [PT Run] Add setting to use centralized hook

* Add UI separator
This commit is contained in:
Jaime Bernardo
2021-10-01 14:59:52 +01:00
committed by GitHub
parent 55054f1fa6
commit 84b2ae3e8f
11 changed files with 124 additions and 29 deletions

View File

@@ -171,6 +171,10 @@ public
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT); return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT);
} }
static String ^ PowerLauncherCentralizedHookSharedEvent() {
return gcnew String(CommonSharedConstants::POWER_LAUNCHER_CENTRALIZED_HOOK_SHARED_EVENT);
}
static String ^ RunSendSettingsTelemetryEvent() { static String ^ RunSendSettingsTelemetryEvent() {
return gcnew String(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT); return gcnew String(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT);
} }

View File

@@ -15,6 +15,8 @@ namespace CommonSharedConstants
// Path to the event used by PowerLauncher // 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_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_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"; const wchar_t RUN_EXIT_EVENT[] = L"Local\\PowerToysRunExitEvent-3e38e49d-a762-4ef1-88f2-fd4bc7481516";

View File

@@ -25,6 +25,7 @@ namespace
const wchar_t JSON_KEY_SHIFT[] = L"shift"; const wchar_t JSON_KEY_SHIFT[] = L"shift";
const wchar_t JSON_KEY_CODE[] = L"code"; const wchar_t JSON_KEY_CODE[] = L"code";
const wchar_t JSON_KEY_OPEN_POWERLAUNCHER[] = L"open_powerlauncher"; 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) BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
@@ -73,11 +74,15 @@ private:
// Hotkey to invoke the module // Hotkey to invoke the module
Hotkey m_hotkey = { .key = 0 }; 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 // Helper function to extract the hotkey from the settings
void parse_hotkey(PowerToysSettings::PowerToyValues& settings); void parse_hotkey(PowerToysSettings::PowerToyValues& settings);
// Handle to event used to invoke the Runner // Handle to event used to invoke the Runner
HANDLE m_hEvent; HANDLE m_hEvent;
HANDLE m_hCentralizedKeyboardHookEvent;
HANDLE send_telemetry_event; HANDLE send_telemetry_event;
@@ -115,6 +120,8 @@ public:
init_settings(); init_settings();
m_hEvent = CreateDefaultEvent(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT); 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); send_telemetry_event = CreateDefaultEvent(CommonSharedConstants::RUN_SEND_SETTINGS_TELEMETRY_EVENT);
}; };
@@ -199,7 +206,7 @@ public:
{ {
Logger::info("Microsoft_Launcher::enable()"); Logger::info("Microsoft_Launcher::enable()");
m_enabled = true; m_enabled = true;
ResetEvent(m_hEvent); ResetEvent(m_hCentralizedKeyboardHookEvent);
ResetEvent(send_telemetry_event); ResetEvent(send_telemetry_event);
unsigned long powertoys_pid = GetCurrentProcessId(); unsigned long powertoys_pid = GetCurrentProcessId();
@@ -210,7 +217,7 @@ public:
std::wstring executable_args; std::wstring executable_args;
executable_args += L" -powerToysPid "; executable_args += L" -powerToysPid ";
executable_args += std::to_wstring(powertoys_pid); executable_args += std::to_wstring(powertoys_pid);
executable_args += L" --centralized-kb-hook"; executable_args += L" --started-from-runner";
SHELLEXECUTEINFOW sei{ sizeof(sei) }; SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
@@ -234,7 +241,7 @@ public:
std::wstring runExecutablePath = get_module_folderpath(); std::wstring runExecutablePath = get_module_folderpath();
std::wstring params; std::wstring params;
params += L" -powerToysPid " + std::to_wstring(powertoys_pid) + L" "; 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"; runExecutablePath += L"\\modules\\launcher\\PowerLauncher.exe";
if (RunNonElevatedEx(runExecutablePath, params)) if (RunNonElevatedEx(runExecutablePath, params))
{ {
@@ -268,6 +275,7 @@ public:
TerminateRunningInstance(); TerminateRunningInstance();
processStarted = false; processStarted = false;
ResetEvent(m_hEvent); ResetEvent(m_hEvent);
ResetEvent(m_hCentralizedKeyboardHookEvent);
ResetEvent(send_telemetry_event); ResetEvent(send_telemetry_event);
} }
@@ -310,13 +318,13 @@ public:
enable(); 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.
* 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.*/
* This means we can't return true so that the hotkey can propagate to PowerToys Run. if (m_use_centralized_keyboard_hook) {
Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT"); Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT");
SetEvent(m_hEvent); SetEvent(m_hCentralizedKeyboardHookEvent);
return true; return true;
*/ }
} }
return false; return false;
@@ -360,6 +368,7 @@ void Microsoft_Launcher::init_settings()
void Microsoft_Launcher::parse_hotkey(PowerToysSettings::PowerToyValues& settings) void Microsoft_Launcher::parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{ {
m_use_centralized_keyboard_hook = false;
auto settingsObject = settings.get_raw_json(); auto settingsObject = settings.get_raw_json();
if (settingsObject.GetView().Size()) 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"); 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 else
{ {

View File

@@ -112,7 +112,7 @@ namespace PowerLauncher
_settingsVM = new SettingWindowViewModel(); _settingsVM = new SettingWindowViewModel();
_settings = _settingsVM.Settings; _settings = _settingsVM.Settings;
_settings.UsePowerToysRunnerKeyboardHook = e.Args.Contains("--centralized-kb-hook"); _settings.StartedFromPowerToysRunner = e.Args.Contains("--started-from-runner");
_stringMatcher = new StringMatcher(); _stringMatcher = new StringMatcher();
StringMatcher.Instance = _stringMatcher; StringMatcher.Instance = _stringMatcher;

View File

@@ -100,6 +100,11 @@ namespace PowerLauncher
_settings.Hotkey = openPowerlauncher; _settings.Hotkey = openPowerlauncher;
} }
if (_settings.UseCentralizedKeyboardHook != overloadSettings.Properties.UseCentralizedKeyboardHook)
{
_settings.UseCentralizedKeyboardHook = overloadSettings.Properties.UseCentralizedKeyboardHook;
}
if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults) if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults)
{ {
_settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults; _settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults;

View File

@@ -88,9 +88,15 @@ namespace PowerLauncher.ViewModel
// Allow OOBE to call PowerToys Run. // Allow OOBE to call PowerToys Run.
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey); 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) => _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(() => Application.Current.Dispatcher.Invoke(() =>
{ {
@@ -741,26 +747,33 @@ namespace PowerLauncher.ViewModel
Log.Info("Unregistering previous low level key handler", GetType()); Log.Info("Unregistering previous low level key handler", GetType());
} }
_globalHotKeyVK = hotkey.Key; if (_settings.StartedFromPowerToysRunner && _settings.UseCentralizedKeyboardHook)
_globalHotKeyFSModifiers = VKModifiersFromHotKey(hotkey);
if (NativeMethods.RegisterHotKey(hwnd, _globalHotKeyId, _globalHotKeyFSModifiers, _globalHotKeyVK))
{ {
// Using global hotkey registered through the native RegisterHotKey method. Log.Info("Using the Centralized Keyboard Hook for the HotKey.", GetType());
_globalHotKeyHwnd = hwnd;
_usingGlobalHotKey = true;
Log.Info("Registered global hotkey", GetType());
return;
} }
else
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(); _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 #pragma warning disable CA1031 // Do not catch general exception types
catch (Exception) catch (Exception)
@@ -817,6 +830,14 @@ namespace PowerLauncher.ViewModel
} }
*/ */
private void OnCentralizedKeyboardHookHotKey()
{
if (_settings.StartedFromPowerToysRunner && _settings.UseCentralizedKeyboardHook)
{
OnHotkey();
}
}
private void OnHotkey() private void OnHotkey()
{ {
Application.Current.Dispatcher.Invoke(() => Application.Current.Dispatcher.Invoke(() =>

View File

@@ -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 string Language { get; set; } = "en";
public Theme Theme { get; set; } = Theme.System; public Theme Theme { get; set; } = Theme.System;
@@ -172,7 +191,7 @@ namespace Wox.Infrastructure.UserSettings
public bool IgnoreHotkeysOnFullscreen { get; set; } public bool IgnoreHotkeysOnFullscreen { get; set; }
public bool UsePowerToysRunnerKeyboardHook { get; set; } public bool StartedFromPowerToysRunner { get; set; }
public HttpProxy Proxy { get; set; } = new HttpProxy(); public HttpProxy Proxy { get; set; } = new HttpProxy();

View File

@@ -48,6 +48,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("startupPosition")] [JsonPropertyName("startupPosition")]
public StartupPosition Position { get; set; } public StartupPosition Position { get; set; }
[JsonPropertyName("use_centralized_keyboard_hook")]
public bool UseCentralizedKeyboardHook { get; set; }
public PowerLauncherProperties() public PowerLauncherProperties()
{ {
OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32); OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32);
@@ -61,6 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
MaximumNumberOfResults = 4; MaximumNumberOfResults = 4;
Theme = Theme.System; Theme = Theme.System;
Position = StartupPosition.Cursor; Position = StartupPosition.Cursor;
UseCentralizedKeyboardHook = false;
} }
} }
} }

View File

@@ -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 public HotkeySettings OpenFileLocation
{ {
get get

View File

@@ -401,6 +401,9 @@
<data name="PowerLauncher_IgnoreHotkeysInFullScreen.Content" xml:space="preserve"> <data name="PowerLauncher_IgnoreHotkeysInFullScreen.Content" xml:space="preserve">
<value>Ignore shortcuts in fullscreen mode</value> <value>Ignore shortcuts in fullscreen mode</value>
</data> </data>
<data name="PowerLauncher_UseCentralizedKeyboardHook.Content" xml:space="preserve">
<value>Use centralized keyboard hook (try it if there are issues with the shortcut)</value>
</data>
<data name="PowerLauncher_ClearInputOnLaunch.Content" xml:space="preserve"> <data name="PowerLauncher_ClearInputOnLaunch.Content" xml:space="preserve">
<value>Clear the previous query on launch</value> <value>Clear the previous query on launch</value>
</data> </data>

View File

@@ -45,6 +45,8 @@
</controls:SettingExpander.Header> </controls:SettingExpander.Header>
<controls:SettingExpander.Content> <controls:SettingExpander.Content>
<StackPanel> <StackPanel>
<CheckBox x:Uid="PowerLauncher_UseCentralizedKeyboardHook" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.UseCentralizedKeyboardHook}" Margin="{StaticResource ExpanderSettingMargin}" />
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="PowerLauncher_IgnoreHotkeysInFullScreen" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.IgnoreHotkeysInFullScreen}" Margin="{StaticResource ExpanderSettingMargin}" /> <CheckBox x:Uid="PowerLauncher_IgnoreHotkeysInFullScreen" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.IgnoreHotkeysInFullScreen}" Margin="{StaticResource ExpanderSettingMargin}" />
</StackPanel> </StackPanel>
</controls:SettingExpander.Content> </controls:SettingExpander.Content>