Skip to content

Keep off-screen culling paused while dragging - #321

Merged
dovvnloading merged 1 commit into
mainfrom
fix/drag-culls-dragged-node
Aug 14, 2026
Merged

Keep off-screen culling paused while dragging#321
dovvnloading merged 1 commit into
mainfrom
fix/drag-culls-dragged-node

Conversation

@dovvnloading

Copy link
Copy Markdown
Owner

Problem

The canvas saves work by only rendering nodes that are currently inside the visible area. That optimization stayed active during drag gestures. When a drag makes the view follow the pointer, nodes and connections near the edge of the screen cross in and out of the visible area mid-gesture, and the renderer was removing and re-inserting them while everything was moving. On a crowded canvas this showed up as nodes and connections popping in and out during a drag - measured at over a hundred consecutive frames with a node and its connection missing during one drag that panned the view.

Change

A flag now tracks each drag gesture from its first movement to its release, and the only-render-visible optimization is paused while the flag is set - the same suspension mechanism the image-export path already uses. Culling resumes as soon as the drag ends, so the savings on large scenes are unchanged except during the gesture itself.

Test plan

  • Full frontend check passes: schema check, type check, lint (0 errors), 1927/1927 tests, production build, bundle-size check
  • Scripted-drag measurement in headless Chromium, before and after: with the fix, zero frames during a boundary-crossing drag had the dragged node or its connection unrendered, and connection endpoints stayed within 8 pixels of the node's connection point on every frame - including with the processor throttled sixfold to simulate a heavily loaded machine

The canvas only renders nodes currently inside the viewport. That rule
stayed active during drag gestures, so when a drag made the view follow
the pointer, any node or connection crossing the viewport edge was
removed or inserted mid-gesture - visible popping while things were
moving. Measured on a crowded scene: a node and its connection stayed
unrendered for over a hundred consecutive frames during a single drag
that panned the view.

The fix mirrors the existing export-time suspension: a dragActive flag
tracks the gesture from its first movement to its release, and
off-screen culling is paused while it is set. Culling resumes the moment
the drag ends, so the memory and render savings on large scenes are
unchanged for everything except the duration of a gesture.

Verified with a scripted-drag measurement in headless Chromium: with the
fix, zero frames during a boundary-crossing drag had the dragged node or
its connection unrendered; connection endpoints stayed within the handle
radius (under 8 pixels) of the node on every frame, including with the
processor throttled sixfold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dovvnloading
dovvnloading merged commit 5fe6f37 into main Aug 14, 2026
4 checks passed
@dovvnloading
dovvnloading deleted the fix/drag-culls-dragged-node branch August 14, 2026 17:32
dovvnloading added a commit that referenced this pull request Aug 14, 2026
These three changes were attempts at the drag artifact that were not
confirmed to work before shipping, and the most recent one made things
worse: with #324 in place the connection lag became visible in the light
theme as well, where it had previously been unnoticeable.

The most likely cause of that regression is the composition flag. The
audit behind #324 established that the flag added in #323 never reached
the browser, because the window library passes a conflicting switch and
duplicate switches resolve last-one-wins. #324 corrected the delivery,
so disabling delegated composition took effect for the first time - and
it applies to both themes equally, which matches the report exactly. The
stroke width increase and the explicit high-quality smoothing hint in
the same change also affect both themes and cannot be ruled out.

This restores graphlink_desktop.py, styles.css and gl-vars-dev.css to
their state as of #321. The measured performance fixes in #319, #320 and
#321 are untouched.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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