Skip to content

Harden replay synchronization and add focus-at verb#16

Merged
jserv merged 1 commit into
mainfrom
motif
Jun 16, 2026
Merged

Harden replay synchronization and add focus-at verb#16
jserv merged 1 commit into
mainfrom
motif

Conversation

@jserv

@jserv jserv commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Stabilize the motif-fileview-done smoke by anchoring the in-process snapshot on activity quiescence via wait-converge instead of a fixed delay.

Add a focus-at replay verb that resolves the X subwindow under a target-local point and calls XSetInputFocus on it via the main thread, exposing Motif's XmToggleButton focus-highlight rect that synthetic ButtonPress alone does not trigger.

Cover the SDL_USEREVENT round-trip surface in src/snapshot.c with shared helpers (prepareSnapshotRoundTrip, signalSnapshotResult, waitSnapshotResult), an SDL_atomic event-type, and a generation counter so a request that times out cannot have its stale event satisfy a fresh waiter. All three round-trips (snapshot, resize, focus-at) now carry a SnapshotEnvelope with generation + payload.

Mirror timelineTapXEvent inside popPutBackEvent so synthesized crossing chains and send-event payloads appear in timeline JSONL. Track alreadyTapped on PutBackEvent so events that already went through convertEvent's terminal tap (drainSdlEventsToPutBack) are not double-counted.

Tighten the wait-converge parser to reject trailing garbage; on timeout/divergence fall through to the runner's expected state-snapshot line instead of breaking out so the runner errors fast instead of polling 31s for a marker that would never arrive.

Add DEBUG-gated XLoadQueryFont / XCreateFontSet trace lines so the empirical font-parity investigation under the differential harness is reproducible without re-editing source.


Summary by cubic

Stabilizes replay sync by waiting for UI quiescence and adds a new focus-at verb to set X input focus on the correct subwindow. Hardens SDL round-trips with generation-tagged envelopes, improves event timeline coverage, tightens wait-converge parsing and failure handling, and fixes wheel scroll by pairing press/release to match X11.

  • New Features

    • Added focus-at x y to focus the subwindow under a target-local point (runs on the main thread). For xdotool, falls back to windowfocus and now requires a prior wait-window or errors.
    • Enhanced wait-converge: stricter validation, rejects trailing garbage, accepts failure-marker=path in any position. The runner writes a state-snapshot after it and writes/reads the failure marker to fail fast without breaking the script.
  • Refactors

    • Unified snapshot/resize/focus-at round-trips with a generation-tagged SnapshotEnvelope, atomic SDL event type, and shared helpers; stale events no longer satisfy new waits.
    • Timeline: put-back events are now tapped once; alreadyTapped prevents double counts and synthesized/send-event paths are tapped on delivery. Added a regression test for deferred Expose.
    • Input: SDL_MOUSEWHEEL now emits ButtonPress + matching ButtonRelease so Motif scroll actions fire; tests drain both.
    • Debug: added logs for XLoadQueryFont and XCreateFontSet. Minor runner error-message cleanups and stricter focus-at arg checks.

Written for commit ba52ece. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

@jserv jserv force-pushed the motif branch 2 times, most recently from 13894ca to f5cd2d3 Compare June 16, 2026 10:55
Stabilize the motif-fileview-done smoke by anchoring the in-process
snapshot on activity quiescence via wait-converge instead of a fixed
delay.

Add a focus-at replay verb that resolves the X subwindow under a
target-local point and calls XSetInputFocus on it via the main
thread, exposing Motif's XmToggleButton focus-highlight rect that
synthetic ButtonPress alone does not trigger.

Cover the SDL_USEREVENT round-trip surface in src/snapshot.c with
shared helpers (prepareSnapshotRoundTrip, signalSnapshotResult,
waitSnapshotResult), an SDL_atomic event-type, and a generation
counter so a request that times out cannot have its stale event
satisfy a fresh waiter. All three round-trips (snapshot, resize,
focus-at) now carry a SnapshotEnvelope with generation + payload.

Mirror timelineTapXEvent inside popPutBackEvent so synthesized
crossing chains and send-event payloads appear in timeline JSONL.
Track alreadyTapped on PutBackEvent so events that already went
through convertEvent's terminal tap (drainSdlEventsToPutBack) are
not double-counted.

Tighten the wait-converge parser to reject trailing garbage; on
timeout/divergence fall through to the runner's expected
state-snapshot line instead of breaking out so the runner errors
fast instead of polling 31s for a marker that would never arrive.

focus-at via the xdotool backend silently no-op'd when no prior
wait-window had cached a target window id. Mirror target-motion and
raise a deterministic ReplayError so a script misordering surfaces
instead of disappearing into a successful run.

X11 wheel input always arrives as a Button4/Button5 ButtonPress
followed immediately by a matching ButtonRelease, and Motif
translations (XmScrollBar, XmText) only fire their scroll actions
once they see the full press/release sequence. Synthesizing only the
press from SDL_MOUSEWHEEL leaves Btn4Down/Btn5Down translations
latched mid-sequence, so wheel scroll through libx11-compat appears
as a no-op while the same replay driven via xdotool against system
X11 scrolls correctly. This was the visible failure mode in
violawww-scroll-system.replay under the compat backend: vw never
moved a pixel after wheel-down, leaving the scrolled assertion at 0%
changed.

Synthesize the paired release inside convertEvent's SDL_MOUSEWHEEL
arm. Queue both at the put-back head (release first so the press
ends up on top after the second enqueue) and return -1 so all
consumer paths -- the main XNextEvent pump and the
drainSdlEventsToPutBack drains -- pull them through popPutBackEvent
in the correct order without the caller redundantly appending the
press behind the release we already queued.
@jserv jserv merged commit 4fb2357 into main Jun 16, 2026
12 checks passed
@jserv jserv deleted the motif branch June 16, 2026 11:11
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