Over "ssh -X" the viewer was near unusable, and the July finding that every
repaint uploads the whole window (5.3 MiB at the default size) regardless of
how small the damage is turns out to have a single cause: the reciprocal-space
window constructed a QOpenGLWidget at startup, and one dormant QOpenGLWidget -
unmapped, in a window nobody ever opened - switches Qt's window composition
onto the OpenGL swapchain path. That path re-presents the entire window on
every flush (and is also the llvmpipe CPU burn seen on headless boxes). The
reciprocal-space window was a placeholder feature and is removed; with it gone
Qt flushes through the raster backing store, which sends only the damaged
region.
On top of that, interactions that repainted once per input event are held to
the hover cadence (15 Hz) on remote sessions only: panning accumulates its
pixel delta, wheel zoom its steps, a recolour burst its final value, live
playback keeps only the newest frame (the worker ack stays per-frame), and the
toolbar counter/slider readbacks coalesce the same way. Each throttle applies
inline with a single-shot tail, the same shape as the existing hover limiter,
so the view always lands exactly where the gesture put it. Local sessions are
unchanged - every event still applies inline.
Remote sessions are detected once at startup (xcb platform and a DISPLAY with
a host part, i.e. "localhost:10.0" from SSH forwarding or "host:0"); the
JFJOCH_VIEWER_REMOTE environment variable and a View-menu toggle override the
detection in either direction.
Measured through a byte-counting X relay against Xvfb with MIT-SHM disabled
(client-to-server bytes are what the SSH link carries), same scripted
interaction sequence, 1200x1100 window, KiB:
rc169 removal only removal+throttles
hover, 50 motions 82088 2040 2040
pan, 50 motions 290046 12087 4778
wheel zoom x10 71143 12603 7649
ctrl-wheel x6 65672 7194 4797
frame step x10 284572 21454 21454
Removing the reciprocal-space window from the source measured byte-identical
to only deferring its GL view to first show, confirming the cost is the live
QOpenGLWidget, not the code being compiled in. The image panel renders
pixel-identically (AE=0) to rc169 after identical zoom+pan gestures, with the
throttles on and off.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WbjnQhutnboy4qbxwmgDAX
17 lines
867 B
C++
17 lines
867 B
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#pragma once
|
|
|
|
// Whether the viewer talks to its display server across a network link (ssh -X and the like).
|
|
// On such a link every repaint is shipped as pixels, so interactions that repaint per input
|
|
// event are throttled to the hover cadence instead. Detected once from the session; the
|
|
// JFJOCH_VIEWER_REMOTE environment variable (0/1) and the View-menu toggle override it.
|
|
// Only call after QApplication exists - detection reads the platform name.
|
|
bool RemoteDisplayMode();
|
|
void SetRemoteDisplayMode(bool active);
|
|
|
|
// The cadence remote-throttled updates run at, chosen to match JFJochImage's hover rate limit:
|
|
// far below the input event rate, above what the eye follows.
|
|
constexpr int kRemoteRepaintIntervalMs = 66;
|