HotkeySettingsControlHook.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 7 using PowerToys.Interop; 8 9 namespace Microsoft.PowerToys.Settings.UI.Library 10 { 11 public delegate void KeyEvent(int key); 12 13 public delegate bool IsActive(); 14 15 public delegate bool FilterAccessibleKeyboardEvents(int key, UIntPtr extraInfo); 16 17 public class HotkeySettingsControlHook : IDisposable 18 { 19 private const int WmKeyDown = 0x100; 20 private const int WmKeyUp = 0x101; 21 private const int WmSysKeyDown = 0x0104; 22 private const int WmSysKeyUp = 0x0105; 23 24 private KeyboardHook _hook; 25 private KeyEvent _keyDown; 26 private KeyEvent _keyUp; 27 private IsActive _isActive; 28 private bool disposedValue; 29 30 private FilterAccessibleKeyboardEvents _filterKeyboardEvent; 31 32 public HotkeySettingsControlHook(KeyEvent keyDown, KeyEvent keyUp, IsActive isActive, FilterAccessibleKeyboardEvents filterAccessibleKeyboardEvents) 33 { 34 _keyDown = keyDown; 35 _keyUp = keyUp; 36 _isActive = isActive; 37 _filterKeyboardEvent = filterAccessibleKeyboardEvents; 38 _hook = new KeyboardHook(HotkeySettingsHookCallback, IsActive, FilterKeyboardEvents); 39 _hook.Start(); 40 } 41 42 private bool IsActive() 43 { 44 return _isActive(); 45 } 46 47 private void HotkeySettingsHookCallback(KeyboardEvent ev) 48 { 49 switch (ev.message) 50 { 51 case WmKeyDown: 52 case WmSysKeyDown: 53 _keyDown(ev.key); 54 break; 55 case WmKeyUp: 56 case WmSysKeyUp: 57 _keyUp(ev.key); 58 break; 59 } 60 } 61 62 private bool FilterKeyboardEvents(KeyboardEvent ev) 63 { 64 #pragma warning disable CA2020 // Prevent from behavioral change 65 return _filterKeyboardEvent(ev.key, (UIntPtr)ev.dwExtraInfo); 66 #pragma warning restore CA2020 // Prevent from behavioral change 67 } 68 69 protected virtual void Dispose(bool disposing) 70 { 71 if (!disposedValue) 72 { 73 if (disposing) 74 { 75 // Dispose the KeyboardHook object to terminate the hook threads 76 _hook.Dispose(); 77 } 78 79 disposedValue = true; 80 } 81 } 82 83 public bool GetDisposedState() => disposedValue; 84 85 public void Dispose() 86 { 87 Dispose(disposing: true); 88 GC.SuppressFinalize(this); 89 } 90 } 91 }