Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow slider bar to take focus and accept keyboard input while not hovered #6390

Merged
merged 8 commits into from
Oct 24, 2024
20 changes: 20 additions & 0 deletions osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public TestSceneSliderBar()
Size = new Vector2(200, 50),
BackgroundColour = Color4.White,
SelectionColour = Color4.Pink,
FocusColour = Color4.Purple,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand All @@ -72,6 +73,7 @@ public TestSceneSliderBar()
RangePadding = 20,
BackgroundColour = Color4.White,
SelectionColour = Color4.Pink,
FocusColour = Color4.Purple,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand All @@ -85,6 +87,7 @@ public TestSceneSliderBar()
Size = new Vector2(200, 10),
BackgroundColour = Color4.White,
SelectionColour = Color4.Pink,
FocusColour = Color4.Purple,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand All @@ -97,6 +100,7 @@ public TestSceneSliderBar()
Size = new Vector2(200, 10),
BackgroundColour = Color4.White,
SelectionColour = Color4.Pink,
FocusColour = Color4.Purple,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand Down Expand Up @@ -141,6 +145,8 @@ public void TestDragOutReleaseInHasNoEffect()
[Test]
public void TestKeyboardInput()
{
AddStep("Unfocus slider", () => sliderBar.GetContainingFocusManager()!.ChangeFocus(null));

AddStep("Press right arrow key", () =>
{
InputManager.PressKey(Key.Right);
Expand All @@ -160,6 +166,20 @@ public void TestKeyboardInput()
InputManager.ReleaseKey(Key.Right);
});
checkValue(1);

AddStep("Focus slider", () => sliderBar.GetContainingFocusManager()!.ChangeFocus(sliderBar));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should test click by not using programmed focus:

diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs
index 797cba1c4..e63e8bbec 100644
--- a/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs
+++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneSliderBar.cs
@@ -169,7 +169,9 @@ public void TestKeyboardInput()
             });
             checkValue(1);
 
-            AddStep("Focus slider", () => sliderBar.GetContainingFocusManager()!.ChangeFocus(sliderBar));
+            AddStep("Click slider", () => InputManager.Click(MouseButton.Left));
+
+            AddAssert("Slider has focus", () => sliderBar.HasFocus);
 
             AddStep("move mouse outside", () =>
             {
@@ -181,7 +183,7 @@ public void TestKeyboardInput()
                 InputManager.PressKey(Key.Right);
                 InputManager.ReleaseKey(Key.Right);
             });
-            checkValue(2);
+            checkValue(-4);
         }
 
         [TestCase(false)]


AddStep("move mouse outside", () =>
{
InputManager.MoveMouseTo(sliderBar.ToScreenSpace(sliderBar.DrawSize * new Vector2(2f, 0.5f)));
});

AddStep("Press right arrow key", () =>
{
InputManager.PressKey(Key.Right);
InputManager.ReleaseKey(Key.Right);
});
checkValue(2);
}

[TestCase(false)]
Expand Down
43 changes: 40 additions & 3 deletions osu.Framework/Graphics/UserInterface/BasicSliderBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Numerics;
using osuTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using Vector2 = osuTK.Vector2;

namespace osu.Framework.Graphics.UserInterface
Expand All @@ -17,10 +18,28 @@ public Color4 BackgroundColour
set => Box.Colour = value;
}

private Color4 selectionColour = FrameworkColour.Yellow;

public Color4 SelectionColour
{
get => SelectionBox.Colour;
set => SelectionBox.Colour = value;
get => selectionColour;
set
{
selectionColour = value;
updateColour();
}
}

private Color4 focusColour = FrameworkColour.YellowGreen;

public Color4 FocusColour
{
get => focusColour;
set
{
focusColour = value;
updateColour();
}
}

protected readonly Box SelectionBox;
Expand All @@ -38,9 +57,27 @@ public BasicSliderBar()
SelectionBox = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = FrameworkColour.Yellow,
}
};

updateColour();
}

private void updateColour()
{
SelectionBox.Colour = HasFocus ? FocusColour : SelectionColour;
}

protected override void OnFocus(FocusEvent e)
{
updateColour();
base.OnFocus(e);
}

protected override void OnFocusLost(FocusLostEvent e)
{
updateColour();
base.OnFocusLost(e);
}

protected override void UpdateValue(float value)
Expand Down
4 changes: 3 additions & 1 deletion osu.Framework/Graphics/UserInterface/SliderBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,14 @@ protected override bool OnDragStart(DragStartEvent e)

protected override void OnDragEnd(DragEndEvent e) => Commit();

public override bool AcceptsFocus => true;

protected override bool OnKeyDown(KeyDownEvent e)
{
if (currentNumberInstantaneous.Disabled)
return false;

if (!IsHovered)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably early return if not focused. Pressing left/right randomly in settings can unintentionally change a slider.

if (!IsHovered && !HasFocus)
return false;

float step = KeyboardStep != 0 ? KeyboardStep : (Convert.ToSingle(currentNumberInstantaneous.MaxValue) - Convert.ToSingle(currentNumberInstantaneous.MinValue)) / 20;
Expand Down
Loading