Skip to content

Commit 5955e3a

Browse files
charliekclaude
andcommitted
fix(input): re-arm the tab-drag inside the accent fence poll (tiny-skia CI)
Pre-existing on main since plan 026 (fails main@337cd17; 4/4 deterministic on the ubuntu tiny-skia cell, wgpu unaffected): iced dispatches queued input against one latest cursor position, so when the drag gesture pressed the ALREADY-ACTIVE pill — no selection change, no redraw — the press and the harness's single 12px arming nudge shared a batch and ReorderStrip recorded the gesture origin ON the nudge: distance 0, the 8px threshold never crossed, the drag border never painted, and the harness blocked forever ("timed out waiting for backward tab source press render"). The tiny-skia/wgpu split was pure redraw cadence, not paint or input — proven by CI-side instrumentation (origin=(477,15) distance=0.0 on the failing cell) and bit-identical band pixels between the CI failure capture and a shed baseline. The fence stays strictly causal (poll until the drag-began accent run spans the press x; no sleeps); the arming move is now re-issued inside the poll alternating between the nudge point and the press point — both inside the source pill — so whichever point the press was attributed to, the other crosses the threshold, and each poll's screenshot render forces a batch boundary. Backtracking never un-arms a started drag. Verified on the authoritative surface: the real CI tiny-skia AND wgpu cells both green with this fix alone, plus clean shed runs of the full check under both renderers. codex review: no findings. Full diagnosis recorded with plan 027 (tinyskia-drag-diagnosis.md). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AyvCPrbetEKy3iHgKLQmwq
1 parent a4fcbe3 commit 5955e3a

1 file changed

Lines changed: 35 additions & 9 deletions

File tree

tools/input/linux/iced_clipboard_check.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,19 +1150,45 @@ def preview_accent_capture() -> tuple[tuple[int, int] | None, bytes]:
11501150
)
11511151
# Plan 026 deferred the accent border to the real drag
11521152
# threshold (strip_reorder DRAG_THRESHOLD = 8px), so a bare
1153-
# press renders nothing. Cross the threshold with a small
1154-
# nudge toward the target first; the drag-began border then
1155-
# serves the same causal purpose — Iced has consumed the
1156-
# press and armed the drag before the trajectory runs. Once
1157-
# dragging, backtracking never un-arms, so a step-1 position
1158-
# behind the nudge is safe.
1153+
# press renders nothing. Cross the threshold before fencing;
1154+
# the drag-began border then serves the same causal purpose —
1155+
# Iced has consumed the press and armed the drag before the
1156+
# trajectory runs.
1157+
#
1158+
# One nudge is not enough. Iced evaluates every event in a
1159+
# redraw batch against the *latest* cursor position, so a
1160+
# press that changes nothing on screen (re-pressing the pill
1161+
# that is already active) need not force a redraw between
1162+
# itself and the nudge that follows: both land in one batch,
1163+
# the gesture records the nudge's own x as its origin, and
1164+
# `origin.distance(current)` is 0 — the drag can never arm,
1165+
# however long the fence waits. That is what made this
1166+
# deterministic on CI's loaded tiny-skia runner and invisible
1167+
# on an idle box.
1168+
#
1169+
# Alternating between two points 12px apart makes arming
1170+
# independent of which of them the press was attributed to:
1171+
# whichever one it lands on, the other is a threshold
1172+
# crossing. Both stay inside the source pill, so a coalesced
1173+
# press still hits the intended child, and each capture's
1174+
# render is a batch boundary between moves. Once dragging,
1175+
# moving back never un-arms, so the trajectory below is
1176+
# unaffected.
11591177
nudge_x = x0 + (12 if target_x >= x0 else -12)
1160-
launch.terminal_pointer(
1161-
["mousemove", "--window", launch.window, str(nudge_x), str(y)]
1162-
)
1178+
arming = [nudge_x, x0]
11631179
pressed_capture: list[bytes] = []
11641180

11651181
def source_press_rendered() -> bool:
1182+
launch.terminal_pointer(
1183+
[
1184+
"mousemove",
1185+
"--window",
1186+
launch.window,
1187+
str(arming[0]),
1188+
str(y),
1189+
]
1190+
)
1191+
arming.reverse()
11661192
run, png = preview_accent_capture()
11671193
if run is None:
11681194
return False

0 commit comments

Comments
 (0)