Skip to content

BUG: Cmd/Ctrl+A does not select all in the chat input #115

Description

@jeonghun-jj-lee

Important

Problem: Standard editing shortcuts (Cmd+A, Cmd+C, Cmd+X, Cmd+Z, Cmd+Y) are dead in the chat input — no select-all, no copy, no undo. Only shortcuts with explicit JS handlers (Cmd+V paste, Cmd+U attach) work.

Approach: Generalize the existing installGlobalPasteFallback (patch #11) into a document-level keydown handler that explicitly implements selectAll, copy, cut, undo, and redo in JS — the same "don't rely on native browser defaults" pattern that already fixed paste.

Scope: All standard editing Cmd+key shortcuts in any editable element inside the chat iframe. Non-editing shortcuts (Cmd+F, etc.) are out of scope.


Root cause

The chat input is a contenteditable div inside a sandboxed cross-origin iframe (sandbox="allow-scripts allow-forms allow-same-origin allow-popups allow-downloads") embedded in a VS Code WebviewPanel.

Confirmed by code audit: no app code calls preventDefault() or stopPropagation() on Cmd+A/C/Z when the target is the contenteditable. The command.tsx capture-phase handler explicitly returns early for clipboard chords on editable targets. CSS user-select is correctly set to text. The iframe sandbox and Permissions-Policy (clipboard-read; clipboard-write) are permissive.

Conclusion by elimination: the VS Code / Electron platform layer suppresses native browser actions for these shortcuts. Keydown events DO reach the iframe (typing works, Cmd+V's explicit handler works), but the associated DOM default action (selectAll, clipboard copy, undo) never fires. The Electron Edit-menu accelerators or VS Code's webview keyboard routing consumes the action at the platform level.

This is the same class of bug that affected paste (patch #11): native browser defaults cannot be relied on inside this sandboxed-iframe-in-a-webview architecture. The fix is the same pattern: explicit JS implementation, activated only in the framed context.

Affected shortcuts

Shortcut Native action Status Notes
Cmd+V Paste Works Patch #11 — explicit handleKeyDown + bridge
Cmd+U Attach file Works Explicit handleKeyDown
Cmd+A Select all Broken Native selectAll suppressed
Cmd+C Copy Broken global-clipboard.ts bridge either doesn't fire or silently fails
Cmd+X Cut Broken Same mechanism as Cmd+C
Cmd+Z Undo Broken Native undo suppressed
Cmd+Shift+Z / Cmd+Y Redo Broken (assumed) Same mechanism as undo

Approach: Global editing fallback (extends patch #11)

Architecture

Extend installGlobalPasteFallback (or rename it to installGlobalEditingFallback) in packages/app/src/utils/global-clipboard.ts to cover all standard editing shortcuts. Single install point in entry.tsx.

Activation guard (same as paste fallback):

  • window.parent !== window — only fires in the framed/VS Code context; plain browser keeps native behavior
  • Target is an editable element (input, textarea, or [contenteditable])
  • event.metaKey || event.ctrlKey (platform-appropriate modifier)

Implementation per shortcut

Shortcut JS implementation
Cmd+A event.preventDefault() + window.getSelection().selectAllChildren(editableRoot) where editableRoot is the closest [contenteditable] ancestor (for input/textarea: .select())
Cmd+C event.preventDefault() + extract selection text + writeClipboardViaBridge() (the bridge from patch #11; diagnose why global-clipboard.ts's existing Cmd+C path silently fails — likely the bridge response never arrives)
Cmd+X Same as Cmd+C + deleteFromDocument() on the selection
Cmd+Z event.preventDefault() + document.execCommand('undo') on the contenteditable (browser-managed undo stack)
Cmd+Shift+Z / Cmd+Y event.preventDefault() + document.execCommand('redo')

File changes

  • packages/app/src/utils/global-clipboard.ts — extend installGlobalPasteFallback to handle a, z, y in addition to existing v, c, x (fix the existing broken Cmd+C/X path while here)
  • packages/app/src/entry.tsx — no change needed (already installs the fallback)
  • Zero extension-side changes, zero package.json keybinding contributions

Diagnostic confirmation (pre-implementation)

To record the exact Electron mechanism (for AMICODE-PATCHES.md's root-cause documentation):

// Paste into the iframe's devtools console:
document.addEventListener('keydown', e => {
  if (e.metaKey) console.log(`META+${e.key}`, 'defaultPrevented:', e.defaultPrevented, 'target:', e.target.tagName)
}, true)

If defaultPrevented: true for Cmd+A, the event arrives already cancelled by Electron. If false, the native action is cancelled AFTER JS dispatch (accelerator fires asynchronously). Either way, the fix is the same — explicit JS implementation.

Approaches considered

# Approach Verdict
C Global keydown fallback (extends patch #11) Selected — proven pattern, single install point, no extension-side changes
A Per-element explicit handlers in handleKeyDown Rejected — scatters the fix across components; doesn't cover non-prompt editables (API key fields, etc.)
B VS Code extension-side command forwarding via package.json keybindings Rejected — requires focus-context tracking, when clause management, couples fix to VS Code API surface

Acceptance criteria

  • Cmd+A selects all text in the chat input (contenteditable)
  • Cmd+C copies mouse-selected or Cmd+A-selected text to OS clipboard
  • Cmd+X cuts selected text to OS clipboard
  • Cmd+Z undoes the last edit in the chat input
  • Cmd+Shift+Z (or Cmd+Y) redoes
  • All of the above also work in other editables inside the iframe (API key fields, search inputs)
  • Plain browser tab at http://127.0.0.1:{port} is unaffected (native behavior preserved)
  • Existing Cmd+V paste behavior unchanged
  • bun test passes, typecheck green

Constraints & invariants

  • The framed-context guard (window.parent !== window) MUST remain — non-VS-Code contexts keep native behavior.
  • global-clipboard.ts's existing Cmd+C bridge path must be FIXED, not duplicated — diagnose why writeClipboardViaBridge silently fails and repair it.
  • execCommand('undo'/'redo') is deprecated but functional in all Chromium-based webviews. A proper undo manager is out of scope (separate issue if needed).

Prior art


Diagnostics (original filing)

intake: ready
suggested_path: C
diagnostics: inline
upstream: anomalyco/opencode#8504 (open); #25637 closed not-planned (same symptom, TUI input)

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions