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);