Skip to content

fix(desktop): isolate preview keyboard input - #9522

Closed
0bkevin wants to merge 1 commit into
pingdotgg:mainfrom
0bkevin:t3code/fix-thread-input-focus-loss
Closed

fix(desktop): isolate preview keyboard input#9522
0bkevin wants to merge 1 commit into
pingdotgg:mainfrom
0bkevin:t3code/fix-thread-input-focus-loss

Conversation

@0bkevin

@0bkevin 0bkevin commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

What Changed

  • Route desktop preview_press input to the exact registered preview WebContents without focusing the guest, focusing the host window, or bringing a debugger target to the front.
  • Correlate native input delivery with the target tab, attachment, document, and request so navigation, tab replacement, human input, and stale acknowledgements fail safely.
  • Add typed success and failure results across the contracts, Electron IPC bridge, and web consumer.
  • Restrict press inputs to native-representable named keys and printable ASCII; Unicode text continues to use preview_type.
  • Add focused coverage for concurrent tabs, background threads, focus preservation, recording leases, human takeover, navigation, and uncertain delivery quarantine.

This carries forward the exact-target native delivery design from #8494 and combines it with the focus-preservation goal explored in #4118 and #5898, rebased and hardened against current main.

Why

Browser automation in one thread could temporarily focus its preview WebContents, stealing focus from the composer in another active thread. Capturing and restoring DOM focus only masks that handoff and can restore stale focus after the user has moved elsewhere.

The safer invariant is that preview keyboard automation never borrows UI focus. It now delivers only to the requested preview and fails explicitly if Electron cannot guarantee that target. In particular, an unfocused or minimized desktop window returns a typed failure instead of focusing T3 Code or silently misdelivering input.

Fixes #5792
Fixes #3715

UI Changes

No visual UI changes. The interaction change is that background preview key presses no longer move focus away from the active thread composer.

Verification

  • 168 focused tests across desktop preview management, keyboard packets, IPC, web request consumption, and contracts
  • Targeted typechecks for @t3tools/contracts, @t3tools/desktop, and @t3tools/web
  • Formatting, targeted lint, and git diff checks
  • Independent correctness review after the final race-condition fixes
  • Not run: headed native Electron smoke test

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • Screenshots are not applicable because there are no visual changes
  • A video is not applicable because there are no animation changes

Built with GPT-5.6 Sol in T3 Code through the Codex harness.

Note

Isolate preview keyboard input with native Electron packets and delivery confirmation

  • Replaces Chromium CDP key-dispatch with Electron native KeyboardInputEvent packets carrying key-down/key-up phase and modifier state, sent directly to the selected guest WebContents without host focus
  • Requires renderer receipt confirmation within a 1-second timeout; uncertain delivery quarantines subsequent presses until committed navigation clears the hazard
  • Adds attachment-identity validation so registration, navigation, and tab-close reject stale or replaced WebContents targets with typed PreviewManagerError variants
  • Correlates human input with active automation by sender/frame/process metadata; unmatched key sequences invalidate pending delivery before human control is claimed
  • Constrains PreviewAutomationPressKey to named keys, F1–F12, and printable ASCII (!~); unsupported keys now raise an error directing Unicode text to preview_type
  • Risk: resolveKeyDefinition in PreviewKeyboard.ts removes the generic unknown-key fallback; callers passing unsupported keys get an error instead of a zero-code packet. MAC_EDITING_COMMANDS and modifierMask are removed, so any out-of-tree consumers of Chromium-shaped packets will break.

Macroscope summarized 80d7cf3.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Sep 4, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 80d7cf3. Configure here.

if (existing) {
existing.active = false;
yield* Scope.close(existing.scope, Exit.void).pipe(Effect.ignore);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Session replace hits attached debugger

Medium Severity

ensureControlSession now tries to replace a live session whose attachmentId or tabId no longer matches, but it still fails on wc.debugger.isAttached() before closing that session. The later close-and-recreate path never runs for an attached debugger, so automation surfaces PreviewAutomationDebuggerAttachedError instead of taking over the current guest.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 80d7cf3. Configure here.

@macroscopeapp

macroscopeapp Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR substantially changes preview keyboard behavior and shared automation/session lifecycle code, including a new cross-process delivery protocol and IPC error contract. Its broad production blast radius, together with an unresolved target-replacement concern, warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@0bkevin 0bkevin closed this Sep 4, 2026
@0bkevin
0bkevin deleted the t3code/fix-thread-input-focus-loss branch September 4, 2026 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Browser automation steals composer focus across threads [Bug]: preview_press does not reliably target the preview page

1 participant