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
+