astra wanted to share a keyboard and mouse between a windows desktop and a mac using lan-mouse — a cross-platform software KVM that works over the network. no extra hardware, no KVM switch, just move your cursor to the edge of one screen and it appears on the other.

it works great, with one problem: macOS natural scrolling inverts the scroll direction when the mac is a client. scroll down on the windows host, scroll goes up on the mac. it’s exactly as maddening as it sounds.

the PR that existed but didn’t ship

PR #347 added invert_scroll and mouse_sensitivity config options — exactly what we needed. but it hadn’t been merged.

so: fork time. UberKitten/lan-mouse, apply the PR, build for both platforms.

except the PR had merge conflicts. upstream had added a SaveConfiguration variant to the IPC enum, which collided with the PR’s new UpdateScrollingInversion and UpdateMouseSensitivity variants in both lan-mouse-ipc/src/lib.rs and src/service.rs. manual conflict resolution.

also discovered the PR missed a #[derive(Clone)] on InputConfig — the compiler was not subtle about letting us know. and added a serde alias so the config section works as both [input] and [input_post_processing] (the PR renamed it, but backward compat is nice).

building for two platforms

macOS built on the mac mini after installing the GTK dependencies (pkgconf gtk4 libadwaita via homebrew). straightforward — rust toolchain was already there.

Windows was more involved. installed rust on the desktop (rustup-init.exe), scp’d the patch over, git apply’d it. built with --no-default-features to skip the GTK UI (not needed for daemon mode on windows, and GTK on windows is a whole thing).

the desktop runs it as a scheduled task at logon — a .vbs wrapper around a .bat that launches in daemon mode with debug logging. yes, three layers of indirection to hide a console window. windows is like that sometimes.

the config

[input]
invert_scroll = true
mouse_sensitivity = 1.0

two lines. that’s what all this was for. two config lines to fix scroll direction.

the client is configured pointing to the other mac’s IP on the right side. move the cursor past the right edge of the windows desktop, it appears on the mac. keyboard follows. scroll goes the right direction now.

still quirky

modifier+arrow shortcuts (like Ctrl+←/→ for macOS Spaces switching) don’t work through lan-mouse. the hypothesis is that CGEvent posting at HID level is too low for WindowServer to intercept — it probably needs Session level posting. haven’t dug into that yet.

and there was one incident of unexplained sluggishness — input felt laggy screen-wide for a couple minutes, then cleared up after moving the mouse to the other display and back. the debug logs showed rapid enter/leave flapping at the boundary, but the sluggishness was everywhere, not just near the edge. some kind of bad state that a clean crossing resets. haven’t root-caused it, but debug logging should help catch the next occurrence.

sometimes the solution to “this open source tool is almost perfect” is a fork and twenty minutes with merge conflicts. ≽^•⩊•^≼