Preserve cross-edge cursor position when switching machines - #494
Open
salvarecuero wants to merge 2 commits into
Open
Preserve cross-edge cursor position when switching machines#494salvarecuero wants to merge 2 commits into
salvarecuero wants to merge 2 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #230.
When moving the cursor from one machine to another, Lan Mouse currently only tells the receiving peer which edge was crossed.
It does not tell it where along that edge the cursor crossed, so the receiver can keep its previous cursor position instead. For example, crossing the right edge near the top of one screen may make the cursor appear at a completely different height on the other machine.
This PR makes the cursor enter the destination at the corresponding position along the edge.
How it works
The source sends a normalized position (
Option<f32>,0.0..=1.0) along the crossed edge:For a single monitor this is straightforward.
Multi-monitor layouts need a little more care. Using the percentage of the whole virtual desktop does not work well when monitors have different sizes, are stacked or offset, or have gaps between them.
Instead, Lan Mouse builds the parts of each desktop edge that are actually exposed to the outside and maps the cursor position across those edges. Internal borders between monitors and empty gaps are not counted.
This keeps the mapping based on the physical edge the cursor can actually cross.
Protocol compatibility
The new
Capabilitiesevent lets peers advertise support for positioned transitions.When both peers support it, the sender uses
EnterWithPosition, which includes the edge, the optional cross-axis position, and transition identifiers:epoch(set once at startup, so the receiver can tell transitions from a previous process lifetime apart) plusserial(per-transition).When the other peer does not support it, Lan Mouse keeps using the existing
Enterevent, so mixed old/new setups keep the previous behavior.The existing protocol event IDs are unchanged; the new event types are appended after them. Unknown events are already ignored by the receive loop instead of closing the connection.
EnterWithPositionis also retried while waiting for its ACK. Itsepochandseriallet the receiver recognize retries and stale transitions, so the same handoff is not applied multiple times.Backend support
Capture backends that currently provide the crossing position:
InputCapturePortal)macOS and dummy capture currently send no position (
None); macOS only for lack of a Mac to test against.On the receiving side, cursor positioning is implemented for:
Other emulation backends (X11, macOS, xdg-desktop-portal) keep their existing behavior.
macOS cursor positioning is left as a follow-up: the CoreGraphics pieces (display bounds, warp) are all available in the existing backend, but I have no Mac available to test against.
Testing
The shared screen geometry is tested with:
The edge calculations are also checked against a separate grid-based model rather than only testing the implementation against itself. Generated coverage exercises 1,296 two-monitor layouts.
Protocol tests cover positioned transitions both with and without a cursor position, plus capability serialization.
Local verification on Linux:
cargo fmt --checkcargo test -p input-event— 25/25 passedcargo test --workspacecargo clippy --workspace --all-targets -- -D warningsRuntime test on a real two-machine setup (Linux host on the left, Windows 11 client on the right): crossing at various heights lands at the corresponding height on the peer.
Note: the Windows build used for testing was compiled with
cargo build --no-default-features(no GTK frontend), which is sufficient for daemon mode.