diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ButtonTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ButtonTests.cs index 436138be06a..ffde8104417 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ButtonTests.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/ButtonTests.cs @@ -105,7 +105,7 @@ await InputSimulator.SendAsync( }); } - [WinFormsFact(Skip = "https://github.com/dotnet/winforms/issues/8635")] + [WinFormsFact] public async Task Button_AchorNone_NoResizeOnWindowSizeWiderAsync() { await RunTestAsync(async (form, button) => @@ -120,7 +120,7 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseBy(form.DisplayRectangle.Width, 0) + .DragMouseBy(form.DisplayRectangle.Width, 0) .LeftButtonUp()); Assert.True(form.DisplayRectangle.Width > originalFormSize.Width); @@ -129,8 +129,7 @@ await InputSimulator.SendAsync( }); } - [ActiveIssue("https://github.com/dotnet/winforms/issues/6714")] - [WinFormsFact(Skip = "Flaky tests, see: https://github.com/dotnet/winforms/issues/6714")] + [WinFormsFact] public async Task Button_AchorNone_NoResizeOnWindowSizeTallerAsync() { await RunTestAsync(async (form, button) => @@ -145,7 +144,7 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseBy(0, form.DisplayRectangle.Height) + .DragMouseBy(0, form.DisplayRectangle.Height) .LeftButtonUp()); Assert.True(form.DisplayRectangle.Height > originalFormSize.Height); @@ -154,8 +153,7 @@ await InputSimulator.SendAsync( }); } - [ActiveIssue("https://github.com/dotnet/winforms/issues/7297")] - [WinFormsFact(Skip = "Flaky tests, see: https://github.com/dotnet/winforms/issues/7297")] + [WinFormsFact] public async Task Button_Anchor_ResizeOnWindowSizeWiderAsync() { await RunTestAsync(async (form, button) => @@ -172,7 +170,7 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseBy(form.DisplayRectangle.Width, 0) + .DragMouseBy(form.DisplayRectangle.Width, 0) .LeftButtonUp()); Assert.True(form.DisplayRectangle.Width > originalFormSize.Width); @@ -185,8 +183,7 @@ await InputSimulator.SendAsync( }); } - [ActiveIssue("https://github.com/dotnet/winforms/issues/7407")] - [WinFormsFact(Skip = "Flaky tests, see: https://github.com/dotnet/winforms/issues/7407")] + [WinFormsFact] public async Task Button_Anchor_ResizeOnWindowSizeTallerAsync() { await RunTestAsync(async (form, button) => @@ -203,7 +200,7 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseBy(0, form.DisplayRectangle.Height) + .DragMouseBy(0, form.DisplayRectangle.Height) .LeftButtonUp()); Assert.True(form.DisplayRectangle.Height > originalFormSize.Height); @@ -228,13 +225,13 @@ await RunControlPairTestAsync(async (form, controls) => control2.Click += (sender, e) => control2ClickCount++; await MoveMouseToControlAsync(control1); - await InputSimulator.SendAsync(form, inputSimulator => inputSimulator.Mouse.LeftButtonDown().LeftButtonUp()); + await InputSimulator.SendAsync(form, inputSimulator => inputSimulator.Mouse.LeftButtonClick()); Assert.Equal(1, control1ClickCount); Assert.Equal(0, control2ClickCount); await MoveMouseToControlAsync(control2); - await InputSimulator.SendAsync(form, inputSimulator => inputSimulator.Mouse.LeftButtonDown().LeftButtonUp()); + await InputSimulator.SendAsync(form, inputSimulator => inputSimulator.Mouse.LeftButtonClick()); Assert.Equal(1, control1ClickCount); Assert.Equal(1, control2ClickCount); @@ -266,7 +263,7 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseTo(virtualPoint.X, virtualPoint.Y) + .DragMouseTo(virtualPoint.X, virtualPoint.Y) .LeftButtonUp()); Assert.Equal(0, control1ClickCount); @@ -301,8 +298,8 @@ await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .MoveMouseTo(virtualPoint.X, virtualPoint.Y) - .MoveMouseTo(virtualPoint1.X, virtualPoint1.Y) + .DragMouseTo(virtualPoint.X, virtualPoint.Y) + .DragMouseTo(virtualPoint1.X, virtualPoint1.Y) .LeftButtonUp()); Assert.Equal(1, control1ClickCount); diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewTests.cs index a1f9d898f49..b287cf5e0e9 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewTests.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DataGridViewTests.cs @@ -33,7 +33,7 @@ await RunTestAsync(async (form, dataGridView) => // Move mouse cursor over any cell of the first row to trigger a tooltip. await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(targetPoint.X, targetPoint.Y)); + inputSimulator => inputSimulator.Mouse.DragMouseTo(targetPoint.X, targetPoint.Y)); // Close the form to verify no exceptions thrown while showing the tooltip. // Regression test for https://github.com/dotnet/winforms/issues/5496 @@ -62,7 +62,7 @@ await RunTestAsync(async (form, dataGridView) => // Wait 1 second to make sure that the toolTip appeared, it has some delay (500 ms by default). await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(targetPoint.X, targetPoint.Y).Sleep(1000)); + inputSimulator => inputSimulator.Mouse.DragMouseTo(targetPoint.X, targetPoint.Y).Sleep(1000)); // DataGridViewToolTip is private so use the reflection object toolTip = dataGridView.TestAccessor().Dynamic._toolTipControl; diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DesignBehaviorsTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DesignBehaviorsTests.cs index 8285180486a..2a92d2cca56 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DesignBehaviorsTests.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DesignBehaviorsTests.cs @@ -128,17 +128,10 @@ async Task InitiateDrangDropAsync(Form form, Point startCoordinates, Control roo await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) + inputSimulator => inputSimulator.Mouse.DragMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) .LeftButtonDown() - .Sleep(100) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - // The d'n'd is very finicky, and if we just call LeftButtonUp() - // it won't work... It'd for some reason think we'd left the control instead. - // - // To work around it - give it a full second to react and then - // simulate a mouse click. - .Sleep(100) - .LeftButtonClick()); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .LeftButtonUp()); dndSignal.Release(); } diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DragDropTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DragDropTests.cs index f5990c5181d..e439c6f2e6e 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DragDropTests.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/DragDropTests.cs @@ -38,26 +38,22 @@ public async Task DragDrop_QueryDefaultCursors_Async() { await MoveMouseToControlAsync(form.ListDragSource); + // Select the item under the caret await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.LeftButtonDown()); + inputSimulator => inputSimulator.Mouse.LeftButtonClick()); var targetMousePosition = ToVirtualPoint(form.ListDragTarget.PointToScreen(new Point(20, 20))); + await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(targetMousePosition.X - 40, targetMousePosition.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(targetMousePosition.X, targetMousePosition.Y) - .Sleep(DragDropDelayMS) // slight delay so drag&drop triggered - .MoveMouseTo(targetMousePosition.X + 2, targetMousePosition.Y + 2) - .Sleep(DragDropDelayMS) // slight delay so drag&drop triggered - .MoveMouseTo(targetMousePosition.X + 4, targetMousePosition.Y + 4) - .Sleep(DragDropDelayMS) - .LeftButtonUp() - .Sleep(DragDropDelayMS)); + .DragMouseTo(targetMousePosition.X - 40, targetMousePosition.Y) + .DragMouseTo(targetMousePosition.X, targetMousePosition.Y) + .DragMouseTo(targetMousePosition.X + 2, targetMousePosition.Y + 2) + .DragMouseTo(targetMousePosition.X + 4, targetMousePosition.Y + 4) + .LeftButtonUp()); Assert.Equal(1, form.ListDragTarget.Items.Count); }); @@ -115,20 +111,14 @@ public async Task DragDrop_NonSerializedObject_ReturnsExpected_Async() await InputSimulator.SendAsync( form, inputSimulator - => inputSimulator - .Mouse.MoveMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) + => inputSimulator.Mouse + .DragMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .LeftButtonClick() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .LeftButtonUp()); }); Assert.NotNull(data); @@ -229,27 +219,16 @@ await InputSimulator.SendAsync( inputSimulator => inputSimulator.Mouse .MoveMouseToPositionOnVirtualDesktop(virtualPointStart.X, virtualPointStart.Y) - .Sleep(DragDropDelayMS) .LeftButtonDown() - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) .MoveMouseToPositionOnVirtualDesktop(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .LeftButtonClick() - .Sleep(DragDropDelayMS)); + .LeftButtonUp()); Assert.NotNull(dragDropForm); Assert.NotNull(dragDropForm.RichTextBoxDropTarget); @@ -347,20 +326,14 @@ public async Task DragDrop_SerializedObject_ReturnsExpected_Async() await InputSimulator.SendAsync( form, inputSimulator - => inputSimulator - .Mouse.MoveMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) + => inputSimulator.Mouse + .DragMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .LeftButtonClick() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .LeftButtonUp()); }); Assert.NotNull(data); @@ -417,64 +390,34 @@ public async Task DragEnter_Set_DropImageType_Message_MessageReplacementToken_Re await InputSimulator.SendAsync( form, inputSimulator - => inputSimulator - .Mouse.MoveMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) + => inputSimulator.Mouse + .DragMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - // The drag and drop is very finicky, and if we just call LeftButtonUp() - // it won't work... It'd for some reason think we'd left the control instead. - // - // To work around it - give it a full second to react and then - // simulate a mouse click. - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .LeftButtonClick() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .LeftButtonUp()); await InputSimulator.SendAsync( form, inputSimulator - => inputSimulator - .Mouse.MoveMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) + => inputSimulator.Mouse + .DragMouseTo(virtualPointStart.X + 6, virtualPointStart.Y + 6) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - // The drag and drop is very finicky, and if we just call LeftButtonUp() - // it won't work... It'd for some reason think we'd left the control instead. - // - // To work around it - give it a full second to react and then - // simulate a mouse click. - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) - .Sleep(DragDropDelayMS) - .LeftButtonClick() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .DragMouseTo(virtualPointEnd.X + 2, virtualPointEnd.Y + 2) + .DragMouseTo(virtualPointEnd.X + 4, virtualPointEnd.Y + 4) + .LeftButtonUp()); Assert.Equal(2, form.ListDragTarget.Items.Count); }); @@ -496,13 +439,10 @@ public async Task PictureBox_SetData_DoDragDrop_RichTextBox_ReturnsExptected_Asy Point virtualPointEnd = ToVirtualPoint(startCoordinates); await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(virtualPointStart.X, virtualPointStart.Y) + inputSimulator => inputSimulator.Mouse.DragMouseTo(virtualPointStart.X, virtualPointStart.Y) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .LeftButtonUp() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .LeftButtonUp()); Assert.NotNull(form); Assert.NotNull(form.RichTextBoxDropTarget); @@ -527,8 +467,7 @@ public async Task ToolStripItem_SetData_DoDragDrop_RichTextBox_ReturnsExptected_ await MoveMouseToControlAsync(form.ToolStrip); await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.LeftButtonClick() - .Sleep(DragDropDelayMS)); + inputSimulator => inputSimulator.Mouse.LeftButtonClick()); Point toolStripItemCoordinates = form.ToolStrip.PointToScreen(new Point(5, 5)); toolStripItemCoordinates.Offset(0, 40); @@ -536,20 +475,17 @@ await InputSimulator.SendAsync( await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(virtualToolStripItemCoordinates.X, virtualToolStripItemCoordinates.Y)); + inputSimulator => inputSimulator.Mouse.DragMouseTo(virtualToolStripItemCoordinates.X, virtualToolStripItemCoordinates.Y)); Point virtualPointStart = virtualToolStripItemCoordinates; toolStripItemCoordinates.Offset(50, 50); Point virtualPointEnd = ToVirtualPoint(toolStripItemCoordinates); await InputSimulator.SendAsync( form, - inputSimulator => inputSimulator.Mouse.MoveMouseTo(virtualPointStart.X, virtualPointStart.Y) + inputSimulator => inputSimulator.Mouse.DragMouseTo(virtualPointStart.X, virtualPointStart.Y) .LeftButtonDown() - .Sleep(DragDropDelayMS) - .MoveMouseTo(virtualPointEnd.X, virtualPointEnd.Y) - .Sleep(DragDropDelayMS) - .LeftButtonUp() - .Sleep(DragDropDelayMS)); + .DragMouseTo(virtualPointEnd.X, virtualPointEnd.Y) + .LeftButtonUp()); Assert.NotNull(form); Assert.NotNull(form.RichTextBoxDropTarget); @@ -956,6 +892,9 @@ private void ListDragTarget_DragEnter(object? sender, DragEventArgs e) // Reset the label text. DropLocationLabel.Text = "None"; + + // Also treat this as a DragOver to start the drag/drop operation + ListDragTarget_DragOver(sender, e); } private void ListDragTarget_DragLeave(object? sender, EventArgs e) diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/IMouseSimulatorExtensions.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/IMouseSimulatorExtensions.cs new file mode 100644 index 00000000000..7ae45bdef0b --- /dev/null +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/IMouseSimulatorExtensions.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using WindowsInput; + +// Work around for global usings breaking things +using ThreadState = System.Diagnostics.ThreadState; + +namespace System.Windows.Forms.UITests +{ + internal static class IMouseSimulatorExtensions + { + public static IMouseSimulator DragMouseBy(this IMouseSimulator simulator, int pixelDeltaX, int pixelDeltaY) + { + simulator.MoveMouseBy(pixelDeltaX, pixelDeltaY); + + // Wait for the message to be processed. Since this is a drag operation, it is possible for the main thread + // to busy-wait for additional mouse messages during the handling of the previous message, so we block for + // a short timeout before silently allowing more messages to be sent. + simulator.WaitForInputIdle(throwOnTimeOut: false, TimeSpan.FromMilliseconds(200)); + + return simulator; + } + + public static IMouseSimulator DragMouseTo(this IMouseSimulator simulator, double absoluteX, double absoluteY) + { + simulator.MoveMouseTo(absoluteX, absoluteY); + + // Wait for the message to be processed. Since this is a drag operation, it is possible for the main thread + // to busy-wait for additional mouse messages during the handling of the previous message, so we block for + // a short timeout before silently allowing more messages to be sent. + simulator.WaitForInputIdle(throwOnTimeOut: false, TimeSpan.FromMilliseconds(200)); + + return simulator; + } + + private static IMouseSimulator WaitForInputIdle(this IMouseSimulator simulator, bool throwOnTimeOut, TimeSpan timeout) + { + using var process = Process.GetCurrentProcess(); + return WaitForInputIdle(simulator, throwOnTimeOut, (HWND)process.MainWindowHandle, timeout); + } + + private static IMouseSimulator WaitForInputIdle(this IMouseSimulator simulator, bool throwOnTimeOut, HWND activeWindow, TimeSpan timeout) + { + var stopwatch = Stopwatch.StartNew(); + var threadId = PInvoke.GetWindowThreadProcessId(activeWindow, out var processId); + if (threadId == 0) + return simulator; + + while (true) + { + if (IsThreadIdle(processId, threadId)) + return simulator; + + if (stopwatch.Elapsed >= timeout) + { + break; + } + + Thread.Sleep(TimeSpan.FromMilliseconds(15)); + } + + if (throwOnTimeOut) + throw new TimeoutException(); + + return simulator; + } + + private static bool IsThreadIdle(uint processId, uint threadId) + { + using var process = Process.GetProcessById((int)processId); + var thread = process.Threads.Cast().FirstOrDefault(t => threadId == t.Id); + if (thread is null) + return true; + + return thread is null + || thread is { ThreadState: ThreadState.Wait, WaitReason: ThreadWaitReason.UserRequest }; + } + } +} diff --git a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/RichTextBoxTests.cs b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/RichTextBoxTests.cs index d83109ed1b7..1997f08578c 100644 --- a/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/RichTextBoxTests.cs +++ b/src/System.Windows.Forms/tests/IntegrationTests/UIIntegrationTests/RichTextBoxTests.cs @@ -55,9 +55,6 @@ await InputSimulator.SendAsync( { await MoveMouseAsync(form, previousPosition); } - - // Let the event queue drain after clicking, before moving the cursor back to the old position. - Application.DoEvents(); } finally { @@ -69,7 +66,6 @@ await InputSimulator.SendAsync( await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse.MoveMouseTo(previousPosition.X, previousPosition.Y)); - Application.DoEvents(); } } @@ -130,9 +126,6 @@ await InputSimulator.SendAsync( { await MoveMouseAsync(form, previousPosition); } - - // Let the event queue drain after clicking, before moving the cursor back to the old position. - Application.DoEvents(); } finally { @@ -144,7 +137,6 @@ await InputSimulator.SendAsync( await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse.MoveMouseTo(previousPosition.X, previousPosition.Y)); - Application.DoEvents(); } } @@ -167,8 +159,7 @@ await InputSimulator.SendAsync( }); } - [ActiveIssue("https://github.com/dotnet/winforms/issues/6609")] - [WinFormsFact(Skip = "Flaky tests, see: https://github.com/dotnet/winforms/issues/6609")] + [WinFormsFact] public async Task RichTextBox_Click_On_Custom_Link_Followed_By_Hidden_Text_Provides_Displayed_Link_SpanAsync() { await RunTestAsync(async (form, richTextBox) => @@ -206,9 +197,6 @@ await InputSimulator.SendAsync( { await MoveMouseAsync(form, previousPosition); } - - // Let the event queue drain after clicking, before moving the cursor back to the old position. - Application.DoEvents(); } finally { @@ -220,7 +208,6 @@ await InputSimulator.SendAsync( await InputSimulator.SendAsync( form, inputSimulator => inputSimulator.Mouse.MoveMouseTo(previousPosition.X, previousPosition.Y)); - Application.DoEvents(); } }