fix(input): pointer pinned at (0,0) when frames present on the video sink in manual-resolution mode#268
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates coordinate calculation in addons/selkies-web-core/lib/input.js to handle hidden canvas sinks by falling back to visible mirror elements or the last cached valid bounding rect. The reviewer suggests caching the mirror elements on the class instance to avoid high-frequency DOM lookups via document.getElementById during pointer events.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (!(rect.width > 0 && rect.height > 0)) { | ||
| for (const mirrorId of ['videoStream', 'videoWorkerCanvas']) { | ||
| const mirror = document.getElementById(mirrorId); | ||
| if (!mirror) continue; | ||
| const mirrorRect = mirror.getBoundingClientRect(); | ||
| if (mirrorRect.width > 0 && mirrorRect.height > 0) { | ||
| rect = mirrorRect; | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Calling document.getElementById on every high-frequency mouse/pointer event (such as mousemove or pointermove) when the main canvas is hidden can introduce unnecessary overhead and potential performance bottlenecks. Since the mirror elements are persistent, we can lazily cache them on the class instance and verify their connection status using isConnected to handle cases where they might be replaced in the DOM.
if (!(rect.width > 0 && rect.height > 0)) {
if (!this._mirrors) {
this._mirrors = {};
}
for (const mirrorId of ['videoStream', 'videoWorkerCanvas']) {
let mirror = this._mirrors[mirrorId];
if (!mirror || !mirror.isConnected) {
mirror = document.getElementById(mirrorId);
this._mirrors[mirrorId] = mirror;
}
if (!mirror) continue;
const mirrorRect = mirror.getBoundingClientRect();
if (mirrorRect.width > 0 && mirrorRect.height > 0) {
rect = mirrorRect;
break;
}
}
}In manual-resolution mode _applySinkCoordinates maps pointer coordinates against #videoCanvas. ws-core hides that canvas (display: none) whenever decoded frames are presented on the <video>/worker sink instead, so the canvas measures 0x0 the moment any frame arrives. The function then set x = y = 0 and still returned true, suppressing the windowMath fallback — every subsequent pointer event streamed m,0,0 and the remote pointer was pinned at the top-left corner until a window resize re-showed the canvas (and only until the next frame). On a mostly static desktop this looks like "right-click breaks the mouse" (the menu appearing is what triggers the next frame); with any continuously changing content the pointer is dead immediately. The presenter mirrors the canvas box verbatim onto the visible sink (#videoStream or #videoWorkerCanvas), so when the canvas measures zero, take the rect from the visible mirror (the canvas buffer dimensions stay authoritative for scaling), then from the last valid measurement, and only if neither exists return false so the caller falls back to windowMath instead of claiming success with (0, 0). Tested on the comprehensive-fixes stack (selkies 40a5312 + pixelflux 968a4f4 + pcmflux 6aa227e) on an lsio-based image, Firefox client, manual resolution 1920x1080: reproduced the pinned pointer, verified the fix restores correct absolute coordinates through right-click menus and continuous screen updates. Co-authored-by: Claude <noreply@anthropic.com>
e07efc9 to
9f2b734
Compare
155eb0b to
de77558
Compare
|
Fixes incorporated in de77558, linuxserver/pixelflux@b32a178, linuxserver/pcmflux@0cbadcb. |
3bab531 to
4de4c8a
Compare
In manual-resolution mode
_applySinkCoordinatesmaps pointer coordinates against#videoCanvas. ws-core hides that canvas (display: none) whenever decoded frames are presented on the<video>/worker sink (presentFrameToVideo/activateWorkerSinkDisplay), so the canvas measures 0×0 the moment any frame arrives. The function then setx = y = 0and still returnedtrue, suppressing the windowMath fallback — every subsequent pointer event streamedm,0,0and the remote pointer was pinned at the top-left corner.On a mostly static desktop this masquerades as "right-click breaks the mouse": decoder warm-up frames paint on the (visible) canvas, nothing changes on screen, input works — then the right-click menu appearing produces the first frame on the video sink, the canvas is hidden, and the pointer dies. A window resize heals it (resize handlers re-show the canvas) until the next frame. With continuously changing content the pointer is dead immediately.
Since the presenter mirrors the canvas box verbatim onto the visible sink, the fix measures the visible mirror (
#videoStream/#videoWorkerCanvas) when the canvas rect is zero (the canvas buffer dimensions stay authoritative for scaling), falls back to the last valid measurement, and only if neither exists returnsfalseso the caller uses windowMath instead of claiming success with (0, 0).Tested on the comprehensive-fixes stack (selkies 40a5312 + pixelflux 968a4f4 + pcmflux 6aa227e) on an lsio-based image with a Firefox client at manual resolution 1920×1080: reproduced the pinned pointer, verified the fix gives correct absolute coordinates through right-click menus and continuous screen updates, with no offset on a fresh session.
🤖 Generated with Claude Code