Skip to content

Commit 003bddb

Browse files
committed
feat: shift+escape toggles focus between editor and bottom panel
- Add Panel.focus() API (default returns false, override for focusable panels) - Add PanelView.getActiveBottomPanel() to retrieve the active panel - Terminal panel overrides focus() to focus the active terminal instance - Terminal passes Shift+Escape through to WorkspaceManager - Shift+Escape from editor focuses the active bottom panel if visible - Shift+Escape from anywhere else focuses the active editor
1 parent cddac19 commit 003bddb

4 files changed

Lines changed: 71 additions & 7 deletions

File tree

src/extensionsIntegrated/Terminal/TerminalInstance.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ define(function (require, exports, module) {
247247

248248
const ctrlOrMeta = event.ctrlKey || event.metaKey;
249249

250+
// Shift+Escape should focus the active editor
251+
if (event.shiftKey && event.key === "Escape") {
252+
return false;
253+
}
254+
250255
// Ctrl+C with a selection should copy to clipboard, not send SIGINT
251256
if (ctrlOrMeta && !event.shiftKey && event.key.toLowerCase() === "c" && this.terminal.hasSelection()) {
252257
return false;

src/extensionsIntegrated/Terminal/main.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ define(function (require, exports, module) {
106106
$panel = $(Mustache.render(panelHTML, templateVars));
107107
panel = WorkspaceManager.createBottomPanel(PANEL_ID, $panel, PANEL_MIN_SIZE);
108108

109+
// Override focus() so Shift+Escape can transfer focus to the terminal
110+
panel.focus = function () {
111+
const active = _getActiveTerminal();
112+
if (active) {
113+
active.focus();
114+
return true;
115+
}
116+
return false;
117+
};
118+
109119
// Cache DOM references
110120
$contentArea = $panel.find(".terminal-content-area");
111121
$shellDropdown = $panel.find(".terminal-shell-dropdown");

src/view/PanelView.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,15 @@ define(function (require, exports, module) {
412412
}
413413
};
414414

415+
/**
416+
* Attempts to focus the panel. Override this in panels that support focus
417+
* (e.g. terminal). The default implementation returns false.
418+
* @return {boolean} true if the panel accepted focus, false otherwise
419+
*/
420+
Panel.prototype.focus = function () {
421+
return false;
422+
};
423+
415424
/**
416425
* Sets the panel's visibility state
417426
* @param {boolean} visible true to show, false to hide
@@ -765,6 +774,17 @@ define(function (require, exports, module) {
765774
return closedIds;
766775
}
767776

777+
/**
778+
* Returns the currently active (visible) bottom panel, or null if none.
779+
* @return {Panel|null}
780+
*/
781+
function getActiveBottomPanel() {
782+
if (_activeId && _panelMap[_activeId]) {
783+
return _panelMap[_activeId];
784+
}
785+
return null;
786+
}
787+
768788
/**
769789
* Cycle to the next open bottom panel tab. If the container is hidden
770790
* or no panels are open, does nothing and returns false.
@@ -789,6 +809,7 @@ define(function (require, exports, module) {
789809
exports.Panel = Panel;
790810
exports.init = init;
791811
exports.getOpenBottomPanelIDs = getOpenBottomPanelIDs;
812+
exports.getActiveBottomPanel = getActiveBottomPanel;
792813
exports.showNextPanel = showNextPanel;
793814
exports.hideAllOpenPanels = hideAllOpenPanels;
794815
exports.exitMaximizeOnResize = exitMaximizeOnResize;

src/view/WorkspaceManager.js

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ define(function (require, exports, module) {
4545
PluginPanelView = require("view/PluginPanelView"),
4646
PanelView = require("view/PanelView"),
4747
EditorManager = require("editor/EditorManager"),
48+
MainViewManager = require("view/MainViewManager"),
4849
KeyEvent = require("utils/KeyEvent");
4950

5051
/**
@@ -647,12 +648,44 @@ define(function (require, exports, module) {
647648
return _togglePanels();
648649
}
649650

650-
// pressing escape when focused on editor will hide the bottom panel container
651+
/**
652+
* Shift+Escape: toggle focus between editor and active bottom panel
653+
* @param event
654+
* @returns {boolean}
655+
* @private
656+
*/
657+
function _handleShiftEscape(event) {
658+
if (!event.shiftKey) {
659+
return false;
660+
}
661+
if (EditorManager.getFocusedEditor()) {
662+
// Editor has focus — focus the panel
663+
const activePanel = PanelView.getActiveBottomPanel();
664+
if(!activePanel || !activePanel.isVisible()){
665+
_togglePanels();
666+
}
667+
activePanel.focus();
668+
} else {
669+
// Focus is elsewhere (panel, sidebar, etc.) — focus the editor
670+
MainViewManager.focusActivePane();
671+
}
672+
event.stopPropagation();
673+
event.preventDefault();
674+
return true;
675+
}
676+
677+
// pressing escape when focused on editor will toggle the bottom panel container
678+
// pressing shift+escape toggles focus between editor and active bottom panel
651679
function _handleKeydown(event) {
652680
if(event.keyCode !== KeyEvent.DOM_VK_ESCAPE || KeyBindingManager.isInOverlayMode()){
653681
return;
654682
}
655683

684+
// Shift+Escape: toggle focus between editor and active bottom panel
685+
if (_handleShiftEscape(event)) {
686+
return;
687+
}
688+
656689
for(let consumerName of Object.keys(_escapeKeyConsumers)){
657690
if(_escapeKeyConsumers[consumerName](event)){
658691
return;
@@ -671,12 +704,7 @@ define(function (require, exports, module) {
671704
return;
672705
}
673706

674-
if (event.shiftKey) {
675-
// Shift+Escape: cycle through open bottom panels
676-
PanelView.showNextPanel();
677-
} else {
678-
_handleEscapeKey();
679-
}
707+
_handleEscapeKey();
680708

681709
event.stopPropagation();
682710
event.preventDefault();

0 commit comments

Comments
 (0)