mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 13:39:41 +02:00
fix(mobile): apply the one-shot Ctrl on the CJK input path too
onData is not the only way keystrokes reach the PTY. With cjkInputEnabled on, the CJK textarea owns the keyboard: onData returns early for everything it swallows, and the focus router even redirects terminal.focus() into the field, which is exactly where the accessory bar sends focus after every key. So an armed modifier could neither fire NOR be spent there — it survived until a session switch or keyboard dismissal and then turned an innocent keystroke into a control byte, the failure mode the whole disarm list exists to prevent. `_handleCjkInput()` is that module's single choke point to the PTY, so applying the modifier there covers typed characters, IME flushes, Enter, backspace and arrows in one place, with the same policy as the onData hook: the next single character is modified, anything longer merely spends it. A committed CJK word therefore passes through untouched and still clears the modifier. Verified against a real shell session with the CJK field focused and owning input (cjkActive true, focus in #cjkInput). Before: typing c left a literal c in the pane, `sleep 300` kept running, and Ctrl stayed armed. After: ^C in the pane, modifier disarmed, plain typing still literal. Tests: 5 cases driving the real _handleCjkInput against the real bar, both loaded into one vm scope (the bar is a const singleton, so a shared script scope is what makes the bare reference resolve). Removing the fix fails 3 of them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2640,6 +2640,20 @@ Object.assign(CodemanApp.prototype, {
|
||||
_crashDiag.log(`CJK send DROP no-session len=${text.length}`);
|
||||
return;
|
||||
}
|
||||
// ── One-shot Ctrl (mobile shell bar, issue #262) ──
|
||||
// While the CJK field is visible it OWNS the keyboard: onData returns early
|
||||
// for everything it swallows, and the focus router even redirects
|
||||
// terminal.focus() into it — which is where the accessory bar sends focus
|
||||
// after every key. So the onData hook never sees these keystrokes, and an
|
||||
// armed modifier could neither fire NOR be spent: it survived until a
|
||||
// session switch and then turned an innocent keystroke into a control byte.
|
||||
// This is the module's single choke point to the PTY, so applying it here
|
||||
// covers typed characters, IME flushes, Enter, backspace and arrows at once.
|
||||
// Same policy as the onData hook: the next single character is modified,
|
||||
// anything longer merely spends the modifier.
|
||||
if (typeof KeyboardAccessoryBar !== 'undefined' && KeyboardAccessoryBar.isCtrlArmed?.()) {
|
||||
text = KeyboardAccessoryBar.consumeCtrl(text);
|
||||
}
|
||||
// Bypasses onData (like insertTerminalText): predictions cannot see this
|
||||
if (this._localEchoPolicy === 'predict') this._predictiveEcho?.clearPredictions();
|
||||
_crashDiag.log(`CJK send→${this.activeSessionId.slice(0, 8)} len=${text.length}`);
|
||||
|
||||
Reference in New Issue
Block a user