using System.Reactive.Linq; using Avalonia.Input; using Avalonia.ReactiveUI; using Avalonia.Win32.Input; using GlobalHotKeys; namespace v2rayN.Desktop.Handler; public sealed class HotkeyHandler { private static readonly Lazy _instance = new(() => new()); public static HotkeyHandler Instance = _instance.Value; private readonly Dictionary _hotkeyTriggerDic = new(); private HotKeyManager? _hotKeyManager; private Config? _config; private event Action? _updateFunc; public bool IsPause { get; set; } = false; public void Init(Config config, Action updateFunc) { _config = config; _updateFunc = updateFunc; Register(); } public void Dispose() { _hotKeyManager?.Dispose(); } private void Register() { if (_config.GlobalHotkeys.Any(t => t.KeyCode > 0) == false) { return; } _hotKeyManager ??= new GlobalHotKeys.HotKeyManager(); _hotkeyTriggerDic.Clear(); foreach (var item in _config.GlobalHotkeys) { if (item.KeyCode is null or 0) { continue; } var vKey = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode); var modifiers = Modifiers.None; if (item.Control) { modifiers |= Modifiers.Control; } if (item.Shift) { modifiers |= Modifiers.Shift; } if (item.Alt) { modifiers |= Modifiers.Alt; } var result = _hotKeyManager?.Register((VirtualKeyCode)vKey, modifiers); if (result?.IsSuccessful == true) { _hotkeyTriggerDic.Add(result.Id, item.EGlobalHotkey); } } _hotKeyManager?.HotKeyPressed .ObserveOn(AvaloniaScheduler.Instance) .Subscribe(OnNext); } private void OnNext(HotKey key) { if (_updateFunc == null || IsPause) { return; } if (_hotkeyTriggerDic.TryGetValue(key.Id, out var value)) { _updateFunc?.Invoke(value); } } }