fix: 在终端容器捕获Escape按键

- 在xterm容器捕获阶段转发Escape控制字符
- 阻止Radix与xterm继续重复处理同一事件
This commit is contained in:
Logan.Li committed 2026-07-26 19:09:18 +08:00
1 parent 57e51ba1cd
commit 82d1b8de10
1 file changed
+12 -6
@@ -132,12 +132,6 @@ export function TerminalDialog({
const ws = new WebSocket(wsUrl); const ws = new WebSocket(wsUrl);
wsRef.current = ws; wsRef.current = ws;
// xterm 在目标元素阶段直接转发 Escape,避免 Radix 捕获层吞掉 Vim 控制字符。 // Logan.Li
term.attachCustomKeyEventHandler((event) => {
if (event.key !== "Escape") return true;
if (event.type === "keydown") sendTerminalInput("\x1b");
return false;
});
term.onData(sendTerminalInput); term.onData(sendTerminalInput);
ws.onmessage = (event) => { ws.onmessage = (event) => {
@@ -189,6 +183,7 @@ export function TerminalDialog({
if (!open || !authReady) return; if (!open || !authReady) return;
let cleanup: (() => void) | undefined; let cleanup: (() => void) | undefined;
let detachEscape: (() => void) | undefined;
let fitFrame = 0; let fitFrame = 0;
let retry = 0; let retry = 0;
@@ -201,6 +196,16 @@ export function TerminalDialog({
if (retry++ < 30) requestAnimationFrame(attach); if (retry++ < 30) requestAnimationFrame(attach);
return; return;
} }
// 在 xterm 目标元素之前截获 Escape,直接发送给远端并阻止 Radix/xterm 重复处理。 // Logan.Li
const forwardEscape = (event: KeyboardEvent) => {
if (event.key !== "Escape") return;
event.preventDefault();
event.stopPropagation();
sendTerminalInput("\x1b");
};
container.addEventListener("keydown", forwardEscape, true);
detachEscape = () =>
container.removeEventListener("keydown", forwardEscape, true);
cleanup = attachTerminalResize(container, fit, term, ws); cleanup = attachTerminalResize(container, fit, term, ws);
const applyFit = () => { const applyFit = () => {
try { try {
@@ -217,6 +222,7 @@ export function TerminalDialog({
attach(); attach();
return () => { return () => {
if (fitFrame) cancelAnimationFrame(fitFrame); if (fitFrame) cancelAnimationFrame(fitFrame);
detachEscape?.();
cleanup?.(); cleanup?.();
}; };
}, [open, authReady, fullscreen]); }, [open, authReady, fullscreen]);