use string for WPFControl & HotkeyModel with left right key accuracy

This commit is contained in:
Jeremy 2025-01-02 20:08:41 +11:00
parent 25bf44d711
commit be796fd899
5 changed files with 173 additions and 104 deletions

View file

@ -37,25 +37,53 @@ namespace Flow.Launcher.Infrastructure.Hotkey
public static SpecialKeyState CheckModifiers() public static SpecialKeyState CheckModifiers()
{ {
SpecialKeyState state = new SpecialKeyState(); SpecialKeyState state = new SpecialKeyState();
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_SHIFT) & 0x8000) != 0) if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_LSHIFT) & 0x8000) != 0)
{ {
//SHIFT is pressed //SHIFT is pressed
state.LeftShiftPressed = true;
state.ShiftPressed = true; state.ShiftPressed = true;
} }
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_CONTROL) & 0x8000) != 0) if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_RSHIFT) & 0x8000) != 0)
{
//SHIFT is pressed
state.RightShiftPressed = true;
state.ShiftPressed = true;
}
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_LCONTROL) & 0x8000) != 0)
{ {
//CONTROL is pressed //CONTROL is pressed
state.LeftCtrlPressed = true;
state.CtrlPressed = true; state.CtrlPressed = true;
} }
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_MENU) & 0x8000) != 0) if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_RCONTROL) & 0x8000) != 0)
{
//CONTROL is pressed
state.RightCtrlPressed = true;
state.CtrlPressed = true;
}
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_LMENU) & 0x8000) != 0)
{ {
//ALT is pressed //ALT is pressed
state.LeftAltPressed = true;
state.AltPressed = true; state.AltPressed = true;
} }
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_LWIN) & 0x8000) != 0 || if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_RMENU) & 0x8000) != 0)
(PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_RWIN) & 0x8000) != 0) {
//ALT is pressed
state.RightAltPressed = true;
state.AltPressed = true;
}
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_LWIN) & 0x8000) != 0)
{ {
//WIN is pressed //WIN is pressed
state.LWinPressed = true;
state.WinPressed = true;
}
if ((PInvoke.GetKeyState((int)VIRTUAL_KEY.VK_RWIN) & 0x8000) != 0)
{
//WIN is pressed
state.RWinPressed = true;
state.WinPressed = true; state.WinPressed = true;
} }

View file

@ -9,10 +9,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{ {
public record struct HotkeyModel public record struct HotkeyModel
{ {
public bool Alt { get; set; } public bool LeftAlt { get; set; }
public bool Shift { get; set; } public bool LeftShift { get; set; }
public bool Win { get; set; } public bool LWin { get; set; }
public bool Ctrl { get; set; } public bool LeftCtrl { get; set; }
public bool RightAlt { get; set; }
public bool RightShift { get; set; }
public bool RWin { get; set; }
public bool RightCtrl { get; set; }
public string HotkeyRaw { get; set; } = string.Empty; public string HotkeyRaw { get; set; } = string.Empty;
public string PreviousHotkey { get; set; } = string.Empty; public string PreviousHotkey { get; set; } = string.Empty;
@ -29,22 +33,22 @@ namespace Flow.Launcher.Infrastructure.Hotkey
get get
{ {
ModifierKeys modifierKeys = ModifierKeys.None; ModifierKeys modifierKeys = ModifierKeys.None;
if (Alt) if (LeftAlt || RightAlt)
{ {
modifierKeys |= ModifierKeys.Alt; modifierKeys |= ModifierKeys.Alt;
} }
if (Shift) if (LeftShift || RightShift)
{ {
modifierKeys |= ModifierKeys.Shift; modifierKeys |= ModifierKeys.Shift;
} }
if (Win) if (LWin || RWin)
{ {
modifierKeys |= ModifierKeys.Windows; modifierKeys |= ModifierKeys.Windows;
} }
if (Ctrl) if (LeftCtrl || RightCtrl)
{ {
modifierKeys |= ModifierKeys.Control; modifierKeys |= ModifierKeys.Control;
} }
@ -58,17 +62,21 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{ {
Clear(); Clear();
Parse(hotkeyString); Parse(hotkeyString);
HotkeyRaw = ToChefKeysString(); HotkeyRaw = FromWPFKeysToString();
} }
internal void SetHotkeyFromWPFControl(SpecialKeyState specialKeyState, Key key) internal void SetHotkeyFromWPFControl(SpecialKeyState specialKeyState, Key key)
{ {
Alt = specialKeyState.AltPressed; LeftAlt = specialKeyState.LeftAltPressed;
Shift = specialKeyState.ShiftPressed; LeftShift = specialKeyState.LeftShiftPressed;
Win = specialKeyState.WinPressed; LWin = specialKeyState.LWinPressed;
Ctrl = specialKeyState.CtrlPressed; LeftCtrl = specialKeyState.LeftCtrlPressed;
RightAlt = specialKeyState.RightAltPressed;
RightShift = specialKeyState.RightShiftPressed;
RWin = specialKeyState.RWinPressed;
RightCtrl = specialKeyState.RightCtrlPressed;
CharKey = key; CharKey = key;
HotkeyRaw = ToChefKeysString(); HotkeyRaw = FromWPFKeysToString();
PreviousHotkey = string.Empty; PreviousHotkey = string.Empty;
} }
@ -77,31 +85,25 @@ namespace Flow.Launcher.Infrastructure.Hotkey
SetHotkeyFromString(hotkey); SetHotkeyFromString(hotkey);
} }
//public HotkeyModel(bool alt, bool shift, bool win, bool ctrl, Key key)
//{
// Alt = alt;
// Shift = shift;
// Win = win;
// Ctrl = ctrl;
// CharKey = key;
//}
// Use for ChefKeys only // Use for ChefKeys only
internal void AddString(string key) internal void AddString(string key)
{ {
HotkeyRaw = string.IsNullOrEmpty(HotkeyRaw) ? key : HotkeyRaw + "+" + key; HotkeyRaw = string.IsNullOrEmpty(HotkeyRaw) ? key : HotkeyRaw + "+" + key;
Parse(HotkeyRaw);
} }
internal string GetLastKeySet() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+').Last() : string.Empty; internal string GetLastKeySet() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+').Last() : string.Empty;
internal bool MaxKeysReached() => DisplayKeysRaw().Count() == 4;
internal void Clear() internal void Clear()
{ {
Alt = false; LeftAlt = false;
Shift = false; LeftShift = false;
Win = false; LWin = false;
Ctrl = false; LeftCtrl = false;
RightAlt = false;
RightShift = false;
RWin = false;
RightCtrl = false;
HotkeyRaw = string.Empty; HotkeyRaw = string.Empty;
PreviousHotkey = string.Empty; PreviousHotkey = string.Empty;
CharKey = Key.None; CharKey = Key.None;
@ -114,36 +116,52 @@ namespace Flow.Launcher.Infrastructure.Hotkey
return; return;
} }
List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList(); List<string> keys = hotkeyString.Split('+', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList();
if (keys.Contains("Alt") || keys.Contains("LeftAlt") || keys.Contains("RightAlt")) if (keys.Contains("Alt") || keys.Contains("LeftAlt"))
{ {
Alt = true; LeftAlt = true;
keys.Remove("Alt"); keys.Remove("Alt");
keys.Remove("LeftAlt"); keys.Remove("LeftAlt");
}
if (keys.Contains("RightAlt"))
{
RightAlt = true;
keys.Remove("RightAlt"); keys.Remove("RightAlt");
} }
if (keys.Contains("Shift") || keys.Contains("LeftShift") || keys.Contains("RightShift")) if (keys.Contains("Shift") || keys.Contains("LeftShift"))
{ {
Shift = true; LeftShift = true;
keys.Remove("Shift"); keys.Remove("Shift");
keys.Remove("LeftShift"); keys.Remove("LeftShift");
}
if (keys.Contains("RightShift"))
{
RightShift = true;
keys.Remove("RightShift"); keys.Remove("RightShift");
} }
if (keys.Contains("Win") || keys.Contains("LWin") || keys.Contains("RWin")) if (keys.Contains("Win") || keys.Contains("LWin"))
{ {
Win = true; LWin = true;
keys.Remove("Win"); keys.Remove("Win");
keys.Remove("LWin"); keys.Remove("LWin");
}
if (keys.Contains("RWin"))
{
RWin = true;
keys.Remove("RWin"); keys.Remove("RWin");
} }
if (keys.Contains("Ctrl") || keys.Contains("LeftCtrl")|| keys.Contains("RightCtrl")) if (keys.Contains("Ctrl") || keys.Contains("LeftCtrl"))
{ {
Ctrl = true; LeftCtrl = true;
keys.Remove("Ctrl"); keys.Remove("Ctrl");
keys.Remove("LeftCtrl"); keys.Remove("LeftCtrl");
}
if (keys.Contains("RightCtrl"))
{
RightCtrl = true;
keys.Remove("RightCtrl"); keys.Remove("RightCtrl");
} }
@ -169,62 +187,90 @@ namespace Flow.Launcher.Infrastructure.Hotkey
} }
} }
public string ToChefKeysString() public readonly string ToWPFHotkeyString()
{ {
var key = string.Join("+", EnumerateDisplayKeys(true)); var hotkey = string.Empty;
return key; foreach (var key in HotkeyRaw.Split('+'))
{
if (!string.IsNullOrEmpty(hotkey))
hotkey += " + ";
switch (key)
{
case "LeftCtrl" or "RightCtrl":
hotkey += "Ctrl";
break;
case "LeftAlt" or "RightAlt":
hotkey += "Alt";
break;
case "LeftShift" or "RightShift":
hotkey += "Shift";
break;
case "LWin" or "RWin":
hotkey += "Win";
break;
default:
hotkey += key;
break;
}
}
return hotkey;
} }
public IEnumerable<string> DisplayKeysRaw() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+') : Array.Empty<string>(); public IEnumerable<string> EnumerateDisplayKeys() => !string.IsNullOrEmpty(HotkeyRaw) ? HotkeyRaw.Split('+') : Array.Empty<string>();
public IEnumerable<string> EnumerateDisplayKeys(bool forChefKeys = false) //For WPF hotkey control
public string FromWPFKeysToString() => string.Join("+", EnumerateWPFKeys());
public IEnumerable<string> EnumerateWPFKeys()
{ {
if (Ctrl && CharKey is not (Key.LeftCtrl or Key.RightCtrl)) if (LeftCtrl && CharKey is not Key.LeftCtrl)
{ {
yield return GetKeyString("Ctrl", forChefKeys); yield return "LeftCtrl";
} }
if (Alt && CharKey is not (Key.LeftAlt or Key.RightAlt)) if (LeftAlt && CharKey is not Key.LeftAlt)
{ {
yield return GetKeyString("Alt", forChefKeys); yield return "LeftAlt";
} }
if (Shift && CharKey is not (Key.LeftShift or Key.RightShift)) if (LeftShift && CharKey is not Key.LeftShift)
{ {
yield return GetKeyString("Shift", forChefKeys); yield return "LeftShift";
} }
if (Win && CharKey is not (Key.LWin or Key.RWin)) if (LWin && CharKey is not Key.LWin)
{ {
yield return GetKeyString("Win", forChefKeys); yield return "LWin";
}
if (RightCtrl && CharKey is not Key.RightCtrl)
{
yield return "RightCtrl";
}
if (RightAlt && CharKey is not Key.RightAlt)
{
yield return "RightAlt";
}
if (RightShift && CharKey is not Key.RightShift)
{
yield return "RightShift";
}
if (RWin && CharKey is not Key.RWin)
{
yield return "RWin";
} }
if (CharKey != Key.None) if (CharKey != Key.None)
{ {
yield return specialSymbolDictionary.TryGetValue(CharKey, out var value) yield return specialSymbolDictionary.TryGetValue(CharKey, out var value)
? value ? value
: GetKeyString(CharKey.ToString(), forChefKeys); : CharKey.ToString();
}
}
private string GetKeyString(string key, bool convertToChefKeysString)
{
if (!convertToChefKeysString)
return key;
switch (key)
{
case "Alt":
return "LeftAlt";
case "Ctrl":
return "LeftCtrl";
case "Shift":
return "LeftShift";
case "Win":
return "LWin";
default:
return key;
} }
} }
@ -235,6 +281,8 @@ namespace Flow.Launcher.Infrastructure.Hotkey
/// <returns></returns> /// <returns></returns>
public bool ValidateForWpf(bool validateKeyGestrue = false) public bool ValidateForWpf(bool validateKeyGestrue = false)
{ {
Parse(HotkeyRaw);
switch (CharKey) switch (CharKey)
{ {
case Key.LeftAlt: case Key.LeftAlt:

View file

@ -38,6 +38,14 @@ namespace Flow.Launcher.Plugin
/// True if the Windows key is pressed. /// True if the Windows key is pressed.
/// </summary> /// </summary>
public bool WinPressed { get; set; } public bool WinPressed { get; set; }
public bool LeftShiftPressed { get; set; }
public bool RightShiftPressed { get; set; }
public bool LeftCtrlPressed { get; set; }
public bool RightCtrlPressed { get; set; }
public bool LeftAltPressed { get; set; }
public bool RightAltPressed { get; set; }
public bool LWinPressed { get; set; }
public bool RWinPressed { get; set; }
/// <summary> /// <summary>
/// Get this object represented as a <see cref="ModifierKeys"/> flag combination. /// Get this object represented as a <see cref="ModifierKeys"/> flag combination.

View file

@ -182,7 +182,7 @@ namespace Flow.Launcher
if (!hotkeyAvailable) if (!hotkeyAvailable)
return; return;
Hotkey = keyModel.HotkeyRaw; Hotkey = keyModel.ToWPFHotkeyString();
SetKeysToDisplay(CurrentHotkey); SetKeysToDisplay(CurrentHotkey);
// If exists then will be unregistered, if doesn't no errors will be thrown. // If exists then will be unregistered, if doesn't no errors will be thrown.
@ -193,7 +193,7 @@ namespace Flow.Launcher
} }
else else
{ {
Hotkey = keyModel.HotkeyRaw; Hotkey = keyModel.ToWPFHotkeyString();
ChangeHotkey?.Execute(keyModel); ChangeHotkey?.Execute(keyModel);
} }
} }

View file

@ -144,17 +144,10 @@ public partial class HotkeyControlDialog : ContentDialog
if (HotkeyToUpdate.GetLastKeySet() == key.ToString()) if (HotkeyToUpdate.GetLastKeySet() == key.ToString())
return; return;
if (!isWPFHotkeyControl) if (MaxKeysLimitReached())
{ return;
if (HotkeyToUpdate.MaxKeysReached())
return;
HotkeyToUpdate.AddString(key.ToString()); HotkeyToUpdate.AddString(key.ToString());
}
else
{
HotkeyToUpdate.SetHotkeyFromWPFControl(GlobalHotkey.CheckModifiers(), key);
}
} }
private void SetKeysToDisplay(HotkeyModel? hotkey) private void SetKeysToDisplay(HotkeyModel? hotkey)
@ -170,19 +163,9 @@ public partial class HotkeyControlDialog : ContentDialog
IEnumerable<string> enumerateMethod; IEnumerable<string> enumerateMethod;
if (!isWPFHotkeyControl) foreach (var key in hotkey.Value.EnumerateDisplayKeys()!)
{ {
foreach (var key in hotkey.Value.DisplayKeysRaw()!) KeysToDisplay.Add(key);
{
KeysToDisplay.Add(key);
}
}
else
{
foreach (var key in hotkey.Value.EnumerateDisplayKeys()!)
{
KeysToDisplay.Add(key);
}
} }
if (tbMsg == null) if (tbMsg == null)
@ -190,7 +173,7 @@ public partial class HotkeyControlDialog : ContentDialog
if (_hotkeySettings.RegisteredHotkeys if (_hotkeySettings.RegisteredHotkeys
.FirstOrDefault(v => v.Hotkey == hotkey .FirstOrDefault(v => v.Hotkey == hotkey
|| v.Hotkey.ToChefKeysString() == hotkey.Value.HotkeyRaw) || v.Hotkey.FromWPFKeysToString() == hotkey.Value.HotkeyRaw)
is { } registeredHotkeyData) is { } registeredHotkeyData)
{ {
var description = string.Format( var description = string.Format(
@ -253,6 +236,8 @@ public partial class HotkeyControlDialog : ContentDialog
private static bool CheckWPFHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) private static bool CheckWPFHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture)
=> hotkey.ValidateForWpf(validateKeyGesture) && HotKeyMapper.CheckHotkeyAvailability(hotkey.HotkeyRaw); => hotkey.ValidateForWpf(validateKeyGesture) && HotKeyMapper.CheckHotkeyAvailability(hotkey.HotkeyRaw);
private bool MaxKeysLimitReached() => isWPFHotkeyControl ? KeysToDisplay.Count == 2 : KeysToDisplay.Count == 4;
private void Overwrite(object sender, RoutedEventArgs e) private void Overwrite(object sender, RoutedEventArgs e)
{ {
_overwriteOtherHotkey?.Invoke(); _overwriteOtherHotkey?.Invoke();