diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs
index 70a1b702a7..511a99dca7 100644
--- a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs
+++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs
@@ -881,6 +881,57 @@ public void TestCursorMovementWithSelection()
AddAssert("second-from-last word selected", () => textBox.SelectedText == "bank");
}
+ [Test]
+ public void TestTypingCancelsOngoingDragSelection()
+ {
+ InsertableTextBox textBox = null;
+
+ AddStep("add textbox", () =>
+ {
+ textBoxes.Add(textBox = new InsertableTextBox
+ {
+ Size = new Vector2(300, 40),
+ Text = "123",
+ ReadOnly = false
+ });
+ });
+
+ AddStep("focus textbox", () =>
+ {
+ InputManager.MoveMouseTo(textBox);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ // drag text, insert, keep mouse held, drag more and ensure it's ignored
+ AddStep("hold from middle of textbox", () => InputManager.PressButton(MouseButton.Left));
+ AddStep("move mouse to left of textbox", () => InputManager.MoveMouseTo(textBox.ScreenSpaceDrawQuad.TopLeft - new Vector2(20f, 0f)));
+ AddAssert("text selected by drag", () => textBox.SelectedText == "123");
+ AddStep("insert character", () => textBox.InsertString("1"));
+ AddAssert("text overwritten", () => textBox.Text == "1");
+ AddStep("move mouse a little", () => InputManager.MoveMouseTo(InputManager.CurrentState.Mouse.Position - new Vector2(10f, 0f)));
+ AddAssert("text not selected by drag", () => string.IsNullOrEmpty(textBox.SelectedText));
+ AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
+
+ // drag text, release mouse, insert, drag again and ensure dragging still works
+ AddStep("hold from middle of textbox", () =>
+ {
+ InputManager.MoveMouseTo(textBox);
+ InputManager.PressButton(MouseButton.Left);
+ });
+ AddStep("drag again", () => InputManager.MoveMouseTo(textBox.ScreenSpaceDrawQuad.TopLeft - new Vector2(20f, 0f)));
+ AddAssert("text selected by drag", () => textBox.SelectedText == "1");
+ AddStep("release mouse", () => InputManager.ReleaseButton(MouseButton.Left));
+ AddStep("insert character", () => textBox.InsertString("1"));
+ AddAssert("text overwritten", () => textBox.Text == "1");
+ AddStep("hold from middle of textbox", () =>
+ {
+ InputManager.MoveMouseTo(textBox);
+ InputManager.PressButton(MouseButton.Left);
+ });
+ AddStep("drag again", () => InputManager.MoveMouseTo(textBox.ScreenSpaceDrawQuad.TopLeft - new Vector2(20f, 0f)));
+ AddAssert("text selected by drag", () => textBox.SelectedText == "1");
+ }
+
private void prependString(InsertableTextBox textBox, string text)
{
InputManager.Keys(PlatformAction.MoveBackwardLine);
diff --git a/osu.Framework/Audio/Sample/SampleChannelBass.cs b/osu.Framework/Audio/Sample/SampleChannelBass.cs
index ee9bc84c7b..f08f5baa49 100644
--- a/osu.Framework/Audio/Sample/SampleChannelBass.cs
+++ b/osu.Framework/Audio/Sample/SampleChannelBass.cs
@@ -19,7 +19,18 @@ internal sealed class SampleChannelBass : SampleChannel, IBassAudioChannel
///
/// This is set to true immediately upon , but the channel may not be audibly playing yet.
///
- public override bool Playing => playing || enqueuedPlaybackStart;
+ public override bool Playing
+ {
+ get
+ {
+ // When short samples loop (especially within mixers), there's a small window where the ChannelIsActive state could be Stopped.
+ // In order to not provide a "stale" value here, we'll not trust the internal playing state from BASS.
+ if (Looping && userRequestedPlay)
+ return true;
+
+ return playing || enqueuedPlaybackStart;
+ }
+ }
private volatile bool playing;
diff --git a/osu.Framework/Graphics/UserInterface/TextBox.cs b/osu.Framework/Graphics/UserInterface/TextBox.cs
index 98ffaca2ef..e825299cd2 100644
--- a/osu.Framework/Graphics/UserInterface/TextBox.cs
+++ b/osu.Framework/Graphics/UserInterface/TextBox.cs
@@ -722,6 +722,8 @@ private void endTextChange(bool started)
textChanging = false;
}
+ private bool ignoreOngoingDragSelection;
+
///
/// Removes the selected text if a selection persists.
///
@@ -868,7 +870,9 @@ private void insertString(string value, Action drawableCreationParamet
drawableCreationParameters?.Invoke(drawable);
text = text.Insert(selectionLeft, c.ToString());
+
selectionStart = selectionEnd = selectionLeft + 1;
+ ignoreOngoingDragSelection = true;
cursorAndLayout.Invalidate();
}
@@ -1188,6 +1192,17 @@ protected override void OnKeyUp(KeyUpEvent e)
base.OnKeyUp(e);
}
+ protected override bool OnDragStart(DragStartEvent e)
+ {
+ ignoreOngoingDragSelection = false;
+
+ if (HasFocus)
+ return true;
+
+ Vector2 posDiff = e.MouseDownPosition - e.MousePosition;
+ return Math.Abs(posDiff.X) > Math.Abs(posDiff.Y);
+ }
+
protected override void OnDrag(DragEvent e)
{
if (ReadOnly)
@@ -1195,6 +1210,9 @@ protected override void OnDrag(DragEvent e)
FinalizeImeComposition(true);
+ if (ignoreOngoingDragSelection)
+ return;
+
var lastSelectionBounds = getTextSelectionBounds();
if (doubleClickWord != null)
@@ -1233,15 +1251,6 @@ protected override void OnDrag(DragEvent e)
onTextSelectionChanged(doubleClickWord != null ? TextSelectionType.Word : TextSelectionType.Character, lastSelectionBounds);
}
- protected override bool OnDragStart(DragStartEvent e)
- {
- if (HasFocus) return true;
-
- Vector2 posDiff = e.MouseDownPosition - e.MousePosition;
-
- return Math.Abs(posDiff.X) > Math.Abs(posDiff.Y);
- }
-
protected override bool OnDoubleClick(DoubleClickEvent e)
{
FinalizeImeComposition(true);