Skip to content

Flush pending pseudo-encodings in writeLosslessRefresh under video mode#358

Open
gaberudy wants to merge 1 commit intokasmtech:masterfrom
goldenhelix:fix/cursor-flush-pseudo-encodings-in-video-mode
Open

Flush pending pseudo-encodings in writeLosslessRefresh under video mode#358
gaberudy wants to merge 1 commit intokasmtech:masterfrom
goldenhelix:fix/cursor-flush-pseudo-encodings-in-video-mode

Conversation

@gaberudy
Copy link
Copy Markdown

@gaberudy gaberudy commented May 3, 2026

When video_mode_available is true, writeLosslessRefresh() early-returns without emitting an FBU. That's correct for the lossless-refresh data path (video mode owns the pixel stream), but it also drops any pending pseudo-encoding rects: cursor shape, cursor position, LED state.

The downstream effect: cursor SHAPE updates (e.g. xfwm4 swapping in the N-S-resize cursor as the pointer approaches a window edge) sit in needSetCursor until some other framebuffer activity triggers a fresh FBU. On an idle desktop the cursor stays whatever it was last drawn as, even after seconds of pointer movement.

Trace into VNCSConnectionST::writeDataUpdate():

if (ui.is_empty() && !writer()->needFakeUpdate() && ...) return;
...
if (!ui.is_empty()) {
encodeManager.writeUpdate(...);
} else {
encodeManager.writeLosslessRefresh(...); // ← we land here
}

So when only a pseudo-encoding is pending and there are no pixel changes, control routes to writeLosslessRefresh, which then bails on video mode without flushing the pseudo-rects.

Fix: before bailing, send a pseudo-only FBU if needFakeUpdate() is set. Uses pseudoEncodingLastRect (or counted nRects when the client doesn't support last-rect) so the message is self-terminating.

When `video_mode_available` is true, `writeLosslessRefresh()` early-returns
without emitting an FBU. That's correct for the lossless-refresh data path
(video mode owns the pixel stream), but it also drops any pending
pseudo-encoding rects: cursor shape, cursor position, LED state.

The downstream effect: cursor SHAPE updates (e.g. xfwm4 swapping in the
N-S-resize cursor as the pointer approaches a window edge) sit in
`needSetCursor` until some other framebuffer activity triggers a fresh
FBU. On an idle desktop the cursor stays whatever it was last drawn as,
even after seconds of pointer movement.

Trace into `VNCSConnectionST::writeDataUpdate()`:

  if (ui.is_empty() && !writer()->needFakeUpdate() && ...) return;
  ...
  if (!ui.is_empty()) {
      encodeManager.writeUpdate(...);
  } else {
      encodeManager.writeLosslessRefresh(...);   // ← we land here
  }

So when only a pseudo-encoding is pending and there are no pixel changes,
control routes to `writeLosslessRefresh`, which then bails on video mode
without flushing the pseudo-rects.

Fix: before bailing, send a pseudo-only FBU if `needFakeUpdate()` is set.
Uses `pseudoEncodingLastRect` (or counted nRects when the client doesn't
support last-rect) so the message is self-terminating.
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.

1 participant