Forge
csharp4405de34
1#nullable enable
2using Avalonia.Input;
3
4namespace CascadeIDE.Services;
5
6/// <summary>
7/// Сопоставление <see cref="KeyGesture"/> с <see cref="KeyEventArgs"/> с учётом раскладки и лишних битов в <see cref="KeyEventArgs.KeyModifiers"/>
8/// (в т.ч. Avalonia 11+): встроенный <see cref="KeyGesture.Matches(KeyEventArgs)"/> требует полного совпадения модификаторов и совпадения <see cref="KeyEventArgs.Key"/> с жестом.
9/// Для буквенных хоткеев (Ctrl+Q, Ctrl+K, …) дополнительно используется <see cref="PhysicalKeyExtensions.ToQwertyKey(Avalonia.Input.PhysicalKey)"/>, чтобы позиция на QWERTY совпадала с жестом при нелатинской раскладке.
10/// </summary>
11public static class KeyGestureChordMatching
12{
13 private const KeyModifiers ChordModifierMask =
14 KeyModifiers.Control | KeyModifiers.Shift | KeyModifiers.Alt | KeyModifiers.Meta;
15
16 public static KeyModifiers NormalizeChordModifiers(KeyModifiers m) => m & ChordModifierMask;
17
18 /// <summary>Та же логика, что у <see cref="KeyGesture"/> для цифровой клавиатуры.</summary>
19 public static Key NormalizeNumPadAlias(Key key) =>
20 key switch
21 {
22 Key.Add => Key.OemPlus,
23 Key.Subtract => Key.OemMinus,
24 Key.Decimal => Key.OemPeriod,
25 _ => key,
26 };
27
28 /// <summary>
29 /// Сначала строгий <see cref="KeyGesture.Matches(KeyEventArgs)"/>; иначе совпадение по нормализованным модификаторам
30 /// и клавише (включая non-Latin: та же физическая K, что и у жеста <c>Key.K</c>).
31 /// </summary>
32 public static bool Matches(KeyGesture gesture, KeyEventArgs e)
33 {
34 if (gesture.Matches(e))
35 return true;
36
37 if (NormalizeChordModifiers(e.KeyModifiers) != NormalizeChordModifiers(gesture.KeyModifiers))
38 return false;
39
40 if (NormalizeNumPadAlias(e.Key) == NormalizeNumPadAlias(gesture.Key))
41 return true;
42
43 // Нелатинские раскладки: e.Key — по текущей раскладке, жест в TOML — как на QWERTY (Ctrl+Q, Ctrl+K, …).
44 // См. KeyEventArgs.Key / PhysicalKey в документации Avalonia; ToQwertyKey — позиция на US QWERTY → Key.
45 var qwertyKey = e.PhysicalKey.ToQwertyKey();
46 if (qwertyKey != Key.None &&
47 NormalizeNumPadAlias(qwertyKey) == NormalizeNumPadAlias(gesture.Key))
48 return true;
49
50 return false;
51 }
52}
53
View only · write via MCP/CIDE