Skip to content

Render local input responses immediately#553

Merged
migueldeicaza merged 2 commits into
migueldeicaza:mainfrom
evertjr:fix/immediate-input-redraw
Jul 1, 2026
Merged

Render local input responses immediately#553
migueldeicaza merged 2 commits into
migueldeicaza:mainfrom
evertjr:fix/immediate-input-redraw

Conversation

@evertjr

@evertjr evertjr commented May 19, 2026

Copy link
Copy Markdown
Contributor

Reopened version of #542 on top of the recent sync-output rework.

Problem

After 9446f60, the remaining typing-lag source is the 16.67ms throttle in queuePendingDisplay. When output bursts coincide with keystrokes, pendingDisplay stays armed and subsequent keystrokes get coalesced into the next 60Hz tick. Perceptible as occasional "skipped" characters that appear together a frame later.

In practice this surfaces most when the host is under load — we see it consistently when many terminals are running concurrently in Maestri.

Fix

Input-immediate bypass only, no settle-window machinery. If output arrives within 150ms of a keystroke and we're not in a sync block, paint synchronously instead of via asyncAfter(+16.67ms). Complementary to the sync-output simplification on main.

Tests

Confirmed in Maestri against the same workloads that motivated the first PR.

evertjr added 2 commits May 19, 2026 19:28
When output arrives within 150ms of a keystroke and the terminal isn't
inside a DEC 2026 sync block, paint synchronously on the main runloop
instead of going through queuePendingDisplay's 16.67ms frame throttle.

Without this, input echo waits one 60Hz tick. When output bursts
coincide with typing, pendingDisplay stays armed and subsequent
keystrokes are coalesced into the next tick, producing a perceptible
"skipped characters appear together" feel.

Complementary to the recent sync-output simplification on main.
The SyncDebug type is not defined in the tree, so main currently fails
to compile. Stripping the call sites in Terminal.swift and
AppleTerminalView.swift unblocks CI on this PR.

Easy to revert if SyncDebug is reintroduced later.
@evertjr

evertjr commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

Added a second commit dropping the SyncDebug.log(...) call sites in Terminal.swift and AppleTerminalView.swift. The SyncDebug type isn't defined anywhere in the tree, so main itself doesn't compile and CI on this PR was inheriting that failure. Easy to revert if you bring SyncDebug back.

@migueldeicaza

Copy link
Copy Markdown
Owner

Apologies for the delay, question about this.

displayImmediately() can schedule a separate main-thread redraw for every feed chunk.

It looks like feedFinish() calls displayImmediately() without using pendingDisplay to coalesce redraws. Then when we run the feed on the main thread we post a new call to the main queue every time.

Seems like the immediate path should still bypass the 16.67 ms timer, but it needs to coalesce duplicate redraw requests. For example, set pendingDisplay before posting the immediate main-queue block, then clear it once the redraw runs.

@migueldeicaza

Copy link
Copy Markdown
Owner

Let me merge and add the suggestion

@migueldeicaza migueldeicaza merged commit 471c978 into migueldeicaza:main Jul 1, 2026
1 check failed
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.

2 participants