diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props index b6cc69bf..77930319 100644 --- a/v2rayN/Directory.Packages.props +++ b/v2rayN/Directory.Packages.props @@ -11,6 +11,7 @@ + diff --git a/v2rayN/v2rayN.Desktop/Handler/HotkeyHandler.cs b/v2rayN/v2rayN.Desktop/Handler/HotkeyHandler.cs new file mode 100644 index 00000000..05470af6 --- /dev/null +++ b/v2rayN/v2rayN.Desktop/Handler/HotkeyHandler.cs @@ -0,0 +1,88 @@ +using System.Reactive.Linq; +using Avalonia.Input; +using Avalonia.ReactiveUI; +using Avalonia.Win32.Input; +using GlobalHotKeys; +using GlobalHotKeys.Native.Types; + +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; + _hotKeyManager = new GlobalHotKeys.HotKeyManager(); + + Register(); + } + + public void Dispose() + { + _hotKeyManager?.Dispose(); + } + + private void Register() + { + _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.NoRepeat; + 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); + } + } + } +} diff --git a/v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml.cs index 7fe157ba..5623ac7d 100644 --- a/v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml.cs @@ -5,6 +5,7 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.ReactiveUI; using ReactiveUI; +using v2rayN.Desktop.Handler; namespace v2rayN.Desktop.Views { @@ -20,8 +21,8 @@ namespace v2rayN.Desktop.Views btnReset.Click += btnReset_Click; - //HotkeyHandler.Instance.IsPause = true; - //this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false; + HotkeyHandler.Instance.IsPause = true; + this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false; btnCancel.Click += (s, e) => this.Close(); this.WhenActivated(disposables => diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index 0f3def91..d9a01eb4 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -12,6 +12,7 @@ using MsBox.Avalonia.Enums; using ReactiveUI; using Splat; using v2rayN.Desktop.Common; +using v2rayN.Desktop.Handler; namespace v2rayN.Desktop.Views { @@ -138,8 +139,7 @@ namespace v2rayN.Desktop.Views if (Utils.IsWindows()) { ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false); - - menuGlobalHotkeySetting.IsVisible = false; + HotkeyHandler.Instance.Init(_config, OnHotkeyHandler); } else { @@ -156,7 +156,6 @@ namespace v2rayN.Desktop.Views RestoreUI(); AddHelpMenuItem(); - //WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null); MessageBus.Current.Listen(EMsgCommand.AppExit.ToString()).Subscribe(StorageUI); } @@ -233,6 +232,7 @@ namespace v2rayN.Desktop.Views StorageUI(); if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { + HotkeyHandler.Instance.Dispose(); desktop.Shutdown(); } break; @@ -268,21 +268,12 @@ namespace v2rayN.Desktop.Views ShowHideWindow(null); break; - //case EGlobalHotkey.SystemProxyClear: - // ViewModel?.SetListenerType(ESysProxyType.ForcedClear); - // break; - - //case EGlobalHotkey.SystemProxySet: - // ViewModel?.SetListenerType(ESysProxyType.ForcedChange); - // break; - - //case EGlobalHotkey.SystemProxyUnchanged: - // ViewModel?.SetListenerType(ESysProxyType.Unchanged); - // break; - - //case EGlobalHotkey.SystemProxyPac: - // ViewModel?.SetListenerType(ESysProxyType.Pac); - // break; + case EGlobalHotkey.SystemProxyClear: + case EGlobalHotkey.SystemProxySet: + case EGlobalHotkey.SystemProxyUnchanged: + case EGlobalHotkey.SystemProxyPac: + Locator.Current.GetService()?.SetListenerType((ESysProxyType)((int)e - 1)); + break; } } diff --git a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj index f234f4ce..5a550837 100644 --- a/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj +++ b/v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj @@ -26,6 +26,7 @@ true +