Browse Source

XYFocus should skip effectively disabled controls (#20241)

* Added failing unit test

* Changed IsValidCandidate to check effective values

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
pull/20295/head
IanRawley 2 months ago
committed by GitHub
parent
commit
7a340a6579
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/Avalonia.Base/Input/Navigation/XYFocus.FindElements.cs
  2. 40
      tests/Avalonia.Base.UnitTests/Input/KeyboardNavigationTests_XY.cs

2
src/Avalonia.Base/Input/Navigation/XYFocus.FindElements.cs

@ -65,7 +65,7 @@ public partial class XYFocus
private static bool IsValidCandidate(InputElement candidate, KeyDeviceType? inputKeyDeviceType)
{
return candidate.Focusable && candidate.IsEnabled && candidate.IsVisible
return candidate.Focusable && candidate.IsEffectivelyEnabled && candidate.IsEffectivelyVisible
// Only allow candidate focus, if original key device type could focus it.
&& XYFocusHelpers.IsAllowedXYNavigationMode(candidate, inputKeyDeviceType);
}

40
tests/Avalonia.Base.UnitTests/Input/KeyboardNavigationTests_XY.cs

@ -459,4 +459,44 @@ public class KeyboardNavigationTests_XY : ScopedTestBase
Assert.Null(KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down));
}
[Fact]
public void XYFocus_Skips_Effectively_Disabled_Controls()
{
using var _ = UnitTestApplication.Start(TestServices.FocusableWindow);
var current = new TestControl() { Height = 20, Width = 20, IsEnabled = true, IsVisible = true, Focusable = true, ShouldEnable = true};
var disabled = new TestControl() { Height = 20, Width = 20, IsEnabled = true, IsVisible = true, Focusable = true, ShouldEnable = false };
var candidate = new TestControl() { Height = 20, Width = 20, IsEnabled = true, IsVisible = true, Focusable = true, ShouldEnable = true };
var parent = new StackPanel
{
Orientation = Orientation.Vertical,
Spacing = 20,
Children = { current, disabled, candidate }
};
var window = new Window
{
[XYFocus.NavigationModesProperty] = XYFocusNavigationModes.Enabled,
Content = parent,
Height = 300
};
window.Show();
Assert.Equal(candidate, KeyboardNavigationHandler.GetNext(current, NavigationDirection.Down));
}
private class TestControl : Decorator
{
private bool _shouldEnable;
public bool ShouldEnable
{
get => _shouldEnable;
set { _shouldEnable = value; UpdateIsEffectivelyEnabled(); }
}
protected override bool IsEnabledCore => IsEnabled && _shouldEnable;
}
}

Loading…
Cancel
Save