Skip to content

display: clamp coordinates to framebuffer range#186

Closed
gaberudy wants to merge 1 commit into
kasmtech:masterfrom
goldenhelix:fix/clamp-mouse-coords-to-framebuffer
Closed

display: clamp coordinates to framebuffer range#186
gaberudy wants to merge 1 commit into
kasmtech:masterfrom
goldenhelix:fix/clamp-mouse-coords-to-framebuffer

Conversation

@gaberudy

@gaberudy gaberudy commented May 3, 2026

Copy link
Copy Markdown

Problem

absX, absY, and the multi-screen branch of clientToElement can produce
negative or out-of-range values when the cursor exits the primary screen on
a side with no adjacent virtual screen (e.g. dragging a window's title bar
above the top edge so the pointer's logical Y goes < 0).

The negative int result reaches RFB.messages.pointerEvent and gets packed
as a uint16 on the wire. The server decodes it as a huge positive coord and
snaps the cursor to the far edge of the framebuffer.

In practice this manifests as: drag a window upward, pointer touches the top
of the canvas, cursor jumps to the bottom edge, drag glitches.

Fix

Clamp the result of each coordinate transform to [0, fbWidth-1] /
[0, fbHeight-1] before returning. The clamp is applied in three places:

  • absX(x) — single-screen path
  • absY(y) — single-screen path
  • clientToElement(...) — multi-screen extension path (which can also yield
    negative values for the same reason)

_fbWidth / _fbHeight may be 0 before resize negotiation completes; the
upper-bound check is gated on truthy width/height to preserve current behavior
during connect.

Repro

Connect via kasmweb to a session, grab a window's title bar, drag upward past
the top of the canvas. The window snaps to the bottom of the screen. With this patch the cursor stays clamped at y=0 and the drag behaves as expected (window stays pinned to the top of the screen).

absX/absY and clientToElement could produce negative or out-of-range
values when the cursor leaves the primary screen on a side with no
adjacent virtual screen. Without clamping, the negative value got
packed into a uint16 on the wire and the server saw a huge positive
coord, snapping the cursor to the far edge.

Clamps to [0, fbWidth-1] and [0, fbHeight-1] in absX, absY, and
clientToElement (multi-screen path).
@mmcclaskey

Copy link
Copy Markdown
Collaborator

@gaberudy , it looks like we already addressed this issue when we fixed a bug in window snapping not working, due to the same bug. However, we addressed it a little different.

commit d9199c6 / PR #189 added RFB.messages.pointerEventClamped() and switched the pointer send paths to use it. That means negative coordinates from absX(), absY(), or multi-monitor coordinate conversion are clamped to 0 immediately before serialization, avoiding the negative-to-uint16 wrap that caused the cursor to jump to the far edge.

@mmcclaskey mmcclaskey closed this Jun 21, 2026
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