Browse Source

Don't focus unfocusable controls.

- Check `CanFocus` in `FocusManager.SetFocusedElement`
- Check for `IsEffectivelyVisible` in `CanFocus`
- Clear focus when control made invisible
- Update tests that relied on unfocusable controls being focused
pull/11287/head
Steven Kirk 3 years ago
parent
commit
531fed2b4e
  1. 7
      src/Avalonia.Base/Input/FocusManager.cs
  2. 4
      src/Avalonia.Base/Input/InputElement.cs
  3. 1
      tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
  4. 1
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
  5. 8
      tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs
  6. 4
      tests/Avalonia.LeakTests/ControlTests.cs

7
src/Avalonia.Base/Input/FocusManager.cs

@ -122,6 +122,11 @@ namespace Avalonia.Input
{
scope = scope ?? throw new ArgumentNullException(nameof(scope));
if (element is not null && !CanFocus(element))
{
return;
}
if (_focusScopes.TryGetValue(scope, out var existingElement))
{
if (element != existingElement)
@ -242,6 +247,6 @@ namespace Avalonia.Input
}
}
private static bool IsVisible(IInputElement e) => (e as Visual)?.IsVisible ?? true;
private static bool IsVisible(IInputElement e) => (e as Visual)?.IsEffectivelyVisible ?? true;
}
}

4
src/Avalonia.Base/Input/InputElement.cs

@ -647,6 +647,10 @@ namespace Avalonia.Input
{
PseudoClasses.Set(":focus-within", change.GetNewValue<bool>());
}
else if (change.Property == IsVisibleProperty && !change.GetNewValue<bool>() && IsFocused)
{
FocusManager.Instance?.Focus(null);
}
}
/// <summary>

1
tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs

@ -657,7 +657,6 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTemplate(),
Text = "1234",
IsVisible = false
};
var root = new TestRoot { Child = target1 };

1
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -594,7 +594,6 @@ namespace Avalonia.Controls.UnitTests
{
Template = CreateTemplate(),
Text = "1234",
IsVisible = false
};
var root = new TestRoot { Child = target1 };

8
tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

@ -298,7 +298,9 @@ namespace Avalonia.Controls.UnitTests
using var app = App();
var (target, scroll, itemsControl) = CreateTarget();
target.GetRealizedElements().First()!.Focus();
var focused = target.GetRealizedElements().First()!;
focused.Focusable = true;
focused.Focus();
Assert.True(target.GetRealizedElements().First()!.IsKeyboardFocusWithin);
scroll.Offset = new Vector(0, 200);
@ -314,6 +316,7 @@ namespace Avalonia.Controls.UnitTests
var (target, scroll, itemsControl) = CreateTarget();
var focused = target.GetRealizedElements().First()!;
focused.Focusable = true;
focused.Focus();
Assert.True(focused.IsKeyboardFocusWithin);
@ -331,6 +334,7 @@ namespace Avalonia.Controls.UnitTests
var (target, scroll, itemsControl) = CreateTarget();
var focused = target.GetRealizedElements().First()!;
focused.Focusable = true;
focused.Focus();
Assert.True(focused.IsKeyboardFocusWithin);
@ -350,12 +354,14 @@ namespace Avalonia.Controls.UnitTests
var (target, scroll, itemsControl) = CreateTarget();
var originalFocused = target.GetRealizedElements().First()!;
originalFocused.Focusable = true;
originalFocused.Focus();
scroll.Offset = new Vector(0, 500);
Layout(target);
var newFocused = target.GetRealizedElements().First()!;
newFocused.Focusable = true;
newFocused.Focus();
Assert.False(originalFocused.IsVisible);

4
tests/Avalonia.LeakTests/ControlTests.cs

@ -558,7 +558,7 @@ namespace Avalonia.LeakTests
control.ContextMenu = null;
}
var window = new Window();
var window = new Window { Focusable = true };
window.Show();
Assert.Same(window, FocusManager.Instance.Current);
@ -605,7 +605,7 @@ namespace Avalonia.LeakTests
contextMenu.Close();
}
var window = new Window();
var window = new Window { Focusable = true };
window.Show();
Assert.Same(window, FocusManager.Instance.Current);

Loading…
Cancel
Save