Compare commits

..

No commits in common. "a7f35d449588a01b5cb357985d0e7cf92092eacf" and "6079e76be5f9b8944068e5afe6cf07a2d81bdc6b" have entirely different histories.

6 changed files with 136 additions and 226 deletions

View file

@ -11,7 +11,6 @@
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.4" /> <PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.4" />
<PackageVersion Include="CliWrap" Version="3.8.0" /> <PackageVersion Include="CliWrap" Version="3.8.0" />
<PackageVersion Include="Downloader" Version="3.3.3" /> <PackageVersion Include="Downloader" Version="3.3.3" />
<PackageVersion Include="GlobalHotKeys.Windows" Version="0.1.0" />
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" /> <PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" />
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" /> <PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" /> <PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />

View file

@ -1,88 +0,0 @@
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<HotkeyHandler> _instance = new(() => new());
public static HotkeyHandler Instance = _instance.Value;
private readonly Dictionary<int, EGlobalHotkey> _hotkeyTriggerDic = new();
private HotKeyManager? _hotKeyManager;
private Config? _config;
private event Action<EGlobalHotkey>? _updateFunc;
public bool IsPause { get; set; } = false;
public void Init(Config config, Action<EGlobalHotkey> 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);
}
}
}
}

View file

@ -6,17 +6,17 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="{x:Static resx:ResUI.menuGlobalHotkeySetting}" Title="{x:Static resx:ResUI.menuSetting}"
Width="700" Width="700"
Height="500" Height="500"
x:DataType="vms:GlobalHotkeySettingViewModel" x:DataType="vms:SubEditViewModel"
ShowInTaskbar="False" ShowInTaskbar="False"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
mc:Ignorable="d"> mc:Ignorable="d">
<DockPanel Margin="{StaticResource Margin8}"> <DockPanel Margin="{StaticResource Margin8}">
<StackPanel <StackPanel
Margin="{StaticResource Margin4}"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Margin="{StaticResource Margin4}"
DockPanel.Dock="Bottom" DockPanel.Dock="Bottom"
Orientation="Horizontal"> Orientation="Horizontal">
<Button <Button
@ -55,77 +55,77 @@
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbDisplayGUI}" /> Text="{x:Static resx:ResUI.TbDisplayGUI}" />
<TextBox <TextBox
x:Name="txtGlobalHotkey0" x:Name="txtGlobalHotkey0"
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
IsReadOnly="True" /> IsReadOnly="True" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbClearSystemProxy}" /> Text="{x:Static resx:ResUI.TbClearSystemProxy}" />
<TextBox <TextBox
x:Name="txtGlobalHotkey1" x:Name="txtGlobalHotkey1"
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
IsReadOnly="True" /> IsReadOnly="True" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="3"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbSetSystemProxy}" /> Text="{x:Static resx:ResUI.TbSetSystemProxy}" />
<TextBox <TextBox
x:Name="txtGlobalHotkey2" x:Name="txtGlobalHotkey2"
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
IsReadOnly="True" /> IsReadOnly="True" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbNotChangeSystemProxy}" /> Text="{x:Static resx:ResUI.TbNotChangeSystemProxy}" />
<TextBox <TextBox
x:Name="txtGlobalHotkey3" x:Name="txtGlobalHotkey3"
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
IsReadOnly="True" /> IsReadOnly="True" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="5"
Grid.Column="0" Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbSystemProxyPac}" /> Text="{x:Static resx:ResUI.TbSystemProxyPac}" />
<TextBox <TextBox
x:Name="txtGlobalHotkey4" x:Name="txtGlobalHotkey4"
Grid.Row="5" Grid.Row="5"
Grid.Column="1" Grid.Column="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
IsReadOnly="True" /> IsReadOnly="True" />
</Grid> </Grid>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="{StaticResource Margin4}"
Text="{x:Static resx:ResUI.TbGlobalHotkeySettingTip}" /> Text="{x:Static resx:ResUI.TbGlobalHotkeySettingTip}" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>

View file

@ -1,138 +1,129 @@
using System.Reactive.Disposables; using Avalonia.Controls;
using System.Text;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.ReactiveUI;
using ReactiveUI;
using v2rayN.Desktop.Handler;
namespace v2rayN.Desktop.Views namespace v2rayN.Desktop.Views
{ {
public partial class GlobalHotkeySettingWindow : ReactiveWindow<GlobalHotkeySettingViewModel> public partial class GlobalHotkeySettingWindow : Window
{ {
private readonly List<object> _textBoxKeyEventItem = new(); private static Config _config = default!;
private Dictionary<object, KeyEventItem> _TextBoxKeyEventItem = default!;
public GlobalHotkeySettingWindow() public GlobalHotkeySettingWindow()
{ {
InitializeComponent(); InitializeComponent();
ViewModel = new GlobalHotkeySettingViewModel(UpdateViewHandler);
btnReset.Click += btnReset_Click;
HotkeyHandler.Instance.IsPause = true;
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
btnCancel.Click += (s, e) => this.Close(); btnCancel.Click += (s, e) => this.Close();
_config = AppHandler.Instance.Config;
//_config.globalHotkeys ??= new List<KeyEventItem>();
this.WhenActivated(disposables => //txtGlobalHotkey0.KeyDown += TxtGlobalHotkey_PreviewKeyDown;
{ //txtGlobalHotkey1.KeyDown += TxtGlobalHotkey_PreviewKeyDown;
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); //txtGlobalHotkey2.KeyDown += TxtGlobalHotkey_PreviewKeyDown;
}); //txtGlobalHotkey3.KeyDown += TxtGlobalHotkey_PreviewKeyDown;
//txtGlobalHotkey4.KeyDown += TxtGlobalHotkey_PreviewKeyDown;
Init(); //HotkeyHandler.Instance.IsPause = true;
BindingData(); //this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
//InitData();
} }
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj) //private void InitData()
{ //{
switch (action) // _TextBoxKeyEventItem = new()
{ // {
case EViewAction.CloseWindow: // { txtGlobalHotkey0,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.ShowForm) },
this.Close(true); // { txtGlobalHotkey1,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyClear) },
break; // { txtGlobalHotkey2,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxySet) },
} // { txtGlobalHotkey3,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyUnchanged)},
return await Task.FromResult(true); // { txtGlobalHotkey4,GetKeyEventItemByEGlobalHotkey(_config.globalHotkeys,EGlobalHotkey.SystemProxyPac)}
} // };
// BindingData();
//}
private void Init() //private void TxtGlobalHotkey_PreviewKeyDown(object? sender, KeyEventArgs e)
{ //{
_textBoxKeyEventItem.Add(txtGlobalHotkey0); // e.Handled = true;
_textBoxKeyEventItem.Add(txtGlobalHotkey1); // var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift,
_textBoxKeyEventItem.Add(txtGlobalHotkey2); // Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin};
_textBoxKeyEventItem.Add(txtGlobalHotkey3); // _TextBoxKeyEventItem[sender].KeyCode = (int)(e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key));
_textBoxKeyEventItem.Add(txtGlobalHotkey4); // _TextBoxKeyEventItem[sender].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
// _TextBoxKeyEventItem[sender].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
// _TextBoxKeyEventItem[sender].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
// (sender as TextBox)!.Text = KeyEventItemToString(_TextBoxKeyEventItem[sender]);
//}
for (var index = 0; index < _textBoxKeyEventItem.Count; index++) //private KeyEventItem GetKeyEventItemByEGlobalHotkey(List<KeyEventItem> KEList, EGlobalHotkey eg)
{ //{
var sender = _textBoxKeyEventItem[index]; // return JsonUtils.DeepCopy(KEList.Find((it) => it.eGlobalHotkey == eg) ?? new()
if (sender is not TextBox txtBox) // {
{ // eGlobalHotkey = eg,
continue; // Control = false,
} // Alt = false,
txtBox.Tag = (EGlobalHotkey)index; // Shift = false,
txtBox.KeyDown += TxtGlobalHotkey_PreviewKeyDown; // KeyCode = null
} // });
} //}
private void TxtGlobalHotkey_PreviewKeyDown(object? sender, KeyEventArgs e) //private string KeyEventItemToString(KeyEventItem item)
{ //{
e.Handled = true; // var res = new StringBuilder();
if (sender is not TextBox txtBox)
{
return;
}
var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag); // if (item.Control) res.Append($"{ModifierKeys.Control}+");
var modifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin }; // if (item.Shift) res.Append($"{ModifierKeys.Shift}+");
// if (item.Alt) res.Append($"{ModifierKeys.Alt}+");
// if (item.KeyCode != null && (Key)item.KeyCode != Key.None)
// res.Append($"{(Key)item.KeyCode}");
item.KeyCode = (int)(e.Key == Key.System ? modifierKeys.Contains(Key.System) ? Key.None : Key.System : modifierKeys.Contains(e.Key) ? Key.None : e.Key); // return res.ToString();
item.Alt = (e.KeyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt; //}
item.Control = (e.KeyModifiers & KeyModifiers.Control) == KeyModifiers.Control;
item.Shift = (e.KeyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift;
txtBox.Text = KeyEventItemToString(item); //private void BindingData()
} //{
// foreach (var item in _TextBoxKeyEventItem)
// {
// if (item.Value.KeyCode != null && (Key)item.Value.KeyCode != Key.None)
// {
// (item.Key as TextBox)!.Text = KeyEventItemToString(item.Value);
// }
// else
// {
// (item.Key as TextBox)!.Text = string.Empty;
// }
// }
//}
private void BindingData() //private void btnSave_Click(object? sender, RoutedEventArgs e)
{ //{
foreach (var sender in _textBoxKeyEventItem) // _config.globalHotkeys = _TextBoxKeyEventItem.Values.ToList();
{
if (sender is not TextBox txtBox)
{
continue;
}
var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag); // if (ConfigHandler.SaveConfig(_config, false) == 0)
txtBox.Text = KeyEventItemToString(item); // {
} // HotkeyHandler.Instance.ReLoad();
} // this.Close();
// }
// else
// {
// UI.Show(ResUI.OperationFailed);
// }
//}
private void btnReset_Click(object sender, RoutedEventArgs e) //private void btnReset_Click(object? sender, RoutedEventArgs e)
{ //{
ViewModel?.ResetKeyEventItem(); // foreach (var k in _TextBoxKeyEventItem.Keys)
BindingData(); // {
} // _TextBoxKeyEventItem[k].Alt = false;
// _TextBoxKeyEventItem[k].Control = false;
// _TextBoxKeyEventItem[k].Shift = false;
// _TextBoxKeyEventItem[k].KeyCode = (int)Key.None;
// }
// BindingData();
//}
private string KeyEventItemToString(KeyEventItem? item) //private void GlobalHotkeySettingWindow_KeyDown(object? sender, KeyEventArgs e)
{ //{
if (item == null) // if (e.Key == Key.Escape)
{ // {
return string.Empty; // this.Close();
} // }
var res = new StringBuilder(); //}
if (item.Control)
{
res.Append($"{KeyModifiers.Control} +");
}
if (item.Shift)
{
res.Append($"{KeyModifiers.Shift} +");
}
if (item.Alt)
{
res.Append($"{KeyModifiers.Alt} +");
}
if (item.KeyCode != null && (Key)item.KeyCode != Key.None)
{
res.Append($"{(Key)item.KeyCode}");
}
return res.ToString();
}
} }
} }

View file

@ -12,7 +12,6 @@ using MsBox.Avalonia.Enums;
using ReactiveUI; using ReactiveUI;
using Splat; using Splat;
using v2rayN.Desktop.Common; using v2rayN.Desktop.Common;
using v2rayN.Desktop.Handler;
namespace v2rayN.Desktop.Views namespace v2rayN.Desktop.Views
{ {
@ -139,7 +138,8 @@ namespace v2rayN.Desktop.Views
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false); ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
HotkeyHandler.Instance.Init(_config, OnHotkeyHandler);
menuGlobalHotkeySetting.IsVisible = false;
} }
else else
{ {
@ -156,6 +156,7 @@ namespace v2rayN.Desktop.Views
RestoreUI(); RestoreUI();
AddHelpMenuItem(); AddHelpMenuItem();
//WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
MessageBus.Current.Listen<string>(EMsgCommand.AppExit.ToString()).Subscribe(StorageUI); MessageBus.Current.Listen<string>(EMsgCommand.AppExit.ToString()).Subscribe(StorageUI);
} }
@ -232,7 +233,6 @@ namespace v2rayN.Desktop.Views
StorageUI(); StorageUI();
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
HotkeyHandler.Instance.Dispose();
desktop.Shutdown(); desktop.Shutdown();
} }
break; break;
@ -268,12 +268,21 @@ namespace v2rayN.Desktop.Views
ShowHideWindow(null); ShowHideWindow(null);
break; break;
case EGlobalHotkey.SystemProxyClear: //case EGlobalHotkey.SystemProxyClear:
case EGlobalHotkey.SystemProxySet: // ViewModel?.SetListenerType(ESysProxyType.ForcedClear);
case EGlobalHotkey.SystemProxyUnchanged: // break;
case EGlobalHotkey.SystemProxyPac:
Locator.Current.GetService<StatusBarViewModel>()?.SetListenerType((ESysProxyType)((int)e - 1)); //case EGlobalHotkey.SystemProxySet:
break; // ViewModel?.SetListenerType(ESysProxyType.ForcedChange);
// break;
//case EGlobalHotkey.SystemProxyUnchanged:
// ViewModel?.SetListenerType(ESysProxyType.Unchanged);
// break;
//case EGlobalHotkey.SystemProxyPac:
// ViewModel?.SetListenerType(ESysProxyType.Pac);
// break;
} }
} }

View file

@ -26,7 +26,6 @@
<PackageReference Include="ReactiveUI.Fody"> <PackageReference Include="ReactiveUI.Fody">
<TreatAsUsed>true</TreatAsUsed> <TreatAsUsed>true</TreatAsUsed>
</PackageReference> </PackageReference>
<PackageReference Include="GlobalHotKeys.Windows" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>