26 if (Enum.TryParse<Key>(keyName,
true, out var key))
29 Engine.
Logger.LogWarning(
"Invalid Avalonia key name: {KeyName}", keyName);
33 private readonly Control _lifetimeOwner;
34 private TopLevel? _topLevel;
37 private readonly
int[] _down =
new int[512];
40 private int _modsBits;
42 private bool _isDisposed;
60 _lifetimeOwner = lifetimeOwner ??
throw new ArgumentNullException(nameof(lifetimeOwner));
62 _lifetimeOwner.AttachedToVisualTree += OnAttachedToVisualTree;
63 _lifetimeOwner.DetachedFromVisualTree += OnDetachedFromVisualTree;
66 if (TopLevel.GetTopLevel(_lifetimeOwner) !=
null)
69 Engine.
Logger.LogInformation(
"AvaloniaKeyboardAdapter initialized.");
72 private void OnAttachedToVisualTree(
object? sender, VisualTreeAttachmentEventArgs e)
73 => ConnectToTopLevel();
75 private void OnDetachedFromVisualTree(
object? sender, VisualTreeAttachmentEventArgs e)
76 => DisconnectFromTopLevel();
78 private void ConnectToTopLevel()
80 if (_isDisposed)
return;
82 var tl = TopLevel.GetTopLevel(_lifetimeOwner);
83 if (tl ==
null || ReferenceEquals(tl, _topLevel))
return;
86 tl.AddHandler(InputElement.KeyDownEvent, OnKeyDown, RoutingStrategies.Tunnel);
87 tl.AddHandler(InputElement.KeyUpEvent, OnKeyUp, RoutingStrategies.Tunnel);
90 private void DisconnectFromTopLevel()
92 if (_topLevel ==
null)
return;
94 _topLevel.RemoveHandler(InputElement.KeyDownEvent, OnKeyDown);
95 _topLevel.RemoveHandler(InputElement.KeyUpEvent, OnKeyUp);
99 private void OnKeyDown(
object? sender, KeyEventArgs e)
101 if (_isDisposed)
return;
102 SetDown((
int)e.Key,
true);
103 UpdateMods(e.KeyModifiers);
106 private void OnKeyUp(
object? sender, KeyEventArgs e)
108 if (_isDisposed)
return;
109 SetDown((
int)e.Key,
false);
110 UpdateMods(e.KeyModifiers);
119 [MethodImpl(MethodImplOptions.AggressiveInlining)]
122 if ((uint)keyCode >= (uint)_down.Length)
return false;
123 return Volatile.Read(ref _down[keyCode]) != 0;
126 [MethodImpl(MethodImplOptions.AggressiveInlining)]
127 private void SetDown(
int keyCode,
bool down)
129 if ((uint)keyCode >= (uint)_down.Length)
return;
130 Volatile.Write(ref _down[keyCode], down ? 1 : 0);
133 [MethodImpl(MethodImplOptions.AggressiveInlining)]
134 private void UpdateMods(KeyModifiers km)
140 Volatile.Write(ref _modsBits, mods);
148 if (_isDisposed)
return;
152 DisconnectFromTopLevel();
153 _lifetimeOwner.AttachedToVisualTree -= OnAttachedToVisualTree;
154 _lifetimeOwner.DetachedFromVisualTree -= OnDetachedFromVisualTree;
156 Engine.
Logger.LogInformation(
"AvaloniaKeyboardAdapter disposed.");