fix(split-pane): gate app-level chords out of Pane B, address Ark0N's third pass

Pane B had no attachCustomKeyEventHandler of its own, so the document
capture-phase shortcut handler's preventDefault() (which does not stop
xterm) left Ctrl+K/Alt+1/Alt+B ALSO writing their raw byte/escape
sequence into Pane B's live PTY on top of whatever the app action did
to Pane A. Pane B now installs the same registry-aware gates the
primary pane's own attachCustomKeyEventHandler uses. Ctrl+V is left on
xterm's default paste — no image-paste trap to route it to.

Plus the rest of the review's smaller items:
- Narrowing the window past the desktop gate now closes an open split
  instead of leaving it stranded on screen.
- Split is refused while a web tab is active (activeWebviewId), which
  used to open Pane B's socket behind a hidden container.
- Pane B now handles the server's `{t:'r'}` refresh frame via a shared
  _loadBuffer() helper (also used by connect()), instead of ignoring it.
- The divider drag now uses pointer events + setPointerCapture (mirrors
  tab-rail-resize.js), a button!==0 guard, preventDefault, and a
  body.split-pane-resizing cursor/selection lock — a plain mousedown
  drag selected the text under the cursor as it crossed both terminals.
- Pane B's close control and the picker rows are real <button>s now
  (keyboard-reachable), with matching CSS chrome resets.
- Dropped the redundant CodemanBase.base prefix on the buffer fetch
  (the global fetch wrapper already applies it).
- data-preview-order for the Split settings chip moved from a collision
  with Ultracode Agents (both 15/12) to 11.5, matching its real
  position between Multi-monitor and Ultracode Agents in the header;
  widened test/app-settings-structure.test.ts's regex to allow the
  decimal (Number() already parses it fine for the preview sort).
- Added zh-CN i18n entries for the Split button and empty-picker text.
- Dropped the stray unused `vi` import Ark0N flagged as unrelated to
  this feature (vitest's `globals: true` makes it ambient anyway).
- Documented the fix and the deliberate no-cid/seq choice in the
  split-pane-sessions architecture-invariants entry.

Added a real-Chromium regression test asserting Ctrl+K/Alt+1/Alt+B
dispatched at Pane B's own textarea send no `{t:'i'}` frame over its
WebSocket. Full CI gate green (409 files, 7736 tests) plus all 8
split-pane browser tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
timkjr
2026-09-20 13:10:33 -05:00
co-authored by Claude Sonnet 5
parent 3152ec801d
commit fafef0aa00
7 changed files with 201 additions and 28 deletions
+22
View File
@@ -675,6 +675,12 @@ body.tab-rail-resizing * {
user-select: none !important;
}
body.split-pane-resizing,
body.split-pane-resizing * {
cursor: col-resize !important;
user-select: none !important;
}
@media (prefers-reduced-motion: reduce) {
.tab-rail,
.tab-rail-resize-handle {
@@ -18662,6 +18668,12 @@ html[data-session-list="sidebar"][data-sidebar="collapsed"] .btn-sidebar-toggle
}
.terminal-pane-b-close {
/* A native <button> now backs this (keyboard-reachable close), so reset its
default chrome back to the plain glyph this rule always drew. */
border: none;
background: none;
font: inherit;
color: inherit;
cursor: pointer;
padding: 0 6px;
opacity: 0.7;
@@ -18697,6 +18709,16 @@ html[data-session-list="sidebar"][data-sidebar="collapsed"] .btn-sidebar-toggle
}
.split-picker-item {
/* A native <button> now backs each row (keyboard-reachable picker), so
reset its default chrome back to the plain list-row look this always
drew — full-width, left-aligned, no border/background of its own. */
display: block;
width: 100%;
text-align: left;
border: none;
background: none;
font: inherit;
color: inherit;
padding: 8px 10px;
border-radius: 6px;
cursor: pointer;