mirror of
https://github.com/tuxdotrs/highminded.git
synced 2025-08-22 23:51:03 +05:30
fix: keybindings trigger
This commit is contained in:
@@ -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
161
utils/KeyBindings.cs
Normal 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}";
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user