LenovoLegionToolkit
112 строк · 3.5 Кб
1using System;2using System.Threading.Tasks;3using LenovoLegionToolkit.Lib.Features;4using LenovoLegionToolkit.Lib.Settings;5using LenovoLegionToolkit.Lib.Utils;6using NeoSmart.AsyncLock;7using Windows.Win32;8using Windows.Win32.UI.Input.KeyboardAndMouse;9using Windows.Win32.UI.WindowsAndMessaging;10
11namespace LenovoLegionToolkit.Lib.Controllers;12
13public class SmartFnLockController14{
15private readonly AsyncLock _lock = new();16
17private readonly FnLockFeature _feature;18private readonly ApplicationSettings _settings;19
20private bool _ctrlDepressed;21private bool _shiftDepressed;22private bool _altDepressed;23private bool _restoreFnLock;24
25public SmartFnLockController(FnLockFeature feature, ApplicationSettings settings)26{27_feature = feature ?? throw new ArgumentNullException(nameof(feature));28_settings = settings ?? throw new ArgumentNullException(nameof(settings));29}30
31public void OnKeyboardEvent(nuint wParam, KBDLLHOOKSTRUCT kbStruct)32{33if (_settings.Store.SmartFnLockFlags == 0)34return;35
36Task.Run(async () =>37{38try39{40using (await _lock.LockAsync().ConfigureAwait(false))41await OnKeyboardEventAsync(wParam, kbStruct).ConfigureAwait(false);42}43catch (Exception ex)44{45if (Log.Instance.IsTraceEnabled)46Log.Instance.Trace($"Failed to handle keyboard event.", ex);47}48});49}50
51private async Task OnKeyboardEventAsync(nuint wParam, KBDLLHOOKSTRUCT kbStruct)52{53if (IsModifierKeyPressed(wParam, kbStruct))54{55if (_restoreFnLock)56return;57
58var state = await _feature.GetStateAsync().ConfigureAwait(false);59if (state == FnLockState.Off)60return;61
62if (Log.Instance.IsTraceEnabled)63Log.Instance.Trace($"Disabling Fn Lock temporarily...");64
65await _feature.SetStateAsync(FnLockState.Off).ConfigureAwait(false);66_restoreFnLock = true;67}68else if (_restoreFnLock)69{70if (Log.Instance.IsTraceEnabled)71Log.Instance.Trace($"Re-enabling Fn Lock...");72
73await _feature.SetStateAsync(FnLockState.On).ConfigureAwait(false);74_restoreFnLock = false;75}76}77
78private bool IsModifierKeyPressed(nuint wParam, KBDLLHOOKSTRUCT kbStruct)79{80var isKeyDown = wParam is PInvoke.WM_KEYDOWN or PInvoke.WM_SYSKEYDOWN;81var vkKeyCode = (VIRTUAL_KEY)kbStruct.vkCode;82
83if (vkKeyCode is VIRTUAL_KEY.VK_LCONTROL or VIRTUAL_KEY.VK_RCONTROL)84_ctrlDepressed = isKeyDown;85
86if (vkKeyCode is VIRTUAL_KEY.VK_LSHIFT or VIRTUAL_KEY.VK_RSHIFT)87_shiftDepressed = isKeyDown;88
89if (vkKeyCode is VIRTUAL_KEY.VK_LMENU or VIRTUAL_KEY.VK_RMENU)90_altDepressed = isKeyDown;91
92if (!_ctrlDepressed && !_shiftDepressed && !_altDepressed)93return false;94
95var result = false;96var flags = _settings.Store.SmartFnLockFlags;97
98if (flags.HasFlag(ModifierKey.Ctrl))99result |= _ctrlDepressed;100
101if (flags.HasFlag(ModifierKey.Shift))102result |= _shiftDepressed;103
104if (flags.HasFlag(ModifierKey.Alt))105result |= _altDepressed;106
107if (Log.Instance.IsTraceEnabled)108Log.Instance.Trace($"Modifier key is depressed: {result} [ctrl={_ctrlDepressed}, shift={_shiftDepressed}, alt={_altDepressed}, flags={flags}]");109
110return result;111}112}
113