From 52762d7c02515474e88e300e41d859e58235fdd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Aug 2024 15:09:17 +0200 Subject: [PATCH 1/2] Add failing test case --- .../Visual/UserInterface/TestSceneTextBox.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs index 511a99dca7..1242f984f3 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs @@ -932,6 +932,76 @@ public void TestTypingCancelsOngoingDragSelection() AddAssert("text selected by drag", () => textBox.SelectedText == "1"); } + [Test] + public void TestTabbing() + { + AddStep("add textboxes", () => + { + textBoxes.AddRange([ + new InsertableTextBox + { + Size = new Vector2(300, 40), + Text = "first!", + ReadOnly = false, + TabbableContentContainer = textBoxes, + }, + new InsertableTextBox + { + Size = new Vector2(300, 40), + Text = "second!", + ReadOnly = false, + TabbableContentContainer = textBoxes, + }, + new InsertableTextBox + { + Size = new Vector2(300, 40), + Text = "third! (readonly)", + ReadOnly = true, + TabbableContentContainer = textBoxes, + }, + new InsertableTextBox + { + Size = new Vector2(300, 40), + Text = "fourth!", + ReadOnly = false, + TabbableContentContainer = textBoxes, + } + ]); + }); + + AddStep("focus first textbox", () => + { + InputManager.MoveMouseTo(textBoxes[0]); + InputManager.Click(MouseButton.Left); + }); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + AddAssert("second textbox focused", () => textBoxes[1].HasFocus); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + AddAssert("readonly textbox skipped", () => textBoxes[3].HasFocus); + + AddStep("press tab", () => InputManager.Key(Key.Tab)); + AddAssert("first textbox focused", () => textBoxes[0].HasFocus); + + AddStep("press shift-tab", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Tab); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + AddAssert("fourth textbox focused", () => textBoxes[3].HasFocus); + + AddStep("hide second textbox", () => textBoxes[1].Alpha = 0); + AddStep("press shift-tab", () => + { + InputManager.PressKey(Key.ShiftLeft); + InputManager.Key(Key.Tab); + InputManager.ReleaseKey(Key.ShiftLeft); + }); + AddAssert("first textbox focused", () => textBoxes[0].HasFocus); + } + private void prependString(InsertableTextBox textBox, string text) { InputManager.Keys(PlatformAction.MoveBackwardLine); From c532d8a93977ff4f9f66cebfb6b09541ced5e4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 20 Aug 2024 15:11:22 +0200 Subject: [PATCH 2/2] Fix tabbable container not checking if its next tab stop is focusable Closes https://github.com/ppy/osu/issues/29501. --- .../Graphics/Containers/TabbableContainer.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Framework/Graphics/Containers/TabbableContainer.cs b/osu.Framework/Graphics/Containers/TabbableContainer.cs index 14c1335af2..9a49804fb6 100644 --- a/osu.Framework/Graphics/Containers/TabbableContainer.cs +++ b/osu.Framework/Graphics/Containers/TabbableContainer.cs @@ -44,13 +44,14 @@ protected override bool OnKeyDown(KeyDownEvent e) if (TabbableContentContainer == null || e.Key != Key.Tab) return false; - var nextTab = nextTabStop(TabbableContentContainer, e.ShiftPressed); - if (nextTab != null) GetContainingFocusManager().AsNonNull().ChangeFocus(nextTab); + moveToNextTabStop(TabbableContentContainer, e.ShiftPressed); return true; } - private Drawable nextTabStop(CompositeDrawable target, bool reverse) + private void moveToNextTabStop(CompositeDrawable target, bool reverse) { + var focusManager = GetContainingFocusManager().AsNonNull(); + Stack stack = new Stack(); stack.Push(target); // Extra push for circular tabbing stack.Push(target); @@ -63,8 +64,8 @@ private Drawable nextTabStop(CompositeDrawable target, bool reverse) if (!started) started = ReferenceEquals(drawable, this); - else if (drawable is ITabbableContainer tabbable && tabbable.CanBeTabbedTo) - return drawable; + else if (drawable is ITabbableContainer tabbable && tabbable.CanBeTabbedTo && focusManager.ChangeFocus(drawable)) + return; if (drawable is CompositeDrawable composite) { @@ -91,8 +92,6 @@ private Drawable nextTabStop(CompositeDrawable target, bool reverse) } } } - - return null; } } }