mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-12 04:33:10 +08:00
[PowerToys Run] Use global HotKey instead of low level keyboard hook (#13114)
* [PowerToys Run] Register global HotKey Using low level keyboard hooks caused focus issues when invoking PowerToys Run. Using a global HotKey solves this issue. * Properly unregister hotkey on dispose * fix spellchecker errors
This commit is contained in:
parent
2c58bdbfb2
commit
5963294b04
3
.github/actions/spell-check/expect.txt
vendored
3
.github/actions/spell-check/expect.txt
vendored
@ -652,6 +652,7 @@ FOF
|
|||||||
FOFX
|
FOFX
|
||||||
FOLDERID
|
FOLDERID
|
||||||
folderpath
|
folderpath
|
||||||
|
FORCEMINIMIZE
|
||||||
FORCEOFFLINE
|
FORCEOFFLINE
|
||||||
foreach
|
foreach
|
||||||
formatetc
|
formatetc
|
||||||
@ -1891,7 +1892,9 @@ SHOWDEFAULT
|
|||||||
SHOWELEVATIONPROMPT
|
SHOWELEVATIONPROMPT
|
||||||
SHOWMAXIMIZED
|
SHOWMAXIMIZED
|
||||||
SHOWMINIMIZED
|
SHOWMINIMIZED
|
||||||
|
SHOWMINNOACTIVE
|
||||||
SHOWNA
|
SHOWNA
|
||||||
|
SHOWNOACTIVATE
|
||||||
SHOWNORMAL
|
SHOWNORMAL
|
||||||
SHOWWINDOW
|
SHOWWINDOW
|
||||||
shtypes
|
shtypes
|
||||||
|
@ -310,9 +310,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.
|
||||||
|
* This means we can't return true so that the hotkey can propagate to PowerToys Run.
|
||||||
Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT");
|
Logger::trace("Set POWER_LAUNCHER_SHARED_EVENT");
|
||||||
SetEvent(m_hEvent);
|
SetEvent(m_hEvent);
|
||||||
return true;
|
return true;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -138,7 +138,6 @@ namespace PowerLauncher
|
|||||||
bootTime.Stop();
|
bootTime.Stop();
|
||||||
|
|
||||||
Log.Info(textToLog.ToString(), GetType());
|
Log.Info(textToLog.ToString(), GetType());
|
||||||
_mainVM.RegisterHotkey();
|
|
||||||
PowerToysTelemetry.Log.WriteEvent(new LauncherBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
|
PowerToysTelemetry.Log.WriteEvent(new LauncherBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
|
||||||
|
|
||||||
// [Conditional("RELEASE")]
|
// [Conditional("RELEASE")]
|
||||||
|
@ -8,7 +8,6 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
using Wox.Plugin.Logger;
|
using Wox.Plugin.Logger;
|
||||||
@ -17,32 +16,11 @@ namespace PowerLauncher.Helper
|
|||||||
{
|
{
|
||||||
public static class EnvironmentHelper
|
public static class EnvironmentHelper
|
||||||
{
|
{
|
||||||
private const string EnvironmentChangeType = "Environment";
|
|
||||||
private const string Username = "USERNAME";
|
private const string Username = "USERNAME";
|
||||||
private const string ProcessorArchitecture = "PROCESSOR_ARCHITECTURE";
|
private const string ProcessorArchitecture = "PROCESSOR_ARCHITECTURE";
|
||||||
private const string Path = "PATH";
|
private const string Path = "PATH";
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Params are required for delegate signature requirements.")]
|
internal static void UpdateEnvironment()
|
||||||
public static IntPtr ProcessWindowMessages(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
|
|
||||||
{
|
|
||||||
switch ((WM)msg)
|
|
||||||
{
|
|
||||||
case WM.SETTINGCHANGE:
|
|
||||||
string changeType = Marshal.PtrToStringUni(lparam);
|
|
||||||
if (changeType == EnvironmentChangeType)
|
|
||||||
{
|
|
||||||
Log.Info("Reload environment", typeof(EnvironmentHelper));
|
|
||||||
UpdateEnvironment();
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UpdateEnvironment()
|
|
||||||
{
|
{
|
||||||
// Username and process architecture are set by the machine vars, this
|
// Username and process architecture are set by the machine vars, this
|
||||||
// may lead to incorrect values so save off the current values to restore.
|
// may lead to incorrect values so save off the current values to restore.
|
||||||
|
@ -31,6 +31,18 @@ namespace PowerLauncher.Helper
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
internal static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||||
|
|
||||||
@ -86,6 +98,34 @@ namespace PowerLauncher.Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
|
||||||
|
internal enum HOTKEY_MODIFIERS : uint
|
||||||
|
{
|
||||||
|
ALT = 0x0001,
|
||||||
|
CONTROL = 0x0002,
|
||||||
|
SHIFT = 0x0004,
|
||||||
|
WIN = 0x0008,
|
||||||
|
NOREPEAT = 0x4000,
|
||||||
|
CHECK_FLAGS = 0x000F, // modifiers to compare between keys.
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
|
||||||
|
internal enum SW : int
|
||||||
|
{
|
||||||
|
HIDE = 0x0000,
|
||||||
|
SHOWNORMAL = 0x0001,
|
||||||
|
SHOWMINIMIZED = 0x0002,
|
||||||
|
SHOWMAXIMIZED = 0x0003,
|
||||||
|
SHOWNOACTIVATE = 0x0004,
|
||||||
|
SHOW = 0x0005,
|
||||||
|
MINIMIZE = 0x0006,
|
||||||
|
SHOWMINNOACTIVE = 0x0007,
|
||||||
|
SHOWNA = 0x0008,
|
||||||
|
RESTORE = 0x0009,
|
||||||
|
SHOWDEFAULT = 0x000A,
|
||||||
|
FORCEMINIMIZE = 0x000B,
|
||||||
|
}
|
||||||
|
|
||||||
internal enum WM
|
internal enum WM
|
||||||
{
|
{
|
||||||
NULL = 0x0000,
|
NULL = 0x0000,
|
||||||
@ -185,6 +225,8 @@ namespace PowerLauncher.Helper
|
|||||||
|
|
||||||
NCMOUSELEAVE = 0x02A2,
|
NCMOUSELEAVE = 0x02A2,
|
||||||
|
|
||||||
|
HOTKEY = 0x0312,
|
||||||
|
|
||||||
DWMCOMPOSITIONCHANGED = 0x031E,
|
DWMCOMPOSITIONCHANGED = 0x031E,
|
||||||
DWMNCRENDERINGCHANGED = 0x031F,
|
DWMNCRENDERINGCHANGED = 0x031F,
|
||||||
DWMCOLORIZATIONCOLORCHANGED = 0x0320,
|
DWMCOLORIZATIONCOLORCHANGED = 0x0320,
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
SourceInitialized="OnSourceInitialized"
|
SourceInitialized="OnSourceInitialized"
|
||||||
Loaded="OnLoaded"
|
Loaded="OnLoaded"
|
||||||
Closing="OnClosing"
|
Closing="OnClosing"
|
||||||
|
Closed="OnClosed"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
LocationChanged="OnLocationChanged"
|
LocationChanged="OnLocationChanged"
|
||||||
Deactivated="OnDeactivated"
|
Deactivated="OnDeactivated"
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
@ -96,10 +97,39 @@ namespace PowerLauncher
|
|||||||
Activate();
|
Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string EnvironmentChangeType = "Environment";
|
||||||
|
|
||||||
|
#pragma warning disable CA1801 // Review unused parameters
|
||||||
|
public IntPtr ProcessWindowMessages(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
|
||||||
|
#pragma warning restore CA1801 // Review unused parameters
|
||||||
|
{
|
||||||
|
switch ((WM)msg)
|
||||||
|
{
|
||||||
|
case WM.SETTINGCHANGE:
|
||||||
|
string changeType = Marshal.PtrToStringUni(lparam);
|
||||||
|
if (changeType == EnvironmentChangeType)
|
||||||
|
{
|
||||||
|
Log.Info("Reload environment", typeof(EnvironmentHelper));
|
||||||
|
EnvironmentHelper.UpdateEnvironment();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case WM.HOTKEY:
|
||||||
|
handled = _viewModel.ProcessHotKeyMessages(wparam, lparam);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnSourceInitialized(object sender, EventArgs e)
|
private void OnSourceInitialized(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
_hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
|
||||||
_hwndSource.AddHook(EnvironmentHelper.ProcessWindowMessages);
|
_hwndSource.AddHook(ProcessWindowMessages);
|
||||||
|
|
||||||
|
// Call RegisterHotKey only after a window handle can be used, so that a global hotkey can be registered.
|
||||||
|
_viewModel.RegisterHotkey(_hwndSource.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
@ -489,5 +519,11 @@ namespace PowerLauncher
|
|||||||
Dispose(disposing: true);
|
Dispose(disposing: true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnClosed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_hwndSource.RemoveHook(ProcessWindowMessages);
|
||||||
|
_hwndSource = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,12 @@ namespace PowerLauncher.ViewModel
|
|||||||
private bool _saved;
|
private bool _saved;
|
||||||
private ushort _hotkeyHandle;
|
private ushort _hotkeyHandle;
|
||||||
|
|
||||||
|
private const int _globalHotKeyId = 0x0001;
|
||||||
|
private IntPtr _globalHotKeyHwnd;
|
||||||
|
private uint _globalHotKeyVK;
|
||||||
|
private uint _globalHotKeyFSModifiers;
|
||||||
|
private bool _usingGlobalHotKey;
|
||||||
|
|
||||||
internal HotkeyManager HotkeyManager { get; private set; }
|
internal HotkeyManager HotkeyManager { get; private set; }
|
||||||
|
|
||||||
public MainViewModel(PowerToysRunSettings settings)
|
public MainViewModel(PowerToysRunSettings settings)
|
||||||
@ -75,39 +81,44 @@ namespace PowerLauncher.ViewModel
|
|||||||
RegisterResultsUpdatedEvent();
|
RegisterResultsUpdatedEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterHotkey()
|
public void RegisterHotkey(IntPtr hwnd)
|
||||||
{
|
{
|
||||||
Log.Info("RegisterHotkey()", GetType());
|
Log.Info("RegisterHotkey()", GetType());
|
||||||
if (_settings != null && _settings.UsePowerToysRunnerKeyboardHook)
|
_settings.PropertyChanged += (s, e) =>
|
||||||
{
|
{
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey);
|
if (e.PropertyName == nameof(PowerToysRunSettings.Hotkey))
|
||||||
_hotkeyHandle = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HotkeyManager = new HotkeyManager();
|
|
||||||
_settings.PropertyChanged += (s, e) =>
|
|
||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(PowerToysRunSettings.Hotkey))
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
Application.Current.Dispatcher.Invoke(() =>
|
if (!string.IsNullOrEmpty(_settings.PreviousHotkey))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_settings.PreviousHotkey))
|
if (_usingGlobalHotKey)
|
||||||
{
|
{
|
||||||
HotkeyManager.UnregisterHotkey(_hotkeyHandle);
|
NativeMethods.UnregisterHotKey(_globalHotKeyHwnd, _globalHotKeyId);
|
||||||
|
_usingGlobalHotKey = false;
|
||||||
|
Log.Info("Unregistering previous global hotkey", GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_settings.Hotkey))
|
if (_hotkeyHandle != 0)
|
||||||
{
|
{
|
||||||
SetHotkey(_settings.Hotkey, OnHotkey);
|
HotkeyManager?.UnregisterHotkey(_hotkeyHandle);
|
||||||
|
_hotkeyHandle = 0;
|
||||||
|
Log.Info("Unregistering previous low level key handler", GetType());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SetHotkey(_settings.Hotkey, OnHotkey);
|
if (!string.IsNullOrEmpty(_settings.Hotkey))
|
||||||
SetCustomPluginHotkey();
|
{
|
||||||
}
|
SetHotkey(hwnd, _settings.Hotkey, OnHotkey);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetHotkey(hwnd, _settings.Hotkey, OnHotkey);
|
||||||
|
|
||||||
|
// TODO: Custom plugin hotkeys.
|
||||||
|
// SetCustomPluginHotkey();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterResultsUpdatedEvent()
|
private void RegisterResultsUpdatedEvent()
|
||||||
@ -672,15 +683,35 @@ namespace PowerLauncher.ViewModel
|
|||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetHotkey(string hotkeyStr, HotkeyCallback action)
|
#pragma warning disable CA1801 // Review unused parameters
|
||||||
|
internal bool ProcessHotKeyMessages(IntPtr wparam, IntPtr lparam)
|
||||||
|
#pragma warning restore CA1801 // Review unused parameters
|
||||||
{
|
{
|
||||||
var hotkey = new HotkeyModel(hotkeyStr);
|
if (wparam.ToInt32() == _globalHotKeyId)
|
||||||
SetHotkey(hotkey, action);
|
{
|
||||||
|
OnHotkey();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetHotkey(HotkeyModel hotkeyModel, HotkeyCallback action)
|
private static uint VKModifiersFromHotKey(Hotkey hotkey)
|
||||||
{
|
{
|
||||||
|
return (uint)(HOTKEY_MODIFIERS.NOREPEAT | (hotkey.Alt ? HOTKEY_MODIFIERS.ALT : 0) | (hotkey.Ctrl ? HOTKEY_MODIFIERS.CONTROL : 0) | (hotkey.Shift ? HOTKEY_MODIFIERS.SHIFT : 0) | (hotkey.Win ? HOTKEY_MODIFIERS.WIN : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetHotkey(IntPtr hwnd, string hotkeyStr, HotkeyCallback action)
|
||||||
|
{
|
||||||
|
var hotkey = new HotkeyModel(hotkeyStr);
|
||||||
|
SetHotkey(hwnd, hotkey, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetHotkey(IntPtr hwnd, HotkeyModel hotkeyModel, HotkeyCallback action)
|
||||||
|
{
|
||||||
|
Log.Info("Set HotKey()", GetType());
|
||||||
string hotkeyStr = hotkeyModel.ToString();
|
string hotkeyStr = hotkeyModel.ToString();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Hotkey hotkey = new Hotkey
|
Hotkey hotkey = new Hotkey
|
||||||
@ -692,6 +723,39 @@ namespace PowerLauncher.ViewModel
|
|||||||
Key = (byte)KeyInterop.VirtualKeyFromKey(hotkeyModel.CharKey),
|
Key = (byte)KeyInterop.VirtualKeyFromKey(hotkeyModel.CharKey),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (_usingGlobalHotKey)
|
||||||
|
{
|
||||||
|
NativeMethods.UnregisterHotKey(_globalHotKeyHwnd, _globalHotKeyId);
|
||||||
|
_usingGlobalHotKey = false;
|
||||||
|
Log.Info("Unregistering previous global hotkey", GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hotkeyHandle != 0)
|
||||||
|
{
|
||||||
|
HotkeyManager?.UnregisterHotkey(_hotkeyHandle);
|
||||||
|
_hotkeyHandle = 0;
|
||||||
|
Log.Info("Unregistering previous low level key handler", GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
_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
|
||||||
@ -721,6 +785,11 @@ namespace PowerLauncher.ViewModel
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Custom Hotkeys for Plugins. Commented since this is an incomplete feature.
|
||||||
|
* This needs:
|
||||||
|
* - Support for use with global shortcut.
|
||||||
|
* - Support for use with the fallback Shortcut Manager.
|
||||||
|
* - Support for use through the runner centralized keyboard hooks.
|
||||||
private void SetCustomPluginHotkey()
|
private void SetCustomPluginHotkey()
|
||||||
{
|
{
|
||||||
if (_settings.CustomPluginHotkeys == null)
|
if (_settings.CustomPluginHotkeys == null)
|
||||||
@ -742,6 +811,7 @@ namespace PowerLauncher.ViewModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
private void OnHotkey()
|
private void OnHotkey()
|
||||||
{
|
{
|
||||||
@ -966,6 +1036,12 @@ namespace PowerLauncher.ViewModel
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
|
if (_usingGlobalHotKey)
|
||||||
|
{
|
||||||
|
NativeMethods.UnregisterHotKey(_globalHotKeyHwnd, _globalHotKeyId);
|
||||||
|
_usingGlobalHotKey = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_hotkeyHandle != 0)
|
if (_hotkeyHandle != 0)
|
||||||
{
|
{
|
||||||
HotkeyManager?.UnregisterHotkey(_hotkeyHandle);
|
HotkeyManager?.UnregisterHotkey(_hotkeyHandle);
|
||||||
|
Loading…
Reference in New Issue
Block a user