Skip to content

Commit 08bc84c

Browse files
authored
Merge pull request #372 from switchifyapp/fix/end-drag-before-click-371
End drag before other mouse clicks
2 parents 7ee4b18 + 6ccd949 commit 08bc84c

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

src/SwitchifyPc.Core/Input/DesktopCommandExecutor.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,20 +148,23 @@ private async Task<CommandExecutionResult> EndDragAsync(CancellationToken cancel
148148

149149
private async Task<CommandExecutionResult> ClickMouseAsync(string button, CancellationToken cancellationToken)
150150
{
151+
await ReleaseDragBeforeClickAsync(cancellationToken);
151152
await adapter.ClickMouseAsync(button, cancellationToken);
152153
cursorOverlay?.Show("click");
153154
return CommandExecutionResult.Success;
154155
}
155156

156157
private async Task<CommandExecutionResult> DoubleClickMouseAsync(string button, CancellationToken cancellationToken)
157158
{
159+
await ReleaseDragBeforeClickAsync(cancellationToken);
158160
await adapter.DoubleClickMouseAsync(button, cancellationToken);
159161
cursorOverlay?.Show("click");
160162
return CommandExecutionResult.Success;
161163
}
162164

163165
private async Task<CommandExecutionResult> RightClickMouseAsync(CancellationToken cancellationToken)
164166
{
167+
await ReleaseDragBeforeClickAsync(cancellationToken);
165168
await adapter.ClickMouseAsync("right", cancellationToken);
166169
cursorOverlay?.Show("click");
167170
return CommandExecutionResult.Success;
@@ -388,6 +391,15 @@ private async Task ReleaseHeldMouseButtonAsync(CancellationToken cancellationTok
388391
cursorOverlay?.Hide();
389392
}
390393

394+
private async Task ReleaseDragBeforeClickAsync(CancellationToken cancellationToken)
395+
{
396+
if (activeDragButton is null) return;
397+
string button = activeDragButton;
398+
activeDragButton = null;
399+
await adapter.SetMouseButtonDownAsync(button, false, cancellationToken);
400+
cursorOverlay?.SetDragActive(false);
401+
}
402+
391403
private async Task ReleaseHeldModifiersAsync(CancellationToken cancellationToken)
392404
{
393405
foreach (string key in new[] { "Meta", "Shift", "Alt", "Ctrl" })

src/SwitchifyPc.Tests/DesktopCommandExecutorTests.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,106 @@ public async Task TracksDragStateAndReleasesHeldButtons()
179179
Assert.Equal(1, overlay.HideCount);
180180
}
181181

182+
[Fact]
183+
public async Task ClickReleasesActiveDragBeforeClick()
184+
{
185+
FakeInputAdapter adapter = new();
186+
FakeCursorOverlay overlay = new();
187+
DesktopCommandExecutor executor = new(adapter, overlay);
188+
189+
await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
190+
await executor.ExecuteAsync(Command("mouse.click", new { button = "left" }));
191+
192+
Assert.Equal(
193+
[
194+
"setMouseButtonDown:left:True",
195+
"setMouseButtonDown:left:False",
196+
"clickMouse:left"
197+
],
198+
adapter.Calls);
199+
Assert.Equal([true, false], overlay.DragActiveChanges);
200+
Assert.Equal(["drag", "click"], overlay.Events);
201+
}
202+
203+
[Fact]
204+
public async Task RightClickReleasesActiveDragBeforeClick()
205+
{
206+
FakeInputAdapter adapter = new();
207+
FakeCursorOverlay overlay = new();
208+
DesktopCommandExecutor executor = new(adapter, overlay);
209+
210+
await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
211+
await executor.ExecuteAsync(Command("mouse.rightClick", new { }));
212+
213+
Assert.Equal(
214+
[
215+
"setMouseButtonDown:left:True",
216+
"setMouseButtonDown:left:False",
217+
"clickMouse:right"
218+
],
219+
adapter.Calls);
220+
Assert.Equal([true, false], overlay.DragActiveChanges);
221+
}
222+
223+
[Fact]
224+
public async Task DoubleClickReleasesActiveDragBeforeClick()
225+
{
226+
FakeInputAdapter adapter = new();
227+
FakeCursorOverlay overlay = new();
228+
DesktopCommandExecutor executor = new(adapter, overlay);
229+
230+
await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
231+
await executor.ExecuteAsync(Command("mouse.doubleClick", new { button = "middle" }));
232+
233+
Assert.Equal(
234+
[
235+
"setMouseButtonDown:left:True",
236+
"setMouseButtonDown:left:False",
237+
"doubleClickMouse:middle"
238+
],
239+
adapter.Calls);
240+
Assert.Equal([true, false], overlay.DragActiveChanges);
241+
}
242+
243+
[Fact]
244+
public async Task MoveDoesNotReleaseActiveDrag()
245+
{
246+
FakeInputAdapter adapter = new();
247+
FakeCursorOverlay overlay = new();
248+
DesktopCommandExecutor executor = new(adapter, overlay);
249+
250+
await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
251+
await executor.ExecuteAsync(Command("mouse.move", new { dx = 5, dy = 0 }));
252+
253+
Assert.Equal(
254+
[
255+
"setMouseButtonDown:left:True",
256+
"moveMouseBy:5,0"
257+
],
258+
adapter.Calls);
259+
Assert.Equal([true], overlay.DragActiveChanges);
260+
Assert.Equal(["drag", "drag"], overlay.Events);
261+
}
262+
263+
[Fact]
264+
public async Task ScrollDoesNotReleaseActiveDrag()
265+
{
266+
FakeInputAdapter adapter = new();
267+
FakeCursorOverlay overlay = new();
268+
DesktopCommandExecutor executor = new(adapter, overlay);
269+
270+
await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
271+
await executor.ExecuteAsync(Command("mouse.scroll", new { dx = 0, dy = -3 }));
272+
273+
Assert.Equal(
274+
[
275+
"setMouseButtonDown:left:True",
276+
"scrollMouse:0,-3"
277+
],
278+
adapter.Calls);
279+
Assert.Equal([true], overlay.DragActiveChanges);
280+
}
281+
182282
[Fact]
183283
public async Task TracksModifierStateAndUpdatesOverlay()
184284
{

0 commit comments

Comments
 (0)