Browse Source

Merge pull request #11465 from AvaloniaUI/fixes/11290-tab-focus-from-nothing

Focus first child from no focus.
Max Katz 2 years ago
parent
commit
f63cca9b6f

+ 8 - 6
src/Avalonia.Base/Input/KeyboardNavigationHandler.cs

@@ -77,13 +77,16 @@ namespace Avalonia.Input
         /// <param name="direction">The direction to move.</param>
         /// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
         public void Move(
-            IInputElement element,
+            IInputElement? element,
             NavigationDirection direction,
             KeyModifiers keyModifiers = KeyModifiers.None)
         {
-            element = element ?? throw new ArgumentNullException(nameof(element));
+            if (element is null && _owner is null)
+            {
+                return;
+            }
 
-            var next = GetNext(element, direction);
+            var next = GetNext(element ?? _owner!, direction);
 
             if (next != null)
             {
@@ -101,10 +104,9 @@ namespace Avalonia.Input
         /// <param name="e">The event args.</param>
         protected virtual void OnKeyDown(object? sender, KeyEventArgs e)
         {
-            var current = FocusManager.GetFocusManager(e.Source as IInputElement)?.GetFocusedElement();
-
-            if (current != null && e.Key == Key.Tab)
+            if (e.Key == Key.Tab)
             {
+                var current = FocusManager.GetFocusManager(e.Source as IInputElement)?.GetFocusedElement();
                 var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ?
                     NavigationDirection.Next : NavigationDirection.Previous;
                 Move(current, direction, e.KeyModifiers);

+ 20 - 0
tests/Avalonia.Base.UnitTests/Input/KeyboardNavigationTests_Tab.cs

@@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using Avalonia.Controls;
 using Avalonia.Input;
+using Avalonia.UnitTests;
 using Xunit;
 
 namespace Avalonia.Base.UnitTests.Input
@@ -1253,5 +1254,24 @@ namespace Avalonia.Base.UnitTests.Input
 
             Assert.Same(expected, result);
         }
+
+        [Fact]
+        public void Focuses_First_Child_From_No_Focus()
+        {
+            using var app = UnitTestApplication.Start(TestServices.RealFocus);
+            var button = new Button();
+            var root = new TestRoot(button);
+            var target = new KeyboardNavigationHandler();
+
+            target.SetOwner(root);
+
+            root.RaiseEvent(new KeyEventArgs
+            {
+                RoutedEvent = InputElement.KeyDownEvent,
+                Key = Key.Tab,
+            });
+
+            Assert.True(button.IsFocused);
+        }
     }
 }