[Launcher] Use a keyboard hook in the runner to invoke the Launcher (#6660)

* Added a keyboard hook to the runner

* Update RootKeyboardHook

* Enable reading the whole JsonObject property

* Renamed RootKeyboardHook to CentralizedKeyboardHook

* Fixed build break, changed callback return type to bool

* Added Hotkey struct which somehow went missing

+ Cherry-pick fixes

* Reorganized the kb hook

* Basic version works

* Various fixes

* Finishing touches

* Fix potential threading issue

* int -> size_t

* Add default initializers to the Hotkey struct

* Added a suggested comment

* Unified a constant

* Use C# classes instead of native calls for sync

* Added a claryfing comment

* Use std::move

* Renamed a method

* Possible fix for compilation errors

* Fix a regression

* Show a message on failure

* Added DISABLE_LOWLEVEL_HOOK support

* Allow running Launcher as standalone

* Rename string constants
This commit is contained in:
Ivan Stošić
2020-09-21 12:44:16 +02:00
committed by GitHub
parent e135153c45
commit b266e336b5
20 changed files with 392 additions and 40 deletions

View File

@@ -4,6 +4,7 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
@@ -30,7 +31,6 @@ namespace PowerLauncher
private const string Unique = "PowerLauncher_Unique_Application_Mutex";
private static bool _disposed;
private static int _powerToysPid;
private Settings _settings;
private MainViewModel _mainVM;
private MainWindow _mainWindow;
@@ -40,15 +40,10 @@ namespace PowerLauncher
private SettingsWatcher _settingsWatcher;
[STAThread]
public static void Main(string[] args)
public static void Main()
{
if (SingleInstance<App>.InitializeAsFirstInstance(Unique))
{
if (args?.Length > 0)
{
_ = int.TryParse(args[0], out _powerToysPid);
}
using (var application = new App())
{
application.InitializeComponent();
@@ -59,17 +54,29 @@ namespace PowerLauncher
private void OnStartup(object sender, StartupEventArgs e)
{
RunnerHelper.WaitForPowerToysRunner(_powerToysPid, () =>
for (int i = 0; i + 1 < e.Args.Length; i++)
{
try
if (e.Args[i] == "-powerToysPid")
{
Dispose();
int powerToysPid;
if (int.TryParse(e.Args[i + 1], out powerToysPid))
{
RunnerHelper.WaitForPowerToysRunner(powerToysPid, () =>
{
try
{
Dispose();
}
finally
{
Environment.Exit(0);
}
});
}
break;
}
finally
{
Environment.Exit(0);
}
});
}
var bootTime = new System.Diagnostics.Stopwatch();
bootTime.Start();
@@ -85,6 +92,7 @@ namespace PowerLauncher
_settingsVM = new SettingWindowViewModel();
_settings = _settingsVM.Settings;
_settings.UsePowerToysRunnerKeyboardHook = e.Args.Contains("--centralized-kb-hook");
_alphabet.Initialize(_settings);
_stringMatcher = new StringMatcher(_alphabet);

View File

@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Windows;
namespace PowerLauncher.Helper
{
public static class NativeEventWaiter
{
public static void WaitForEventLoop(string eventName, Action callback)
{
new Thread(() =>
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
while (true)
{
if (eventHandle.WaitOne())
{
Application.Current.Dispatcher.Invoke(callback);
}
}
}).Start();
}
}
}

View File

@@ -55,7 +55,6 @@ namespace PowerLauncher.ViewModel
public MainViewModel(Settings settings)
{
HotkeyManager = new HotkeyManager();
_saved = false;
_queryTextBeforeLeaveResults = string.Empty;
_currentQuery = _emptyQuery;
@@ -78,27 +77,36 @@ namespace PowerLauncher.ViewModel
InitializeKeyCommands();
RegisterResultsUpdatedEvent();
_settings.PropertyChanged += (s, e) =>
if (settings != null && settings.UsePowerToysRunnerKeyboardHook)
{
if (e.PropertyName == nameof(Settings.Hotkey))
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey);
_hotkeyHandle = 0;
}
else
{
HotkeyManager = new HotkeyManager();
_settings.PropertyChanged += (s, e) =>
{
Application.Current.Dispatcher.Invoke(() =>
if (e.PropertyName == nameof(Settings.Hotkey))
{
if (!string.IsNullOrEmpty(_settings.PreviousHotkey))
Application.Current.Dispatcher.Invoke(() =>
{
HotkeyManager.UnregisterHotkey(_hotkeyHandle);
}
if (!string.IsNullOrEmpty(_settings.PreviousHotkey))
{
HotkeyManager.UnregisterHotkey(_hotkeyHandle);
}
if (!string.IsNullOrEmpty(_settings.Hotkey))
{
SetHotkey(_settings.Hotkey, OnHotkey);
}
});
}
};
if (!string.IsNullOrEmpty(_settings.Hotkey))
{
SetHotkey(_settings.Hotkey, OnHotkey);
}
});
}
};
SetHotkey(_settings.Hotkey, OnHotkey);
SetCustomPluginHotkey();
SetHotkey(_settings.Hotkey, OnHotkey);
SetCustomPluginHotkey();
}
}
private void RegisterResultsUpdatedEvent()