Extension API: how to retrieve focused view ID during keybinding command execution?
I'm developing an extension which manages 5 views, and it needs to support keybindings for commands operating on TreeView item selections. Since there are multiple views, the extension needs to know exactly which view was focused when the keybinding was pressed, but I haven't found a reliable way to retrieve the view ID in this scenario.
The extension already has 100 commands, 56 of which are duplicates created specifically to work around this limitation (30 + 14 * 5). These are context menu commands for operations over TreeView items, with optional keybindings.
This is already becoming difficult to manage, because the duplication propagates through:
commands
commandPalette
keybindings
menus.view/item/context
submenus
I still need to add around 50 * 5 more commands, which would push the total above 350. At this point I decided to ask whether I missed a proper solution, or whether this is currently not supported by the Extension API.
Why command duplication is currently the only reliable solution
The extension manages a single TreeDataProvider, shared across 5 views (activitybar, explorer, scm, debug, test) so the same tree can be accessed from different workbench layouts if needed.
I tried several heuristics to determine the active view during keybinding execution, but none of them are reliable enough:
TreeView.onDidChangeVisibility - multiple views can be visible simultaneously, so result depends on event ordering
TreeView.onDidChangeSelection - views can be focused/switched without changing selection
Both approaches may result in executing a command against the wrong view selection, which is unsafe for destructive operations.
As a workaround, I duplicated commands, scoped each keybinding to its own view through when clauses, and subscribed them to separate handlers.
For example:
{
"key": "shift+g",
"command": "focus.arrange.group.activity",
"when": "focus.activity"
},
{
"key": "shift+g",
"command": "focus.arrange.group.explorer",
"when": "focus.explorer"
},
{
"key": "shift+g",
"command": "focus.arrange.group.scm",
"when": "focus.scm"
},
{
"key": "shift+g",
"command": "focus.arrange.group.debug",
"when": "focus.debug"
},
{
"key": "shift+g",
"command": "focus.arrange.group.test",
"when": "focus.test"
}
I also considered command arguments as a workaround, but rejected that approach because it is not user-friendly:
- arguments are not visible/manageable in Keyboard Shortcuts UI
- users would need to manually edit
keybindings.json
- extension would need additional documentation just to explain keybinding setup, including the need to create 5 bindings per key and specify the correct command and view IDs in the arguments for each one, which is not something extension users should reasonably be expected to do
So my question is: did I miss a proper way to solve this, and is there a correct way to handle this scenario?
If not, I will probably have to drop keybinding support for some commands.
Possible API improvements
Some possible additions that could solve this cleanly:
window.onDidChangeActiveView(TreeView | undefined) and window.activeView (mirroring the existing activeTextEditor API)
TreeView.onDidChangeFocus(boolean) (view-local variant of 1)
- Passing the view ID or
TreeView reference to command handlers
This is not limited to keybindings, but also affects regular tree view context menu commands. In cases where a command needs to call TreeView API methods, such as TreeView.reveal for the corresponding view, the command also needs a reliable way to determine which view invoked it. Tree items could theoretically be associated with a specific view to retrieve the corresponding TreeView reference, but this is not applicable when a single TreeDataProvider is shared across multiple views, so command duplication becomes the only reliable solution.
Another related limitation is the inability to retrieve the currently focused/highlighted tree item. For example, in Explorer view it is possible to navigate using arrow keys and then rename or delete the highlighted file using a keybinding. In extension TreeViews, only selection is exposed, but selection does not change during keyboard navigation, so it is currently not possible to retrieve the correct item for keybinding execution. Pressing Space or Enter updates the selection, but it is an extra action and also executes the assigned TreeItem.command, which may be undesired. Having access to the active/focused item would also help extensions provide more native keyboard interaction behavior.
Extension API: how to retrieve focused view ID during keybinding command execution?
I'm developing an extension which manages 5 views, and it needs to support keybindings for commands operating on
TreeViewitem selections. Since there are multiple views, the extension needs to know exactly which view was focused when the keybinding was pressed, but I haven't found a reliable way to retrieve the view ID in this scenario.The extension already has 100 commands, 56 of which are duplicates created specifically to work around this limitation (30 + 14 * 5). These are context menu commands for operations over
TreeViewitems, with optional keybindings.This is already becoming difficult to manage, because the duplication propagates through:
commandscommandPalettekeybindingsmenus.view/item/contextsubmenusI still need to add around 50 * 5 more commands, which would push the total above 350. At this point I decided to ask whether I missed a proper solution, or whether this is currently not supported by the Extension API.
Why command duplication is currently the only reliable solution
The extension manages a single
TreeDataProvider, shared across 5 views (activitybar,explorer,scm,debug,test) so the same tree can be accessed from different workbench layouts if needed.I tried several heuristics to determine the active view during keybinding execution, but none of them are reliable enough:
TreeView.onDidChangeVisibility- multiple views can be visible simultaneously, so result depends on event orderingTreeView.onDidChangeSelection- views can be focused/switched without changing selectionBoth approaches may result in executing a command against the wrong view selection, which is unsafe for destructive operations.
As a workaround, I duplicated commands, scoped each keybinding to its own view through
whenclauses, and subscribed them to separate handlers.For example:
{ "key": "shift+g", "command": "focus.arrange.group.activity", "when": "focus.activity" }, { "key": "shift+g", "command": "focus.arrange.group.explorer", "when": "focus.explorer" }, { "key": "shift+g", "command": "focus.arrange.group.scm", "when": "focus.scm" }, { "key": "shift+g", "command": "focus.arrange.group.debug", "when": "focus.debug" }, { "key": "shift+g", "command": "focus.arrange.group.test", "when": "focus.test" }I also considered command arguments as a workaround, but rejected that approach because it is not user-friendly:
keybindings.jsonSo my question is: did I miss a proper way to solve this, and is there a correct way to handle this scenario?
If not, I will probably have to drop keybinding support for some commands.
Possible API improvements
Some possible additions that could solve this cleanly:
window.onDidChangeActiveView(TreeView | undefined)andwindow.activeView(mirroring the existingactiveTextEditorAPI)TreeView.onDidChangeFocus(boolean)(view-local variant of 1)TreeViewreference to command handlersThis is not limited to keybindings, but also affects regular tree view context menu commands. In cases where a command needs to call
TreeViewAPI methods, such asTreeView.revealfor the corresponding view, the command also needs a reliable way to determine which view invoked it. Tree items could theoretically be associated with a specific view to retrieve the correspondingTreeViewreference, but this is not applicable when a singleTreeDataProvideris shared across multiple views, so command duplication becomes the only reliable solution.Another related limitation is the inability to retrieve the currently focused/highlighted tree item. For example, in Explorer view it is possible to navigate using arrow keys and then rename or delete the highlighted file using a keybinding. In extension
TreeViews, only selection is exposed, but selection does not change during keyboard navigation, so it is currently not possible to retrieve the correct item for keybinding execution. Pressing Space or Enter updates the selection, but it is an extra action and also executes the assignedTreeItem.command, which may be undesired. Having access to the active/focused item would also help extensions provide more native keyboard interaction behavior.