fix: intercept Ctrl+B and app shortcuts in capture phase when terminal is focused
This commit is contained in:
+17
-3
@@ -217,17 +217,21 @@ class TerminalApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initKeyboardShortcuts() {
|
initKeyboardShortcuts() {
|
||||||
window.addEventListener('keydown', (e) => {
|
window.addEventListener(
|
||||||
|
'keydown',
|
||||||
|
(e) => {
|
||||||
// Ctrl+Shift+P 或 F1: 命令面板
|
// Ctrl+Shift+P 或 F1: 命令面板
|
||||||
if ((e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'p') || e.key === 'F1') {
|
if ((e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'p') || e.key === 'F1') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
this.commandPalette.toggle();
|
this.commandPalette.toggle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl+B: 切换左侧工作区侧边栏
|
// Ctrl+B: 切换左侧工作区侧边栏
|
||||||
if (e.ctrlKey && e.key.toLowerCase() === 'b') {
|
if (e.ctrlKey && !e.shiftKey && !e.altKey && e.key.toLowerCase() === 'b') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
this.workspaceManager?.toggleSidebar();
|
this.workspaceManager?.toggleSidebar();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -235,6 +239,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Shift+T: 新建当前工作区标签页
|
// Ctrl+Shift+T: 新建当前工作区标签页
|
||||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 't') {
|
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 't') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
const activeWs = this.workspaceManager ? this.workspaceManager.getActiveWorkspace() : null;
|
const activeWs = this.workspaceManager ? this.workspaceManager.getActiveWorkspace() : null;
|
||||||
const spawnOpts = this.workspaceManager ? this.workspaceManager.getSpawnOptions(activeWs?.id) : {};
|
const spawnOpts = this.workspaceManager ? this.workspaceManager.getSpawnOptions(activeWs?.id) : {};
|
||||||
this.tabManager.createTab({
|
this.tabManager.createTab({
|
||||||
@@ -250,6 +255,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Shift+W: 关闭窗格
|
// Ctrl+Shift+W: 关闭窗格
|
||||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'w') {
|
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'w') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
const tab = this.tabManager.getActiveTab();
|
const tab = this.tabManager.getActiveTab();
|
||||||
if (tab && tab.splitTree.activeTerminal) {
|
if (tab && tab.splitTree.activeTerminal) {
|
||||||
tab.splitTree.closeTerminal(tab.splitTree.activeTerminal.id);
|
tab.splitTree.closeTerminal(tab.splitTree.activeTerminal.id);
|
||||||
@@ -260,6 +266,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Shift+E: 水平分屏 (左右)
|
// Ctrl+Shift+E: 水平分屏 (左右)
|
||||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'e') {
|
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'e') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
const tab = this.tabManager.getActiveTab();
|
const tab = this.tabManager.getActiveTab();
|
||||||
if (tab) tab.splitTree.splitCurrent('horizontal');
|
if (tab) tab.splitTree.splitCurrent('horizontal');
|
||||||
return;
|
return;
|
||||||
@@ -268,6 +275,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Shift+O: 垂直分屏 (上下)
|
// Ctrl+Shift+O: 垂直分屏 (上下)
|
||||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'o') {
|
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'o') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
const tab = this.tabManager.getActiveTab();
|
const tab = this.tabManager.getActiveTab();
|
||||||
if (tab) tab.splitTree.splitCurrent('vertical');
|
if (tab) tab.splitTree.splitCurrent('vertical');
|
||||||
return;
|
return;
|
||||||
@@ -276,6 +284,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Shift+F: 搜索
|
// Ctrl+Shift+F: 搜索
|
||||||
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {
|
if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() === 'f') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
this.toggleSearch();
|
this.toggleSearch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -283,6 +292,7 @@ class TerminalApp {
|
|||||||
// Ctrl+,: 设置
|
// Ctrl+,: 设置
|
||||||
if (e.ctrlKey && e.key === ',') {
|
if (e.ctrlKey && e.key === ',') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
this.settings.open();
|
this.settings.open();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -290,6 +300,7 @@ class TerminalApp {
|
|||||||
// Ctrl+Tab / Ctrl+Shift+Tab: 标签页切换
|
// Ctrl+Tab / Ctrl+Shift+Tab: 标签页切换
|
||||||
if (e.ctrlKey && e.key === 'Tab') {
|
if (e.ctrlKey && e.key === 'Tab') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
this.tabManager.prevTab();
|
this.tabManager.prevTab();
|
||||||
} else {
|
} else {
|
||||||
@@ -301,13 +312,16 @@ class TerminalApp {
|
|||||||
// Alt+1 .. Alt+9: 快速直达标签页
|
// Alt+1 .. Alt+9: 快速直达标签页
|
||||||
if (e.altKey && e.key >= '1' && e.key <= '9') {
|
if (e.altKey && e.key >= '1' && e.key <= '9') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
const index = parseInt(e.key, 10) - 1;
|
const index = parseInt(e.key, 10) - 1;
|
||||||
const ids = Array.from(this.tabManager.tabs.keys());
|
const ids = Array.from(this.tabManager.tabs.keys());
|
||||||
if (ids[index]) {
|
if (ids[index]) {
|
||||||
this.tabManager.switchTab(ids[index]);
|
this.tabManager.switchTab(ids[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
true // 启用捕获阶段,确保终端即使在聚焦/输入状态下应用级快捷键也能被优先拦截响应
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async initStatusBar() {
|
async initStatusBar() {
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ export class TerminalView {
|
|||||||
console.warn('WebGL addon not supported, fallback to default Canvas renderer:', e);
|
console.warn('WebGL addon not supported, fallback to default Canvas renderer:', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自定义按键过滤:允许应用级全局快捷键(如 Ctrl+B 切换侧边栏)穿透
|
||||||
|
this.xterm.attachCustomKeyEventHandler((event) => {
|
||||||
|
if (event.ctrlKey && !event.shiftKey && !event.altKey && event.key.toLowerCase() === 'b') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
// 监听输入
|
// 监听输入
|
||||||
this.xterm.onData((data) => {
|
this.xterm.onData((data) => {
|
||||||
window.terminalAPI.writePty(this.id, data);
|
window.terminalAPI.writePty(this.id, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user