Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/browser/contextkeys.ts
5221 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../base/common/lifecycle.js';
7
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
8
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
9
import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsAgentSessionsWorkspaceContext, WorkbenchModeContext } from '../common/contextkeys.js';
10
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
11
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
12
import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
13
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
14
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
15
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
16
import { getVirtualWorkspaceScheme } from '../../platform/workspace/common/virtualWorkspace.js';
17
import { IWorkingCopyService } from '../services/workingCopy/common/workingCopyService.js';
18
import { isNative } from '../../base/common/platform.js';
19
import { IPaneCompositePartService } from '../services/panecomposite/browser/panecomposite.js';
20
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
21
import { IProductService } from '../../platform/product/common/productService.js';
22
import { getTitleBarStyle } from '../../platform/window/common/window.js';
23
import { mainWindow } from '../../base/browser/window.js';
24
import { isFullscreen, onDidChangeFullscreen } from '../../base/browser/browser.js';
25
import { IEditorService } from '../services/editor/common/editorService.js';
26
import { IWorkbenchModeService } from '../services/layout/common/workbenchModeService.js';
27
28
export class WorkbenchContextKeysHandler extends Disposable {
29
30
private dirtyWorkingCopiesContext: IContextKey<boolean>;
31
32
private activeEditorGroupEmpty: IContextKey<boolean>;
33
private activeEditorGroupIndex: IContextKey<number>;
34
private activeEditorGroupLast: IContextKey<boolean>;
35
private activeEditorGroupLocked: IContextKey<boolean>;
36
private multipleEditorGroupsContext: IContextKey<boolean>;
37
38
private editorsVisibleContext: IContextKey<boolean>;
39
40
private splitEditorsVerticallyContext: IContextKey<boolean>;
41
42
private workbenchStateContext: IContextKey<string>;
43
private workspaceFolderCountContext: IContextKey<number>;
44
45
private openFolderWorkspaceSupportContext: IContextKey<boolean>;
46
private enterMultiRootWorkspaceSupportContext: IContextKey<boolean>;
47
private emptyWorkspaceSupportContext: IContextKey<boolean>;
48
49
private virtualWorkspaceContext: IContextKey<string>;
50
private temporaryWorkspaceContext: IContextKey<boolean>;
51
private isAgentSessionsWorkspaceContext: IContextKey<boolean>;
52
private workbenchModeContext: IContextKey<string>;
53
private inAutomationContext: IContextKey<boolean>;
54
55
private inZenModeContext: IContextKey<boolean>;
56
private isMainWindowFullscreenContext: IContextKey<boolean>;
57
private isAuxiliaryWindowFocusedContext: IContextKey<boolean>;
58
private isMainEditorCenteredLayoutContext: IContextKey<boolean>;
59
private sideBarVisibleContext: IContextKey<boolean>;
60
private mainEditorAreaVisibleContext: IContextKey<boolean>;
61
private panelPositionContext: IContextKey<string>;
62
private panelVisibleContext: IContextKey<boolean>;
63
private panelAlignmentContext: IContextKey<string>;
64
private panelMaximizedContext: IContextKey<boolean>;
65
private auxiliaryBarVisibleContext: IContextKey<boolean>;
66
private auxiliaryBarMaximizedContext: IContextKey<boolean>;
67
private editorTabsVisibleContext: IContextKey<boolean>;
68
private titleAreaVisibleContext: IContextKey<boolean>;
69
private titleBarStyleContext: IContextKey<string>;
70
71
constructor(
72
@IContextKeyService private readonly contextKeyService: IContextKeyService,
73
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
74
@IConfigurationService private readonly configurationService: IConfigurationService,
75
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
76
@IProductService private readonly productService: IProductService,
77
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
78
@IEditorService private readonly editorService: IEditorService,
79
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
80
@IPaneCompositePartService private readonly paneCompositeService: IPaneCompositePartService,
81
@IWorkingCopyService private readonly workingCopyService: IWorkingCopyService,
82
@IWorkbenchModeService private readonly workbenchModeService: IWorkbenchModeService,
83
) {
84
super();
85
86
// Platform
87
IsMacContext.bindTo(this.contextKeyService);
88
IsLinuxContext.bindTo(this.contextKeyService);
89
IsWindowsContext.bindTo(this.contextKeyService);
90
91
IsWebContext.bindTo(this.contextKeyService);
92
IsMacNativeContext.bindTo(this.contextKeyService);
93
IsIOSContext.bindTo(this.contextKeyService);
94
IsMobileContext.bindTo(this.contextKeyService);
95
96
RemoteNameContext.bindTo(this.contextKeyService).set(getRemoteName(this.environmentService.remoteAuthority) || '');
97
98
this.virtualWorkspaceContext = VirtualWorkspaceContext.bindTo(this.contextKeyService);
99
this.temporaryWorkspaceContext = TemporaryWorkspaceContext.bindTo(this.contextKeyService);
100
this.isAgentSessionsWorkspaceContext = IsAgentSessionsWorkspaceContext.bindTo(this.contextKeyService);
101
this.isAgentSessionsWorkspaceContext.set(!!this.contextService.getWorkspace().isAgentSessionsWorkspace);
102
this.workbenchModeContext = WorkbenchModeContext.bindTo(this.contextKeyService);
103
this.workbenchModeContext.set(this.workbenchModeService.workbenchMode ?? '');
104
this.updateWorkspaceContextKeys();
105
106
// Capabilities
107
HasWebFileSystemAccess.bindTo(this.contextKeyService).set(WebFileSystemAccess.supported(mainWindow));
108
109
// Development
110
const isDevelopment = !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment;
111
IsDevelopmentContext.bindTo(this.contextKeyService).set(isDevelopment);
112
setConstantContextKey(IsDevelopmentContext.key, isDevelopment);
113
114
// Product Service
115
ProductQualityContext.bindTo(this.contextKeyService).set(this.productService.quality || '');
116
EmbedderIdentifierContext.bindTo(this.contextKeyService).set(productService.embedderIdentifier);
117
118
// Automation
119
this.inAutomationContext = InAutomationContext.bindTo(this.contextKeyService);
120
this.inAutomationContext.set(!!this.environmentService.enableSmokeTestDriver);
121
122
// Editor Groups
123
this.activeEditorGroupEmpty = ActiveEditorGroupEmptyContext.bindTo(this.contextKeyService);
124
this.activeEditorGroupIndex = ActiveEditorGroupIndexContext.bindTo(this.contextKeyService);
125
this.activeEditorGroupLast = ActiveEditorGroupLastContext.bindTo(this.contextKeyService);
126
this.activeEditorGroupLocked = ActiveEditorGroupLockedContext.bindTo(this.contextKeyService);
127
this.multipleEditorGroupsContext = MultipleEditorGroupsContext.bindTo(this.contextKeyService);
128
129
// Editors
130
this.editorsVisibleContext = EditorsVisibleContext.bindTo(this.contextKeyService);
131
132
// Working Copies
133
this.dirtyWorkingCopiesContext = DirtyWorkingCopiesContext.bindTo(this.contextKeyService);
134
this.dirtyWorkingCopiesContext.set(this.workingCopyService.hasDirty);
135
136
// Workbench State
137
this.workbenchStateContext = WorkbenchStateContext.bindTo(this.contextKeyService);
138
this.updateWorkbenchStateContextKey();
139
140
// Workspace Folder Count
141
this.workspaceFolderCountContext = WorkspaceFolderCountContext.bindTo(this.contextKeyService);
142
this.updateWorkspaceFolderCountContextKey();
143
144
// Opening folder support: support for opening a folder workspace
145
// (e.g. "Open Folder...") is limited in web when not connected
146
// to a remote.
147
this.openFolderWorkspaceSupportContext = OpenFolderWorkspaceSupportContext.bindTo(this.contextKeyService);
148
this.openFolderWorkspaceSupportContext.set(isNative || typeof this.environmentService.remoteAuthority === 'string');
149
150
// Empty workspace support: empty workspaces require built-in file system
151
// providers to be available that allow to enter a workspace or open loose
152
// files. This condition is met:
153
// - desktop: always
154
// - web: only when connected to a remote
155
this.emptyWorkspaceSupportContext = EmptyWorkspaceSupportContext.bindTo(this.contextKeyService);
156
this.emptyWorkspaceSupportContext.set(isNative || typeof this.environmentService.remoteAuthority === 'string');
157
158
// Entering a multi root workspace support: support for entering a multi-root
159
// workspace (e.g. "Open Workspace from File...", "Duplicate Workspace", "Save Workspace")
160
// is driven by the ability to resolve a workspace configuration file (*.code-workspace)
161
// with a built-in file system provider.
162
// This condition is met:
163
// - desktop: always
164
// - web: only when connected to a remote
165
this.enterMultiRootWorkspaceSupportContext = EnterMultiRootWorkspaceSupportContext.bindTo(this.contextKeyService);
166
this.enterMultiRootWorkspaceSupportContext.set(isNative || typeof this.environmentService.remoteAuthority === 'string');
167
168
// Editor Layout
169
this.splitEditorsVerticallyContext = SplitEditorsVertically.bindTo(this.contextKeyService);
170
this.updateSplitEditorsVerticallyContext();
171
172
// Window
173
this.isMainWindowFullscreenContext = IsMainWindowFullscreenContext.bindTo(this.contextKeyService);
174
this.isAuxiliaryWindowFocusedContext = IsAuxiliaryWindowFocusedContext.bindTo(this.contextKeyService);
175
176
// Zen Mode
177
this.inZenModeContext = InEditorZenModeContext.bindTo(this.contextKeyService);
178
179
// Centered Layout (Main Editor)
180
this.isMainEditorCenteredLayoutContext = IsMainEditorCenteredLayoutContext.bindTo(this.contextKeyService);
181
182
// Editor Area
183
this.mainEditorAreaVisibleContext = MainEditorAreaVisibleContext.bindTo(this.contextKeyService);
184
this.editorTabsVisibleContext = EditorTabsVisibleContext.bindTo(this.contextKeyService);
185
186
// Sidebar
187
this.sideBarVisibleContext = SideBarVisibleContext.bindTo(this.contextKeyService);
188
189
// Title Bar
190
this.titleAreaVisibleContext = TitleBarVisibleContext.bindTo(this.contextKeyService);
191
this.titleBarStyleContext = TitleBarStyleContext.bindTo(this.contextKeyService);
192
this.updateTitleBarContextKeys();
193
194
// Panel
195
this.panelPositionContext = PanelPositionContext.bindTo(this.contextKeyService);
196
this.panelPositionContext.set(positionToString(this.layoutService.getPanelPosition()));
197
this.panelVisibleContext = PanelVisibleContext.bindTo(this.contextKeyService);
198
this.panelVisibleContext.set(this.layoutService.isVisible(Parts.PANEL_PART));
199
this.panelMaximizedContext = PanelMaximizedContext.bindTo(this.contextKeyService);
200
this.panelMaximizedContext.set(this.layoutService.isPanelMaximized());
201
this.panelAlignmentContext = PanelAlignmentContext.bindTo(this.contextKeyService);
202
this.panelAlignmentContext.set(this.layoutService.getPanelAlignment());
203
204
// Auxiliary Bar
205
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
206
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
207
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
208
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
209
210
this.registerListeners();
211
}
212
213
private registerListeners(): void {
214
this.editorGroupService.whenReady.then(() => {
215
this.updateEditorAreaContextKeys();
216
this.updateActiveEditorGroupContextKeys();
217
this.updateVisiblePanesContextKeys();
218
});
219
220
this._register(this.editorService.onDidActiveEditorChange(() => this.updateActiveEditorGroupContextKeys()));
221
this._register(this.editorService.onDidVisibleEditorsChange(() => this.updateVisiblePanesContextKeys()));
222
this._register(this.editorGroupService.onDidAddGroup(() => this.updateEditorGroupsContextKeys()));
223
this._register(this.editorGroupService.onDidRemoveGroup(() => this.updateEditorGroupsContextKeys()));
224
this._register(this.editorGroupService.onDidChangeGroupIndex(() => this.updateActiveEditorGroupContextKeys()));
225
this._register(this.editorGroupService.onDidChangeGroupLocked(() => this.updateActiveEditorGroupContextKeys()));
226
227
this._register(this.editorGroupService.onDidChangeEditorPartOptions(() => this.updateEditorAreaContextKeys()));
228
229
this._register(this.contextService.onDidChangeWorkbenchState(() => this.updateWorkbenchStateContextKey()));
230
this._register(this.contextService.onDidChangeWorkspaceFolders(() => {
231
this.updateWorkspaceFolderCountContextKey();
232
this.updateWorkspaceContextKeys();
233
}));
234
235
this._register(this.workbenchModeService.onDidChangeWorkbenchMode(mode => this.workbenchModeContext.set(mode ?? '')));
236
237
this._register(this.configurationService.onDidChangeConfiguration(e => {
238
if (e.affectsConfiguration('workbench.editor.openSideBySideDirection')) {
239
this.updateSplitEditorsVerticallyContext();
240
}
241
}));
242
243
this._register(this.layoutService.onDidChangeZenMode(enabled => this.inZenModeContext.set(enabled)));
244
this._register(this.layoutService.onDidChangeActiveContainer(() => this.isAuxiliaryWindowFocusedContext.set(this.layoutService.activeContainer !== this.layoutService.mainContainer)));
245
this._register(onDidChangeFullscreen(windowId => {
246
if (windowId === mainWindow.vscodeWindowId) {
247
this.isMainWindowFullscreenContext.set(isFullscreen(mainWindow));
248
}
249
}));
250
this._register(this.layoutService.onDidChangeMainEditorCenteredLayout(centered => this.isMainEditorCenteredLayoutContext.set(centered)));
251
this._register(this.layoutService.onDidChangePanelPosition(position => this.panelPositionContext.set(position)));
252
253
this._register(this.layoutService.onDidChangePanelAlignment(alignment => this.panelAlignmentContext.set(alignment)));
254
255
this._register(this.paneCompositeService.onDidPaneCompositeClose(() => this.updateSideBarContextKeys()));
256
this._register(this.paneCompositeService.onDidPaneCompositeOpen(() => this.updateSideBarContextKeys()));
257
258
this._register(this.layoutService.onDidChangePartVisibility(() => {
259
this.mainEditorAreaVisibleContext.set(this.layoutService.isVisible(Parts.EDITOR_PART, mainWindow));
260
this.panelVisibleContext.set(this.layoutService.isVisible(Parts.PANEL_PART));
261
this.panelMaximizedContext.set(this.layoutService.isPanelMaximized());
262
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
263
264
this.updateTitleBarContextKeys();
265
}));
266
267
this._register(this.layoutService.onDidChangeAuxiliaryBarMaximized(() => {
268
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
269
}));
270
271
this._register(this.workingCopyService.onDidChangeDirty(workingCopy => this.dirtyWorkingCopiesContext.set(workingCopy.isDirty() || this.workingCopyService.hasDirty)));
272
}
273
274
private updateVisiblePanesContextKeys(): void {
275
const visibleEditorPanes = this.editorService.visibleEditorPanes;
276
if (visibleEditorPanes.length > 0) {
277
this.editorsVisibleContext.set(true);
278
} else {
279
this.editorsVisibleContext.reset();
280
}
281
}
282
283
// Context keys depending on the state of the editor group itself
284
private updateActiveEditorGroupContextKeys(): void {
285
if (!this.editorService.activeEditor) {
286
this.activeEditorGroupEmpty.set(true);
287
} else {
288
this.activeEditorGroupEmpty.reset();
289
}
290
291
const activeGroup = this.editorGroupService.activeGroup;
292
this.activeEditorGroupIndex.set(activeGroup.index + 1); // not zero-indexed
293
this.activeEditorGroupLocked.set(activeGroup.isLocked);
294
295
this.updateEditorGroupsContextKeys();
296
}
297
298
// Context keys depending on the state of other editor groups
299
private updateEditorGroupsContextKeys(): void {
300
const groupCount = this.editorGroupService.count;
301
if (groupCount > 1) {
302
this.multipleEditorGroupsContext.set(true);
303
} else {
304
this.multipleEditorGroupsContext.reset();
305
}
306
307
const activeGroup = this.editorGroupService.activeGroup;
308
this.activeEditorGroupLast.set(activeGroup.index === groupCount - 1);
309
}
310
311
private updateEditorAreaContextKeys(): void {
312
this.editorTabsVisibleContext.set(this.editorGroupService.partOptions.showTabs === 'multiple');
313
}
314
315
private updateWorkbenchStateContextKey(): void {
316
this.workbenchStateContext.set(this.getWorkbenchStateString());
317
}
318
319
private updateWorkspaceFolderCountContextKey(): void {
320
this.workspaceFolderCountContext.set(this.contextService.getWorkspace().folders.length);
321
}
322
323
private updateSplitEditorsVerticallyContext(): void {
324
const direction = preferredSideBySideGroupDirection(this.configurationService);
325
this.splitEditorsVerticallyContext.set(direction === GroupDirection.DOWN);
326
}
327
328
private getWorkbenchStateString(): string {
329
switch (this.contextService.getWorkbenchState()) {
330
case WorkbenchState.EMPTY: return 'empty';
331
case WorkbenchState.FOLDER: return 'folder';
332
case WorkbenchState.WORKSPACE: return 'workspace';
333
}
334
}
335
336
private updateSideBarContextKeys(): void {
337
this.sideBarVisibleContext.set(this.layoutService.isVisible(Parts.SIDEBAR_PART));
338
}
339
340
private updateTitleBarContextKeys(): void {
341
this.titleAreaVisibleContext.set(this.layoutService.isVisible(Parts.TITLEBAR_PART, mainWindow));
342
this.titleBarStyleContext.set(getTitleBarStyle(this.configurationService));
343
}
344
345
private updateWorkspaceContextKeys(): void {
346
this.virtualWorkspaceContext.set(getVirtualWorkspaceScheme(this.contextService.getWorkspace()) || '');
347
this.temporaryWorkspaceContext.set(isTemporaryWorkspace(this.contextService.getWorkspace()));
348
}
349
}
350
351