Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/SwitchifyPc.Core/Input/DesktopCommandExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,20 +148,23 @@ private async Task<CommandExecutionResult> EndDragAsync(CancellationToken cancel

private async Task<CommandExecutionResult> ClickMouseAsync(string button, CancellationToken cancellationToken)
{
await ReleaseDragBeforeClickAsync(cancellationToken);
await adapter.ClickMouseAsync(button, cancellationToken);
cursorOverlay?.Show("click");
return CommandExecutionResult.Success;
}

private async Task<CommandExecutionResult> DoubleClickMouseAsync(string button, CancellationToken cancellationToken)
{
await ReleaseDragBeforeClickAsync(cancellationToken);
await adapter.DoubleClickMouseAsync(button, cancellationToken);
cursorOverlay?.Show("click");
return CommandExecutionResult.Success;
}

private async Task<CommandExecutionResult> RightClickMouseAsync(CancellationToken cancellationToken)
{
await ReleaseDragBeforeClickAsync(cancellationToken);
await adapter.ClickMouseAsync("right", cancellationToken);
cursorOverlay?.Show("click");
return CommandExecutionResult.Success;
Expand Down Expand Up @@ -388,6 +391,15 @@ private async Task ReleaseHeldMouseButtonAsync(CancellationToken cancellationTok
cursorOverlay?.Hide();
}

private async Task ReleaseDragBeforeClickAsync(CancellationToken cancellationToken)
{
if (activeDragButton is null) return;
string button = activeDragButton;
activeDragButton = null;
await adapter.SetMouseButtonDownAsync(button, false, cancellationToken);
cursorOverlay?.SetDragActive(false);
}

private async Task ReleaseHeldModifiersAsync(CancellationToken cancellationToken)
{
foreach (string key in new[] { "Meta", "Shift", "Alt", "Ctrl" })
Expand Down
100 changes: 100 additions & 0 deletions src/SwitchifyPc.Tests/DesktopCommandExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,106 @@ public async Task TracksDragStateAndReleasesHeldButtons()
Assert.Equal(1, overlay.HideCount);
}

[Fact]
public async Task ClickReleasesActiveDragBeforeClick()
{
FakeInputAdapter adapter = new();
FakeCursorOverlay overlay = new();
DesktopCommandExecutor executor = new(adapter, overlay);

await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
await executor.ExecuteAsync(Command("mouse.click", new { button = "left" }));

Assert.Equal(
[
"setMouseButtonDown:left:True",
"setMouseButtonDown:left:False",
"clickMouse:left"
],
adapter.Calls);
Assert.Equal([true, false], overlay.DragActiveChanges);
Assert.Equal(["drag", "click"], overlay.Events);
}

[Fact]
public async Task RightClickReleasesActiveDragBeforeClick()
{
FakeInputAdapter adapter = new();
FakeCursorOverlay overlay = new();
DesktopCommandExecutor executor = new(adapter, overlay);

await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
await executor.ExecuteAsync(Command("mouse.rightClick", new { }));

Assert.Equal(
[
"setMouseButtonDown:left:True",
"setMouseButtonDown:left:False",
"clickMouse:right"
],
adapter.Calls);
Assert.Equal([true, false], overlay.DragActiveChanges);
}

[Fact]
public async Task DoubleClickReleasesActiveDragBeforeClick()
{
FakeInputAdapter adapter = new();
FakeCursorOverlay overlay = new();
DesktopCommandExecutor executor = new(adapter, overlay);

await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
await executor.ExecuteAsync(Command("mouse.doubleClick", new { button = "middle" }));

Assert.Equal(
[
"setMouseButtonDown:left:True",
"setMouseButtonDown:left:False",
"doubleClickMouse:middle"
],
adapter.Calls);
Assert.Equal([true, false], overlay.DragActiveChanges);
}

[Fact]
public async Task MoveDoesNotReleaseActiveDrag()
{
FakeInputAdapter adapter = new();
FakeCursorOverlay overlay = new();
DesktopCommandExecutor executor = new(adapter, overlay);

await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
await executor.ExecuteAsync(Command("mouse.move", new { dx = 5, dy = 0 }));

Assert.Equal(
[
"setMouseButtonDown:left:True",
"moveMouseBy:5,0"
],
adapter.Calls);
Assert.Equal([true], overlay.DragActiveChanges);
Assert.Equal(["drag", "drag"], overlay.Events);
}

[Fact]
public async Task ScrollDoesNotReleaseActiveDrag()
{
FakeInputAdapter adapter = new();
FakeCursorOverlay overlay = new();
DesktopCommandExecutor executor = new(adapter, overlay);

await executor.ExecuteAsync(Command("mouse.dragStart", new { button = "left" }));
await executor.ExecuteAsync(Command("mouse.scroll", new { dx = 0, dy = -3 }));

Assert.Equal(
[
"setMouseButtonDown:left:True",
"scrollMouse:0,-3"
],
adapter.Calls);
Assert.Equal([true], overlay.DragActiveChanges);
}

[Fact]
public async Task TracksModifierStateAndUpdatesOverlay()
{
Expand Down