From cc850f181da75a2a74ab8491b0b4659f03bdf7f1 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Thu, 23 Jul 2026 11:04:14 +0200 Subject: [PATCH] viewer: don't rebuild the overlay while panning Overlay items live in scene coordinates, so QGraphicsView translates them natively as the view scrolls - no rebuild is required to keep them in the right place during a pan. Rebuilding on every scroll signal only re-ran the spot/prediction viewport culling, at the cost of tearing down and recreating every overlay item on each mouse-move step. Over remote X forwarding that per-step rebuild (and the rasterised pixels it dirties) is the dominant source of pan lag. Skip the rebuild while a pan drag is in progress: onScroll() returns early during a Panning gesture and the pan branch of mouseMoveEvent no longer schedules one. The overlay is refreshed once when the pan ends, via the existing mouseReleaseEvent -> updateROI() -> updateOverlay() path, which re-runs culling for the revealed viewport. Trade-off: spots/predictions in newly revealed regions appear on release rather than mid-drag. Co-Authored-By: Claude Opus 4.8 (1M context) --- viewer/image_viewer/JFJochImage.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/viewer/image_viewer/JFJochImage.cpp b/viewer/image_viewer/JFJochImage.cpp index c266660b..46711144 100644 --- a/viewer/image_viewer/JFJochImage.cpp +++ b/viewer/image_viewer/JFJochImage.cpp @@ -43,6 +43,15 @@ JFJochImage::JFJochImage(QWidget *parent) : QGraphicsView(parent) { } void JFJochImage::onScroll(int value) { + // While the user drags a pan, the scene scrolls natively and overlay items + // (which live in scene coordinates) move with it - no rebuild is needed. A + // single pan step emits up to two scrollbar valueChanged signals; rebuilding + // the overlay on each would tear down and recreate every item for no visual + // change - the dominant lag over remote X. The overlay is refreshed once + // when the pan ends (mouseReleaseEvent -> updateROI -> updateOverlay), which + // re-runs spot/prediction culling for the newly revealed viewport. + if (mouse_event_type == MouseEventType::Panning) + return; scheduleOverlayUpdate(); } @@ -221,7 +230,9 @@ void JFJochImage::mouseMoveEvent(QMouseEvent *event) { horizontalScrollBar()->setValue(horizontalScrollBar()->value() - viewDelta.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - viewDelta.y()); - scheduleOverlayUpdate(); + // No overlay rebuild while dragging: the scene scrolls natively and + // items move with it. onScroll() skips rebuilds during a pan and the + // overlay is refreshed once on mouse release. emitViewportChanged(); break; }