Forge
csharpdeeb25a2
1using Avalonia;
2using Avalonia.Controls;
3using Avalonia.Input;
4using Avalonia.VisualTree;
5
6namespace CascadeIDE.Services;
7
8/// <summary>
9/// Отправить сочетание клавиш в эффективный (под курсором) или указанный по имени контрол. Текст вида "Ctrl+Enter", "Alt+F4". Для ide_send_keys.
10/// </summary>
11public static class UiControlSendKeys
12{
13 public static string SendKeys(TopLevel topLevel, Visual root, string? controlName, string keysSpec)
14 {
15 if (string.IsNullOrWhiteSpace(keysSpec))
16 return "Missing keys (e.g. Ctrl+Enter, Alt+F4).";
17
18 Control? control;
19 if (!string.IsNullOrWhiteSpace(controlName))
20 {
21 control = root is Window mw
22 ? UiControlAppearance.FindControlByNameAcrossAllWindows(mw, controlName.Trim())
23 : UiControlAppearance.FindControlByName(root, controlName.Trim());
24 if (control is null)
25 return $"Control not found: {controlName}.";
26 }
27 else
28 {
29 control = UiPointerClientPosition.TryGetControlUnderPointer(topLevel);
30 if (control is null)
31 return "No control under cursor. Specify name or focus the target first.";
32 }
33
34 if (!TryParseKeys(keysSpec.Trim(), out var key, out var modifiers, out var parseError))
35 return parseError ?? "Invalid keys.";
36
37 control.Focus();
38 var keyDown = new KeyEventArgs
39 {
40 RoutedEvent = InputElement.KeyDownEvent,
41 Source = control,
42 Key = key,
43 KeyModifiers = modifiers
44 };
45 var keyUp = new KeyEventArgs
46 {
47 RoutedEvent = InputElement.KeyUpEvent,
48 Source = control,
49 Key = key,
50 KeyModifiers = modifiers
51 };
52 control.RaiseEvent(keyDown);
53 control.RaiseEvent(keyUp);
54 return "OK";
55 }
56
57 private static bool TryParseKeys(string spec, out Key key, out KeyModifiers modifiers, out string? error)
58 {
59 modifiers = KeyModifiers.None;
60 key = Key.None;
61 error = "";
62
63 var parts = spec.Split('+', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
64 if (parts.Length == 0)
65 {
66 error = "Empty key spec.";
67 return false;
68 }
69 error = null;
70
71 for (var i = 0; i < parts.Length - 1; i++)
72 {
73 var mod = parts[i].ToLowerInvariant();
74 if (mod is "ctrl" or "control")
75 modifiers |= KeyModifiers.Control;
76 else if (mod is "alt")
77 modifiers |= KeyModifiers.Alt;
78 else if (mod is "shift")
79 modifiers |= KeyModifiers.Shift;
80 else if (mod is "meta" or "win" or "windows")
81 modifiers |= KeyModifiers.Meta;
82 else
83 {
84 error = $"Unknown modifier: {parts[i]}.";
85 return false;
86 }
87 }
88
89 var keyPart = parts[^1];
90 var keyName = keyPart.Length == 1 ? keyPart.ToUpperInvariant() : keyPart.ToUpperInvariant().Replace(" ", "");
91 if (!Enum.TryParse<Key>(keyName, true, out key))
92 {
93 error = $"Unknown key: {keyPart}. Use e.g. Enter, Tab, F4, A.";
94 return false;
95 }
96
97 return true;
98 }
99
100}
101
View only · write via MCP/CIDE