fix: keybindings trigger

This commit is contained in:
tux
2025-07-05 19:38:16 +05:30
parent 3c01781503
commit 0ac2f01321
2 changed files with 200 additions and 48 deletions

View File

@@ -7,8 +7,8 @@ using Avalonia.Media;
using Avalonia.Threading; using Avalonia.Threading;
using highminded.ui.controls; using highminded.ui.controls;
using highminded.utils; using highminded.utils;
using SharpHook;
using SharpHook.Data; using SharpHook.Data;
using KeyBinding = highminded.utils.KeyBinding;
namespace highminded.ui.windows; namespace highminded.ui.windows;
@@ -32,7 +32,7 @@ public partial class MainWindow : Window
private readonly SettingsUserControl _settingsUserControl = new SettingsUserControl(); private readonly SettingsUserControl _settingsUserControl = new SettingsUserControl();
// Hotkey // Hotkey
private readonly TaskPoolGlobalHook _hook = new TaskPoolGlobalHook(); private readonly PreciseKeyBindings _keyBindings = new PreciseKeyBindings();
public MainWindow() public MainWindow()
{ {
@@ -42,9 +42,7 @@ public partial class MainWindow : Window
UControl.Content = _chatUserControl; UControl.Content = _chatUserControl;
ChatBtnActive(); ChatBtnActive();
HideOverlay(); HideOverlay();
// Global Hotkey RegisterKeyBindings();
_hook.KeyPressed += OnKeyPressed;
_hook.RunAsync();
} }
private void OnPointerPressed(object? sender, PointerPressedEventArgs e) private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
@@ -141,50 +139,21 @@ public partial class MainWindow : Window
Hide(); Hide();
} }
private void OnKeyPressed(object? sender, KeyboardHookEventArgs e) private void RegisterKeyBindings()
{ {
bool hasCtrl = (e.RawEvent.Mask & EventMask.Ctrl) != EventMask.None; _keyBindings.AddKeyBinding(
bool hasAlt = (e.RawEvent.Mask & EventMask.Alt) != EventMask.None; new KeyBinding(KeyCode.VcH, ModifierKey.Control, ModifierKey.Alt, ModifierKey.Shift),
bool hasShift = (e.RawEvent.Mask & EventMask.Shift) != EventMask.None; () => Dispatcher.UIThread.Post(ShowOverlay)
bool hasH = e.Data.KeyCode == KeyCode.VcH; );
bool hasBackslash = e.Data.KeyCode == KeyCode.VcBackslash;
bool hasA = e.Data.KeyCode == KeyCode.VcA;
bool hasS = e.Data.KeyCode == KeyCode.VcS;
bool hasQ = e.Data.KeyCode == KeyCode.VcQ;
if (hasCtrl && hasShift && hasAlt && hasH) _keyBindings.AddKeyBinding(
{ new KeyBinding(KeyCode.VcQ, ModifierKey.Alt, ModifierKey.Shift),
ShowOverlay(); () => Dispatcher.UIThread.Post(() => Environment.Exit(0))
} );
if (hasAlt && hasShift && hasS) _keyBindings.AddKeyBinding(
{ new KeyBinding(KeyCode.VcBackslash, ModifierKey.Alt, ModifierKey.Shift),
Dispatcher.UIThread.Post(() => { _chatUserControl.SendScreenshot(); }); () => Dispatcher.UIThread.Post(() =>
}
if (hasAlt && hasShift && hasA)
{
Dispatcher.UIThread.Post(() =>
{
if (!InMemoryDb.Obj.MainViewModel.IsRecording)
{
_chatUserControl.StartRecord();
}
else
{
_chatUserControl.StopRecord();
}
});
}
if (hasAlt && hasShift && hasQ)
{
Dispatcher.UIThread.Post(() => { Environment.Exit(0); });
}
if (hasAlt && hasShift && hasBackslash)
{
Dispatcher.UIThread.Post(() =>
{ {
if (WindowState == WindowState.Minimized || !IsVisible) if (WindowState == WindowState.Minimized || !IsVisible)
{ {
@@ -197,7 +166,29 @@ public partial class MainWindow : Window
{ {
Hide(); Hide();
} }
}); })
} );
_keyBindings.AddKeyBinding(
new KeyBinding(KeyCode.VcA, ModifierKey.Alt, ModifierKey.Shift),
() => Dispatcher.UIThread.Post(() =>
{
if (!InMemoryDb.Obj.MainViewModel.IsRecording)
{
_chatUserControl.StartRecord();
}
else
{
_chatUserControl.StopRecord();
}
})
);
_keyBindings.AddKeyBinding(
new KeyBinding(KeyCode.VcS, ModifierKey.Alt, ModifierKey.Shift),
() => Dispatcher.UIThread.Post(() => _chatUserControl.SendScreenshot())
);
_keyBindings.Start();
} }
} }

161
utils/KeyBindings.cs Normal file
View File

@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using SharpHook;
using SharpHook.Data;
namespace highminded.utils;
public enum ModifierKey
{
Control,
Shift,
Alt,
Meta
}
public class PreciseKeyBindings
{
private readonly IGlobalHook _hook;
private readonly Dictionary<KeyBinding, Action> _keyBindings;
private readonly HashSet<KeyCode> _pressedKeys;
public PreciseKeyBindings()
{
_hook = new TaskPoolGlobalHook();
_keyBindings = new Dictionary<KeyBinding, Action>();
_pressedKeys = new HashSet<KeyCode>();
// Subscribe to key events
_hook.KeyPressed += OnKeyPressed;
_hook.KeyReleased += OnKeyReleased;
}
public void AddKeyBinding(KeyBinding binding, Action action)
{
_keyBindings[binding] = action;
}
public void Start()
{
_hook.RunAsync();
}
public void Stop()
{
_hook.Dispose();
}
private void OnKeyPressed(object? sender, KeyboardHookEventArgs e)
{
_pressedKeys.Add(e.Data.KeyCode);
// Check if any key binding matches the current pressed keys
foreach (var kvp in _keyBindings)
{
if (IsExactMatch(kvp.Key))
{
kvp.Value.Invoke();
break; // Only trigger the first match
}
}
}
private void OnKeyReleased(object? sender, KeyboardHookEventArgs e)
{
_pressedKeys.Remove(e.Data.KeyCode);
}
private bool IsExactMatch(KeyBinding binding)
{
// Get currently pressed modifiers
var pressedModifiers = GetPressedModifiers();
// Check if the main key is pressed
if (!_pressedKeys.Contains(binding.Key))
return false;
// Check if modifiers match exactly
if (pressedModifiers.Count != binding.Modifiers.Count)
return false;
foreach (var modifier in binding.Modifiers)
{
if (!pressedModifiers.Contains(modifier))
return false;
}
return true;
}
private HashSet<ModifierKey> GetPressedModifiers()
{
var modifiers = new HashSet<ModifierKey>();
// Check for Control
if (_pressedKeys.Contains(KeyCode.VcLeftControl) || _pressedKeys.Contains(KeyCode.VcRightControl))
modifiers.Add(ModifierKey.Control);
// Check for Shift
if (_pressedKeys.Contains(KeyCode.VcLeftShift) || _pressedKeys.Contains(KeyCode.VcRightShift))
modifiers.Add(ModifierKey.Shift);
// Check for Alt
if (_pressedKeys.Contains(KeyCode.VcLeftAlt) || _pressedKeys.Contains(KeyCode.VcRightAlt))
modifiers.Add(ModifierKey.Alt);
// Check for Meta/Windows key
if (_pressedKeys.Contains(KeyCode.VcLeftMeta) || _pressedKeys.Contains(KeyCode.VcRightMeta))
modifiers.Add(ModifierKey.Meta);
return modifiers;
}
}
public class KeyBinding : IEquatable<KeyBinding>
{
public KeyCode Key { get; }
public HashSet<ModifierKey> Modifiers { get; }
public KeyBinding(KeyCode key, params ModifierKey[] modifiers)
{
Key = key;
Modifiers = new HashSet<ModifierKey>(modifiers);
}
public override bool Equals(object? obj)
{
return Equals(obj as KeyBinding);
}
public bool Equals(KeyBinding? other)
{
if (other == null) return false;
if (Key != other.Key) return false;
if (Modifiers.Count != other.Modifiers.Count) return false;
foreach (var modifier in Modifiers)
{
if (!other.Modifiers.Contains(modifier))
return false;
}
return true;
}
public override int GetHashCode()
{
int hash = Key.GetHashCode();
foreach (var modifier in Modifiers)
{
hash ^= modifier.GetHashCode();
}
return hash;
}
public override string ToString()
{
var modStr = string.Join(" + ", Modifiers);
return string.IsNullOrEmpty(modStr) ? Key.ToString() : $"{modStr} + {Key}";
}
}