[PR #425] feat(scroll): receiver natural-scroll toggle + wlroots axis_source + macOS v120 fix #417

Open
opened 2026-05-05 22:18:36 -06:00 by gitea-mirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/feschber/lan-mouse/pull/425
Author: @jondkinney
Created: 5/6/2026
Status: 🔄 Open

Base: mainHead: split/06-scroll


📝 Commits (10+)

  • 31298f2 feat: cross-platform wall-press auto-release fallback
  • bffbef0 proto: add Bounds(width, height) event variant
  • 2219f45 feat(emulation): display_bounds + warp_cursor for all backends
  • 5de5016 feat(emulation): send Bounds + warp cursor on Enter
  • 68fab55 feat(capture): cache peer bounds and use as wall-press upper clamp
  • 944e758 ui: wrap window content in GtkScrolledWindow
  • 56f7730 ui: rename Auto-Release group to scope it to outgoing capture
  • cd63f5d fix: preserve cross-axis cursor position across machine transitions
  • 2571b47 fix(capture/layer_shell): report screen-space cursor position on Enter
  • cbe2ec1 fix(capture): warp host cursor to guest position on release

📊 Changes

50 files changed (+4457 additions, -590 deletions)

View changed files

.claude/scheduled_tasks.lock (+1 -0)
📝 .gitignore (+1 -0)
📝 Cargo.lock (+494 -204)
📝 Cargo.toml (+5 -1)
📝 input-capture/Cargo.toml (+1 -0)
📝 input-capture/src/dummy.rs (+2 -2)
📝 input-capture/src/layer_shell.rs (+67 -17)
📝 input-capture/src/lib.rs (+574 -11)
📝 input-capture/src/libei.rs (+5 -2)
📝 input-capture/src/macos.rs (+257 -20)
📝 input-capture/src/windows.rs (+1 -1)
📝 input-capture/src/windows/event_thread.rs (+66 -12)
📝 input-capture/src/x11.rs (+1 -1)
📝 input-emulation/src/lib.rs (+49 -0)
📝 input-emulation/src/libei.rs (+49 -2)
📝 input-emulation/src/macos.rs (+110 -1)
📝 input-emulation/src/windows.rs (+41 -4)
📝 input-emulation/src/wlroots.rs (+219 -5)
📝 input-emulation/src/x11.rs (+38 -1)
📝 input-emulation/src/xdg_desktop_portal.rs (+13 -1)

...and 30 more files

📄 Description

Summary

Four scroll-handling fixes that together make trackpad and mouse-wheel forwarding behave correctly across natural/classic preference combinations.

macOS capture (dc09e88): Wire convention canonicalized to classic mouse-wheel direction regardless of the user's macOS Natural Scrolling preference (read via CFPreferencesCopyAppValue). Without a fixed wire convention, the receiver-side toggle has no stable reference. Opposite of #415, which negated unconditionally and traded the bug for the opposite-preference user.

wlroots emulation (a26ae8b): Continuous-scroll events (trackpad) were silently dropped by Hyprland/Sway/GNOME-Shell because the axis() event lacked a companion axis_source in the same wl_pointer.frame. Spec calls it a "hint"; in practice it's load-bearing for continuous scroll. One extra emit per axis frame fixes it.

Receiver-side Natural scrolling toggle (9ed25b0): New GUI preference, off by default — wire is classic, receiver re-inverts. Mirrors libinput's natural_scroll, applied to forwarded events specifically (which on Wayland bypass libinput).

macOS line→tick mapping (19d36bf): Capture used to map one macOS scroll-line to 40 v120 units (1/3 of a wheel tick), so receivers using the discrete count (Slack via XWayland, terminals reading axis_value120) needed 3+ notches before any scroll registered. macOS already amplifies SCROLL_WHEEL_EVENT_DELTA by velocity, so one line should map directly to one full v120 tick. Slow-notch and fast-flick behavior is now symmetric across native-Wayland and XWayland clients.

Test plan

  • Trackpad scroll on macOS host reaches Hyprland peer (was previously silently dropped on continuous-scroll path)
  • Mouse wheel notch on macOS produces exactly one axis_value120 = 120 event on the wire
  • Slack-via-XWayland and ghostty-on-native-Wayland both register a single notch as a single scroll on the peer
  • Receiver-side natural-scroll toggle inverts forwarded events; physical input on the receiver continues to use libinput's preference
  • Both natural-on-sender × natural-on-receiver and the cross-product cases produce intuitive direction

Split out from #418, the umbrella PR collecting ~10 independent feature areas. This PR is the scroll-handling subset. See #418 for the full picture.

Stack overview

These PRs are split out from #418 and stack in this order:

  1. #420 — cursor sync + wall-press + host-lock + slider/UI
  2. #421 — peer version exchange
  3. #422 — hostname resolver + multi-homed DTLS listener
  4. #423 — mDNS-SD service-order discovery
  5. #424 — macOS QoL + UI polish
  6. #425 — scroll forwarding
  7. #426 — GUI singleton

Each PR's branch builds on the previous one, so until earlier PRs are merged the cumulative diff against main includes all preceding work. Reviewing in order is easiest.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/feschber/lan-mouse/pull/425 **Author:** [@jondkinney](https://github.com/jondkinney) **Created:** 5/6/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `split/06-scroll` --- ### 📝 Commits (10+) - [`31298f2`](https://github.com/feschber/lan-mouse/commit/31298f29577e06d4fda36188f5721cd93123e17a) feat: cross-platform wall-press auto-release fallback - [`bffbef0`](https://github.com/feschber/lan-mouse/commit/bffbef0875257c24227e6599e64b4e7a0030e1b2) proto: add Bounds(width, height) event variant - [`2219f45`](https://github.com/feschber/lan-mouse/commit/2219f45a1c37ac9f324728470ea7900eb804c2f6) feat(emulation): display_bounds + warp_cursor for all backends - [`5de5016`](https://github.com/feschber/lan-mouse/commit/5de501637d1e6a5e486c9a3799d8c069ae0d5184) feat(emulation): send Bounds + warp cursor on Enter - [`68fab55`](https://github.com/feschber/lan-mouse/commit/68fab558b340a224e075b842f6182b2c7d6646a3) feat(capture): cache peer bounds and use as wall-press upper clamp - [`944e758`](https://github.com/feschber/lan-mouse/commit/944e7582b783252e07c895b16c5440253b8ecbfe) ui: wrap window content in GtkScrolledWindow - [`56f7730`](https://github.com/feschber/lan-mouse/commit/56f7730164171cbb3dfb0176ca2eae7e314460c6) ui: rename Auto-Release group to scope it to outgoing capture - [`cd63f5d`](https://github.com/feschber/lan-mouse/commit/cd63f5d42875bd27f4724eb9fe3ce787e5725c6c) fix: preserve cross-axis cursor position across machine transitions - [`2571b47`](https://github.com/feschber/lan-mouse/commit/2571b47074da9f68e56501eefbb8ea959b67f5a7) fix(capture/layer_shell): report screen-space cursor position on Enter - [`cbe2ec1`](https://github.com/feschber/lan-mouse/commit/cbe2ec13030fa565f1e562ecf5e09cc5d2a8c637) fix(capture): warp host cursor to guest position on release ### 📊 Changes **50 files changed** (+4457 additions, -590 deletions) <details> <summary>View changed files</summary> ➕ `.claude/scheduled_tasks.lock` (+1 -0) 📝 `.gitignore` (+1 -0) 📝 `Cargo.lock` (+494 -204) 📝 `Cargo.toml` (+5 -1) 📝 `input-capture/Cargo.toml` (+1 -0) 📝 `input-capture/src/dummy.rs` (+2 -2) 📝 `input-capture/src/layer_shell.rs` (+67 -17) 📝 `input-capture/src/lib.rs` (+574 -11) 📝 `input-capture/src/libei.rs` (+5 -2) 📝 `input-capture/src/macos.rs` (+257 -20) 📝 `input-capture/src/windows.rs` (+1 -1) 📝 `input-capture/src/windows/event_thread.rs` (+66 -12) 📝 `input-capture/src/x11.rs` (+1 -1) 📝 `input-emulation/src/lib.rs` (+49 -0) 📝 `input-emulation/src/libei.rs` (+49 -2) 📝 `input-emulation/src/macos.rs` (+110 -1) 📝 `input-emulation/src/windows.rs` (+41 -4) 📝 `input-emulation/src/wlroots.rs` (+219 -5) 📝 `input-emulation/src/x11.rs` (+38 -1) 📝 `input-emulation/src/xdg_desktop_portal.rs` (+13 -1) _...and 30 more files_ </details> ### 📄 Description ## Summary Four scroll-handling fixes that together make trackpad and mouse-wheel forwarding behave correctly across natural/classic preference combinations. **macOS capture (`dc09e88`):** Wire convention canonicalized to classic mouse-wheel direction regardless of the user's macOS Natural Scrolling preference (read via `CFPreferencesCopyAppValue`). Without a fixed wire convention, the receiver-side toggle has no stable reference. Opposite of #415, which negated unconditionally and traded the bug for the opposite-preference user. **wlroots emulation (`a26ae8b`):** Continuous-scroll events (trackpad) were silently dropped by Hyprland/Sway/GNOME-Shell because the `axis()` event lacked a companion `axis_source` in the same `wl_pointer.frame`. Spec calls it a "hint"; in practice it's load-bearing for continuous scroll. One extra emit per axis frame fixes it. **Receiver-side `Natural scrolling` toggle (`9ed25b0`):** New GUI preference, off by default — wire is classic, receiver re-inverts. Mirrors libinput's `natural_scroll`, applied to forwarded events specifically (which on Wayland bypass libinput). **macOS line→tick mapping (`19d36bf`):** Capture used to map one macOS scroll-line to 40 v120 units (1/3 of a wheel tick), so receivers using the discrete count (Slack via XWayland, terminals reading `axis_value120`) needed 3+ notches before any scroll registered. macOS already amplifies `SCROLL_WHEEL_EVENT_DELTA` by velocity, so one line should map directly to one full v120 tick. Slow-notch and fast-flick behavior is now symmetric across native-Wayland and XWayland clients. ## Test plan - [x] Trackpad scroll on macOS host reaches Hyprland peer (was previously silently dropped on continuous-scroll path) - [x] Mouse wheel notch on macOS produces exactly one `axis_value120 = 120` event on the wire - [x] Slack-via-XWayland and ghostty-on-native-Wayland both register a single notch as a single scroll on the peer - [x] Receiver-side natural-scroll toggle inverts forwarded events; physical input on the receiver continues to use libinput's preference - [x] Both natural-on-sender × natural-on-receiver and the cross-product cases produce intuitive direction --- Split out from #418, the umbrella PR collecting ~10 independent feature areas. This PR is the scroll-handling subset. See #418 for the full picture. ## Stack overview These PRs are split out from #418 and stack in this order: 1. #420 — cursor sync + wall-press + host-lock + slider/UI 2. #421 — peer version exchange 3. #422 — hostname resolver + multi-homed DTLS listener 4. #423 — mDNS-SD service-order discovery 5. #424 — macOS QoL + UI polish 6. #425 — scroll forwarding 7. #426 — GUI singleton Each PR's branch builds on the previous one, so until earlier PRs are merged the cumulative diff against `main` includes all preceding work. Reviewing in order is easiest. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
gitea-mirror added the
pull-request
label 2026-05-05 22:18:36 -06:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/lan-mouse#417
No description provided.