Skip to content

fix(terminal): let app shortcuts pass through xterm terminals#1411

Merged
arnestrickmann merged 4 commits intogeneralaction:mainfrom
ckafrouni:fix/terminal-shortcuts-passthrough
Mar 11, 2026
Merged

fix(terminal): let app shortcuts pass through xterm terminals#1411
arnestrickmann merged 4 commits intogeneralaction:mainfrom
ckafrouni:fix/terminal-shortcuts-passthrough

Conversation

@ckafrouni
Copy link
Contributor

@ckafrouni ckafrouni commented Mar 11, 2026

Fixes #1410Cmd+. (toggle right sidebar) and other app shortcuts were swallowed when focus was in any xterm.js terminal.

Root cause (two layers):

  1. Terminal handler consumed the event: TerminalSessionManager.ts's attachCustomKeyEventHandler returned true for unhandled Cmd+key combos, telling xterm to process them and preventing propagation to the global shortcut listener.

  2. Global shortcut handler skipped the event: useKeyboardShortcuts.ts treats any TEXTAREA target as an editable field and skips most shortcuts — but xterm uses a hidden <textarea class="xterm-helper-textarea"> for keyboard capture, so all app shortcuts were silently skipped when a terminal had focus.

Fix (3 parts):

  1. Centralized shortcut check in the terminal handler (TerminalSessionManager.ts): Instead of a broad modifier guard that would break terminal control sequences (Ctrl+C, Ctrl+D, Ctrl+Z, etc.) on Linux/Windows, the terminal handler now imports APP_SHORTCUTS and pre-computes sets of registered shortcut keys. Only key combos that match an actual app shortcut pass through to the global handler — everything else stays with xterm. This is cross-platform safe and automatically covers future shortcuts.

  2. xterm textarea exclusion in the global handler (useKeyboardShortcuts.ts): Excluded xterm's xterm-helper-textarea from the editable-target check so app shortcuts are recognized when originating from a terminal.

  3. Sidebar focus blur (RightSidebar.tsx): When the right sidebar collapses, any focused element inside it (e.g. the sidebar terminal) is blurred so focus returns to the main content area. Agent terminals in the main panel are unaffected.

Test plan

  • Open a task (agent terminal gets focus) → press Cmd+. → right sidebar toggles
  • Click sidebar terminal → press Cmd+. → sidebar closes and terminal loses focus
  • Press Cmd+B → left sidebar toggles
  • Press Cmd+K → command palette opens
  • Normal terminal input still works (typing, Enter, Ctrl+C, etc.)
  • Cmd+C still copies selected text in terminal
  • Cmd+Backspace still clears the line
  • Cmd+Left/Right still navigates to start/end of line

ckafrouni and others added 2 commits March 11, 2026 14:09
…laction#1410)

Cmd+. (toggle right sidebar) and other app shortcuts were swallowed
when an xterm terminal had focus. Two issues contributed:

1. The terminal's custom key handler returned true for unhandled
   Cmd+key combos, telling xterm to consume them. Added a modifier
   guard that returns false so these events propagate to the window.

2. The global shortcut handler skipped shortcuts when event.target
   was a TEXTAREA — but xterm uses a hidden textarea for keyboard
   capture. Excluded xterm's xterm-helper-textarea from the
   editable-target check so app shortcuts fire from terminals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When Cmd+. collapses the right sidebar, any focused element inside it
(such as xterm's hidden textarea) is now blurred so focus returns to the
main content area. Agent terminals in the main panel are unaffected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 11, 2026

@ckafrouni is attempting to deploy a commit to the General Action Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 11, 2026

Greptile Summary

This PR fixes a two-layer problem that caused app-level keyboard shortcuts (Cmd+., Cmd+B, Cmd+K, etc.) to be swallowed when focus was inside an xterm.js terminal. The approach is correct in concept: make xterm pass unhandled modifier-key combos up to the window-level shortcut handler, and stop the global shortcut hook from treating the hidden xterm textarea as a regular editable field.

Key changes:

  • TerminalSessionManager.ts: A new guard returns false from xterm's custom key handler for Cmd+key (macOS) / Ctrl+key (non-Mac) combos that aren't already handled by terminal-specific bindings, allowing events to propagate to the window-level shortcut handler.
  • useKeyboardShortcuts.ts: Excludes xterm-helper-textarea from the isEditableTarget check so app shortcuts are recognized even when the terminal has focus. This change is clean and correct.
  • RightSidebar.tsx: Adds a useEffect to blur the focused element inside the sidebar when it collapses, returning focus to the main content area. This change is clean and correct.

Critical regression on Linux/Windows: The Ctrl+key guard in TerminalSessionManager.ts is too broad — it returns false for all Ctrl+key combinations on non-Mac platforms, not only the ones that map to app shortcuts. Because returning false from xterm's custom key handler prevents xterm from forwarding the event to the PTY, fundamental terminal control sequences (Ctrl+C for SIGINT, Ctrl+D for EOF, Ctrl+Z for SIGTSTP, Ctrl+L for clear screen, and readline navigation keys) will stop working in the terminal for Linux and Windows users. The test plan only covers macOS (Cmd+*) and does not verify these Linux/Windows scenarios.

Confidence Score: 2/5

  • Not safe to merge as-is — the Ctrl+key guard in TerminalSessionManager.ts breaks all terminal control sequences (Ctrl+C, Ctrl+D, Ctrl+Z, etc.) on Linux and Windows.
  • Two of the three changes (useKeyboardShortcuts.ts, RightSidebar.tsx) are correct and safe. The third change (TerminalSessionManager.ts) contains a critical regression: the new modifier guard returns false for every Ctrl+key combo on non-Mac platforms, which prevents xterm from forwarding control characters to the PTY. This silently breaks the ability to interrupt processes, send EOF, suspend jobs, and use readline navigation in the terminal on Linux and Windows. The macOS path is unaffected.
  • src/renderer/terminal/TerminalSessionManager.ts — the Ctrl+key pass-through guard (lines 388-393) must be scoped to only the app-shortcut keys, not all Ctrl combos.

Important Files Changed

Filename Overview
src/renderer/terminal/TerminalSessionManager.ts New return false guard for Ctrl+key combos on non-Mac platforms is too broad — it blocks Ctrl+C (SIGINT), Ctrl+D (EOF), Ctrl+Z (SIGTSTP), and all other xterm control-character sequences from reaching the PTY, breaking fundamental terminal functionality on Linux/Windows.
src/renderer/hooks/useKeyboardShortcuts.ts Correctly excludes xterm-helper-textarea from the editable-target check using classList.contains, with safe optional chaining. Logic is sound and targeted.
src/renderer/components/RightSidebar.tsx Adds asideRef and a useEffect to blur any focused element inside the sidebar when it collapses. Implementation is clean and correctly scoped to the sidebar subtree.

Sequence Diagram

sequenceDiagram
    participant User
    participant xterm as xterm.js<br/>(xterm-helper-textarea)
    participant TSM as TerminalSessionManager<br/>attachCustomKeyEventHandler
    participant PTY as PTY Process
    participant KS as useKeyboardShortcuts<br/>(window keydown)
    participant App as App Handler

    Note over User,App: Before this PR — Cmd+. in terminal (macOS)
    User->>xterm: Cmd+. keydown
    xterm->>TSM: custom handler (returns true)
    TSM-->>xterm: true → xterm processes it
    Note over KS: target is TEXTAREA → isEditableTarget=true<br/>shortcut skipped
    Note over App: Cmd+. never reaches app

    Note over User,App: After this PR — Cmd+. in terminal (macOS)
    User->>xterm: Cmd+. keydown
    xterm->>TSM: custom handler
    Note over TSM: metaKey + not in handled list → return false
    TSM-->>xterm: false → xterm skips it, event propagates
    xterm->>KS: keydown bubbles to window
    Note over KS: isXtermTextarea=true → isEditableTarget=false<br/>shortcut matched
    KS->>App: toggleRightSidebar()
    App->>xterm: sidebar collapses → RightSidebar useEffect blurs focused element
    xterm-->>User: focus returned to main area

    Note over User,App: Regression — Ctrl+C (no selection) on Linux
    User->>xterm: Ctrl+C keydown (no selection)
    xterm->>TSM: custom handler
    Note over TSM: copy handler skipped (no selection)<br/>new guard: ctrlKey + non-Mac → return false
    TSM-->>xterm: false → xterm does NOT send SIGINT to PTY
    PTY-->>User: running process NOT interrupted ❌
Loading

Last reviewed commit: 34c905b

ckafrouni and others added 2 commits March 11, 2026 14:20
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…fier guard

Replaces the broad Cmd+key / Ctrl+key pass-through with a precise
check against registered app shortcut keys. This prevents breaking
terminal control sequences (Ctrl+C, Ctrl+D, Ctrl+Z, etc.) on
Linux/Windows where Ctrl is used for both app shortcuts and terminal
signals.
@ckafrouni
Copy link
Contributor Author

ckafrouni commented Mar 11, 2026

I'm using APP_SHORTCUTS now, so only actual app shortcuts passthrough now.
I tested the terminal shortcuts i know, and only the app-shortcuts escape the terminal.
(tested on mac only)

@arnestrickmann
Copy link
Contributor

Thanks for catching this and for taking this on!
Will review and lyk soon!

@arnestrickmann arnestrickmann merged commit bd1f578 into generalaction:main Mar 11, 2026
2 of 3 checks passed
@ckafrouni ckafrouni deleted the fix/terminal-shortcuts-passthrough branch March 11, 2026 18:27
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.

[bug]: Cmd+. (toggle right sidebar) does not work when terminal has focus

2 participants