From 5dc332e28deec48ca5b8ef7d12e7c6cc7bed45db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beatrice=20Dellac=C3=A0?= Date: Thu, 1 Oct 2026 22:39:01 +0200 Subject: [PATCH] give the mouse back when the user returns mid-movement --- .../autosqueal/controls/CursorMover.java | 5 ++++- .../controls/SingleStepMovementTask.java | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/wtf/beatrice/autosqueal/controls/CursorMover.java b/src/main/java/wtf/beatrice/autosqueal/controls/CursorMover.java index 51efcca..e536b72 100644 --- a/src/main/java/wtf/beatrice/autosqueal/controls/CursorMover.java +++ b/src/main/java/wtf/beatrice/autosqueal/controls/CursorMover.java @@ -17,6 +17,9 @@ import java.util.function.BooleanSupplier; * * The movements only happen when the user is away: while the user is actively * using the machine, they are skipped, so the app never fights for the mouse. + * The same goes for a movement already in progress: the task checks whether + * the user is still away at every step, and gives the mouse back when they + * are not. * * The movement itself is executed by a {@link SingleStepMovementTask}, which * runs on its own virtual thread until it reaches its destination. @@ -72,7 +75,7 @@ public class CursorMover implements Runnable LOGGER.info("Destination coordinates: {}, {}", destX, destY); try { - SingleStepMovementTask movement = new SingleStepMovementTask(robotTracker, destX, destY, click); + SingleStepMovementTask movement = new SingleStepMovementTask(robotTracker, destX, destY, click, isUserAway); movementExecutor.execute(movement); } catch (AWTException ex) { LOGGER.error("Could not start movement task", ex); diff --git a/src/main/java/wtf/beatrice/autosqueal/controls/SingleStepMovementTask.java b/src/main/java/wtf/beatrice/autosqueal/controls/SingleStepMovementTask.java index 915ce8f..3c17662 100644 --- a/src/main/java/wtf/beatrice/autosqueal/controls/SingleStepMovementTask.java +++ b/src/main/java/wtf/beatrice/autosqueal/controls/SingleStepMovementTask.java @@ -5,6 +5,7 @@ import org.apache.logging.log4j.Logger; import java.awt.*; import java.awt.event.InputEvent; +import java.util.function.BooleanSupplier; /** * Moves the mouse cursor towards a destination one small step at a time. @@ -13,6 +14,10 @@ import java.awt.event.InputEvent; * it is free. When it gets to its destination, it can optionally perform a * double click, with the pacing the app has always used. * + * If the user comes back mid-movement, the movement is abandoned at once — + * within the latency of the away detection, which polls about once a second — + * so the mouse is returned to the user instead of being dragged to a corner. + * * All the movements it performs are reported to the {@link RobotMouseTracker}, * so that the away detection can tell them apart from the user's. */ @@ -28,18 +33,21 @@ public class SingleStepMovementTask implements Runnable { private final int destX; private final int destY; private final boolean click; + private final BooleanSupplier userIsAway; private float currentX; private float currentY; private float stepX; private float stepY; - public SingleStepMovementTask(RobotMouseTracker robotTracker, int destinationX, int destinationY, boolean click) throws AWTException { + public SingleStepMovementTask(RobotMouseTracker robotTracker, int destinationX, int destinationY, boolean click, + BooleanSupplier userIsAway) throws AWTException { this.robotTracker = robotTracker; this.destX = destinationX; this.destY = destinationY; this.click = click; + this.userIsAway = userIsAway; Point location = MouseInfo.getPointerInfo().getLocation(); this.currentX = location.x; @@ -65,6 +73,14 @@ public class SingleStepMovementTask implements Runnable { try { while (!hasReachedDestination()) { + // a user who came back mid-movement gets the mouse back + if (!userIsAway.getAsBoolean()) { + LOGGER.info("User is back: abandoning the movement at [{}, {}]", + Math.round(currentX), Math.round(currentY)); + robotTracker.moveEnded(Math.round(currentX), Math.round(currentY)); + return; + } + // when less than a full step is left, move exactly what is // left, so that both axes always land on their destination stepX = adjustedStep(currentX, destX, stepX);