diff --git a/src/Avalonia.Controls/HotkeyManager.cs b/src/Avalonia.Controls/HotkeyManager.cs index 06ff9cb18c..584a56a135 100644 --- a/src/Avalonia.Controls/HotkeyManager.cs +++ b/src/Avalonia.Controls/HotkeyManager.cs @@ -38,8 +38,18 @@ namespace Avalonia.Controls public bool CanExecute(object? parameter) { - if (reference.Target is { } target) + if (reference.Target is InputElement target) { + var current = target as Visual; + while (current != null && current is not TopLevel) + { + if (!current.IsVisible) + { + return false; + } + current = current.VisualParent; + } + if (target is ICommandSource commandSource && commandSource.Command is { } command) { return commandSource.IsEffectivelyEnabled diff --git a/tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs b/tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs index bdaa8d6a98..d27bc8d85c 100644 --- a/tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs +++ b/tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs @@ -119,5 +119,36 @@ namespace Avalonia.Controls.UnitTests Assert.True(hotKeyedTextBox.IsFocused); } + + [Fact] + public void Hidden_Button_HotKey_Should_Not_Swallow_Input() + { + using var _ = CreateServicesWithFocus(); + + var keyboardDevice = new KeyboardDevice(); + var root = PreparedWindow(); + var panel = new StackPanel { IsVisible = false }; + var button = new Button { HotKey = KeyGesture.Parse("Escape") }; + + bool buttonClicked = false; + button.Click += (s, e) => buttonClicked = true; + + panel.Children.Add(button); + root.Content = panel; + root.Show(); + + keyboardDevice.ProcessRawEvent( + new RawKeyEventArgs( + keyboardDevice, + 0, + root.InputRoot, + RawKeyEventType.KeyDown, + Key.Escape, + RawInputModifiers.None, + PhysicalKey.Escape, + "")); + + Assert.False(buttonClicked); + } } }