Skip to content

fix(universal-control): arm on KDE, and smooth the cursor over adb-TCP - #6

Open
X-Ryl669 wants to merge 1 commit into
zoir-dev:mainfrom
X-Ryl669:fix/universal-control-kde-barrier
Open

fix(universal-control): arm on KDE, and smooth the cursor over adb-TCP#6
X-Ryl669 wants to merge 1 commit into
zoir-dev:mainfrom
X-Ryl669:fix/universal-control-kde-barrier

Conversation

@X-Ryl669

Copy link
Copy Markdown

Made by Claude. This fixes the Universal Control feature on KDE Plasma Desktop and made it smooth on ADB over Wifi.

Here's Claude description:

Universal Control never armed on Plasma. Two separate incompatibilities with xdg-desktop-portal-kde, the first masking the second:

  1. barrier_id = 0 is rejected outright. inputcapture.cpp does if (id == 0) { "Invalid barrier id"; failedBarriers.append(id); } BEFORE any geometry check. The InputCapture spec puts no constraint on the id and Mutter accepts 0, so this broke every KDE session while looking like a geometry problem. Now BARRIER_ID = 1.

  2. KWin only arms a barrier spanning the WHOLE screen edge — inputcapturebarrier.cpp requires y1 == geometry.y() && y2 == geometry.bottom() and returns BetweenScreensOrDoesNotFill otherwise. The 400 px corner strip (SEGMENT_LEN) is therefore refused. We now retry across the full edge when the compositor refuses the partial one, rebinding the armed span so entry_point / laptop_point still map crossings against the barrier that actually armed. Mutter keeps the corner strip; KDE trades corner avoidance for working at all. barrier_pos is split out so the retry builds its line the same way the first attempt did.

The failure was diagnosable only from the portal's own journal ("Invalid barrier id 0") — our side could see nothing beyond a non-empty failed_barriers, which is what barrier_refused already reported.

Also: fill gaps in traffic to the phone while it holds the pointer. Android parks the Wi-Fi radio between packets and the AP buffers ours until its next wake — measured 150–350 ms on an idle 5 GHz link (RSSI -52, 866 Mbps) versus 2–13 ms awake, which made the cursor stutter badly whenever adb rides TCP rather than USB. Driven off the existing 2 ms flush tick and gated on last_tx, so it sends nothing while real motion is flowing and stops the moment the pointer leaves. Covers pending too, so the crossing lands on an already-awake radio instead of paying the wake penalty on its first motion. last_tx is deliberately NOT last_motion: that one is the acceleration curve's dt.

This is a mitigation for a transport limitation, not a fix — USB adb remains materially smoother.

Universal Control never armed on Plasma. Two separate incompatibilities
with xdg-desktop-portal-kde, the first masking the second:

1. `barrier_id = 0` is rejected outright. `inputcapture.cpp` does
       if (id == 0) { "Invalid barrier id"; failedBarriers.append(id); }
   BEFORE any geometry check. The InputCapture spec puts no constraint on
   the id and Mutter accepts 0, so this broke every KDE session while
   looking like a geometry problem. Now `BARRIER_ID = 1`.

2. KWin only arms a barrier spanning the WHOLE screen edge —
   `inputcapturebarrier.cpp` requires `y1 == geometry.y() && y2 ==
   geometry.bottom()` and returns `BetweenScreensOrDoesNotFill`
   otherwise. The 400 px corner strip (`SEGMENT_LEN`) is therefore
   refused. We now retry across the full edge when the compositor
   refuses the partial one, rebinding the armed `span` so `entry_point`
   / `laptop_point` still map crossings against the barrier that
   actually armed. Mutter keeps the corner strip; KDE trades corner
   avoidance for working at all. `barrier_pos` is split out so the retry
   builds its line the same way the first attempt did.

The failure was diagnosable only from the portal's own journal
("Invalid barrier id 0") — our side could see nothing beyond a non-empty
`failed_barriers`, which is what `barrier_refused` already reported.

Also: fill gaps in traffic to the phone while it holds the pointer.
Android parks the Wi-Fi radio between packets and the AP buffers ours
until its next wake — measured 150–350 ms on an idle 5 GHz link (RSSI
-52, 866 Mbps) versus 2–13 ms awake, which made the cursor stutter badly
whenever adb rides TCP rather than USB. Driven off the existing 2 ms
flush tick and gated on `last_tx`, so it sends nothing while real motion
is flowing and stops the moment the pointer leaves. Covers `pending` too,
so the crossing lands on an already-awake radio instead of paying the
wake penalty on its first motion. `last_tx` is deliberately NOT
`last_motion`: that one is the acceleration curve's `dt`.

This is a mitigation for a transport limitation, not a fix — USB adb
remains materially smoother.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants