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
27 changes: 27 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.OrangeRed,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand All @@ -72,6 +73,7 @@ public TestSceneSliderBar()
RangePadding = 20,
BackgroundColour = Color4.White,
SelectionColour = Color4.Pink,
FocusColour = Color4.OrangeRed,
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.OrangeRed,
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.OrangeRed,
KeyboardStep = 1,
Current = sliderBarValue
},
Expand All @@ -109,6 +113,8 @@ public TestSceneSliderBar()
{
sliderBar.Current.Disabled = false;
sliderBar.Current.Value = 0;
sliderBar.GetContainingFocusManager()!.ChangeFocus(null);
sliderBarWithNub.GetContainingFocusManager()!.ChangeFocus(null);
});

[Test]
Expand All @@ -122,6 +128,7 @@ public void TestVerticalDragHasNoEffect()
() => { InputManager.MoveMouseTo(sliderBar.ToScreenSpace(sliderBar.DrawSize * new Vector2(0.75f, 1f))); });
AddStep("Release Click", () => { InputManager.ReleaseButton(MouseButton.Left); });
checkValue(0);
AddAssert("Slider has no focus", () => !sliderBar.HasFocus);
}

[Test]
Expand All @@ -136,6 +143,7 @@ public void TestDragOutReleaseInHasNoEffect()
AddStep("Drag Up", () => { InputManager.MoveMouseTo(sliderBar.ToScreenSpace(sliderBar.DrawSize * new Vector2(0.25f, 0.5f))); });
AddStep("Release Click", () => { InputManager.ReleaseButton(MouseButton.Left); });
checkValue(0);
AddAssert("Slider has focus", () => sliderBar.HasFocus);
}

[Test]
Expand All @@ -160,6 +168,23 @@ public void TestKeyboardInput()
InputManager.ReleaseKey(Key.Right);
});
checkValue(1);

AddStep("Click slider", () => InputManager.Click(MouseButton.Left));
checkValue(-5);

AddAssert("Slider has focus", () => sliderBar.HasFocus);

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(-4);
}

[TestCase(false)]
Expand Down Expand Up @@ -246,6 +271,7 @@ public void TestAbsoluteDrag()
() => { InputManager.MoveMouseTo(sliderBarWithNub.ToScreenSpace(sliderBarWithNub.DrawSize * new Vector2(0.4f, 1f))); });
AddStep("Release Click", () => { InputManager.ReleaseButton(MouseButton.Left); });
checkValue(-2);
AddAssert("Slider has focus", () => sliderBarWithNub.HasFocus);
}

[Test]
Expand All @@ -259,6 +285,7 @@ public void TestRelativeDrag()
() => { InputManager.MoveMouseTo(sliderBarWithNub.ToScreenSpace(sliderBarWithNub.DrawSize * new Vector2(0.75f, 1f))); });
AddStep("Release Click", () => { InputManager.ReleaseButton(MouseButton.Left); });
checkValue(3);
AddAssert("Slider has focus", () => sliderBarWithNub.HasFocus);
}

[Test]
Expand Down
42 changes: 41 additions & 1 deletion 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 @@ -23,6 +24,18 @@ public Color4 SelectionColour
set => SelectionBox.Colour = value;
}

private Color4 focusColour = FrameworkColour.YellowGreen;

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

protected readonly Box SelectionBox;
protected readonly Box Box;

Expand All @@ -37,10 +50,37 @@ public BasicSliderBar()
},
SelectionBox = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = FrameworkColour.Yellow,
RelativeSizeAxes = Axes.Both,
}
};

Masking = true;
}

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

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

private void updateFocus()
{
if (HasFocus)
{
BorderThickness = 3;
BorderColour = FocusColour;
}
else
{
BorderThickness = 0;
}
}

protected override void UpdateValue(float value)
Expand Down
5 changes: 4 additions & 1 deletion osu.Framework/Graphics/UserInterface/SliderBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,21 @@ protected override bool OnDragStart(DragStartEvent e)
return false;
}

GetContainingFocusManager()?.ChangeFocus(this);
handleMouseInput(e);
return true;
}

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