Browse Source
fix(controls): stop HotKeyManager from executing on hidden controls (#21714 )
- Added a check for 'target.IsEffectivelyVisible' inside 'HotkeyCommandWrapper.CanExecute'.
- Prevents HotKey from globally triggering and swallowing keyboard input when the host control or its parent panels are invisible (IsVisible="False").
- Added a corresponding unit test to verify input routing for hidden clickable controls.
Closes #21708
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/21812/head
Autumn
3 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with
42 additions and
1 deletions
src/Avalonia.Controls/HotkeyManager.cs
tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs
@ -38,8 +38,18 @@ namespace Avalonia.Controls
public bool CanExecute ( object? parameter )
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 )
if ( target is ICommandSource commandSource & & commandSource . Command is { } command )
{
{
return commandSource . IsEffectivelyEnabled
return commandSource . IsEffectivelyEnabled
@ -119,5 +119,36 @@ namespace Avalonia.Controls.UnitTests
Assert . True ( hotKeyedTextBox . IsFocused ) ;
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 ) ;
}
}
}
}
}