From 432dd285cf5a42ba8998d44d05f1af8a48a3f326 Mon Sep 17 00:00:00 2001 From: ChrisLi Date: Fri, 8 May 2026 12:06:46 +0800 Subject: [PATCH 1/2] feat: cycle tabs with Ctrl+PageUp / Ctrl+PageDown Mirror the existing Shift+ArrowUp/Down handler so the more conventional Ctrl+PageUp/PageDown also switches tabs. Same guards: capture phase, skipped in passthrough mode and when focus is in a real text input. Co-Authored-By: Claude Opus 4.7 --- src/App.tsx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 6680c17..d55f58c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -119,17 +119,23 @@ export default function App() { window.addEventListener("beforeunload", () => flushPersistedState()); - // Shift+ArrowUp / Shift+ArrowDown: cycle tabs. Registered in the capture - // phase so it fires before xterm's textarea handler — otherwise xterm - // swallows the event (translates it to a PTY escape sequence) and the tab - // bar only responds after the user clicks the sidebar to move focus. - // Skipped when focus is in a real text input / passthrough mode so the key - // can still extend selection / be forwarded to the remote agent. + // Shift+ArrowUp/Down and Ctrl+PageUp/PageDown: cycle tabs. Registered in + // the capture phase so it fires before xterm's textarea handler — + // otherwise xterm swallows the event (translates it to a PTY escape + // sequence) and the tab bar only responds after the user clicks the + // sidebar to move focus. Skipped when focus is in a real text input / + // passthrough mode so the key can still extend selection / be forwarded + // to the remote agent. window.addEventListener( "keydown", (e) => { - if (!e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) return; - if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return; + const shiftCombo = + e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && + (e.key === "ArrowUp" || e.key === "ArrowDown"); + const ctrlCombo = + e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey && + (e.key === "PageUp" || e.key === "PageDown"); + if (!shiftCombo && !ctrlCombo) return; if (isActiveTabPassthrough()) return; // xterm's own input is a hidden