diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index f618a8669c2..1da994a9d6d 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -460,7 +460,7 @@ export class CommandCenter { @command('git.clone') async clone(url?: string, parentPath?: string): Promise { - if (!url) { + if (!url || typeof url !== 'string') { url = await pickRemoteSource(this.model, { providerLabel: provider => localize('clonefrom', "Clone from {0}", provider.name), urlLabel: localize('repourl', "Clone from URL") diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 2cd9d04f791..420715ff1fe 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -336,7 +336,18 @@ export class CodeWindow extends Disposable implements ICodeWindow { return !!this.documentEdited; } - focus(): void { + focus(options?: { force: boolean }): void { + // macOS: Electron >6.x changed its behaviour to not + // bring the application to the foreground when a window + // is focused programmatically. Only via `app.focus` and + // the option `steal: true` can you get the previous + // behaviour back. The only reason to use this option is + // when a window is getting focused while the application + // is not in the foreground. + if (isMacintosh && options?.force) { + app.focus({ steal: true }); + } + if (!this._win) { return; } @@ -719,7 +730,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.showTimeoutHandle = setTimeout(() => { if (this._win && !this._win.isVisible() && !this._win.isMinimized()) { this._win.show(); - this._win.focus(); + this.focus({ force: true }); this._win.webContents.openDevTools(); } }, 10000); diff --git a/src/vs/platform/electron/common/electron.ts b/src/vs/platform/electron/common/electron.ts index 759bcd96ab3..1061d20d16f 100644 --- a/src/vs/platform/electron/common/electron.ts +++ b/src/vs/platform/electron/common/electron.ts @@ -44,7 +44,15 @@ export interface ICommonElectronService { unmaximizeWindow(): Promise; minimizeWindow(): Promise; - focusWindow(options?: { windowId?: number }): Promise; + /** + * Make the window focused. + * + * @param options Pass `force: true` if you want to make the window take + * focus even if the application does not have focus currently. This option + * should only be used if it is necessary to steal focus from the current + * focused application which may not be VSCode. + */ + focusWindow(options?: { windowId?: number, force?: boolean }): Promise; // Dialogs showMessageBox(options: MessageBoxOptions): Promise; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index 0c2f9a735ca..91693f0be75 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -172,14 +172,14 @@ export class ElectronMainService implements IElectronMainService { } } - async focusWindow(windowId: number | undefined, options?: { windowId?: number; }): Promise { + async focusWindow(windowId: number | undefined, options?: { windowId?: number; force?: boolean; }): Promise { if (options && typeof options.windowId === 'number') { windowId = options.windowId; } const window = this.windowById(windowId); if (window) { - window.focus(); + window.focus({ force: options?.force ?? false }); } } diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index ead6b3a943a..5903407c087 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -452,7 +452,6 @@ abstract class ResourceNavigator extends Disposable { super(); this.openOnFocus = options?.openOnFocus ?? false; - this.openOnSingleClick = options?.openOnSingleClick ?? true; this._register(Event.filter(this.widget.onDidChangeSelection, e => e.browserEvent instanceof KeyboardEvent)(e => this.onSelectionFromKeyboard(e))); this._register(this.widget.onPointer((e: { browserEvent: MouseEvent }) => this.onPointer(e.browserEvent))); @@ -463,9 +462,12 @@ abstract class ResourceNavigator extends Disposable { } if (typeof options?.openOnSingleClick !== 'boolean' && options?.configurationService) { + this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick'; this._register(options?.configurationService.onDidChangeConfiguration(() => { this.openOnSingleClick = options?.configurationService!.getValue(openModeSettingKey) !== 'doubleClick'; })); + } else { + this.openOnSingleClick = options?.openOnSingleClick ?? true; } } @@ -493,15 +495,19 @@ abstract class ResourceNavigator extends Disposable { } private onPointer(browserEvent: MouseEvent): void { + if (!this.openOnSingleClick) { + return; + } + const isDoubleClick = browserEvent.detail === 2; - if (!this.openOnSingleClick && !isDoubleClick) { + if (isDoubleClick) { return; } const isMiddleClick = browserEvent.button === 1; - const preserveFocus = !isDoubleClick; - const pinned = isDoubleClick || isMiddleClick; + const preserveFocus = true; + const pinned = isMiddleClick; const sideBySide = browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey; this._open(preserveFocus, pinned, sideBySide, browserEvent); diff --git a/src/vs/platform/windows/electron-main/windows.ts b/src/vs/platform/windows/electron-main/windows.ts index bf481595ade..e73561154ab 100644 --- a/src/vs/platform/windows/electron-main/windows.ts +++ b/src/vs/platform/windows/electron-main/windows.ts @@ -61,7 +61,7 @@ export interface ICodeWindow extends IDisposable { load(config: INativeWindowConfiguration, isReload?: boolean): void; reload(configuration?: INativeWindowConfiguration, cli?: ParsedArgs): void; - focus(): void; + focus(options?: { force: boolean }): void; close(): void; getBounds(): Rectangle; diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 1aec9526b10..9181bf457f4 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -167,9 +167,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic private readonly _onWindowReady = this._register(new Emitter()); readonly onWindowReady = this._onWindowReady.event; - private readonly _onWindowClose = this._register(new Emitter()); - readonly onWindowClose = this._onWindowClose.event; - private readonly _onWindowsCountChanged = this._register(new Emitter()); readonly onWindowsCountChanged = this._onWindowsCountChanged.event; @@ -1626,18 +1623,6 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic return state; } - focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { - const lastActive = this.getLastActiveWindow(); - if (lastActive) { - lastActive.focus(); - - return lastActive; - } - - // No window - open new empty one - return this.open({ context, cli, forceEmpty: true })[0]; - } - getLastActiveWindow(): ICodeWindow | undefined { return getLastActiveWindow(WindowsMainService.WINDOWS); } @@ -1695,6 +1680,5 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Emit this._onWindowsCountChanged.fire({ oldCount: WindowsMainService.WINDOWS.length + 1, newCount: WindowsMainService.WINDOWS.length }); - this._onWindowClose.fire(win.id); } } diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 55f0f189714..0ed16cec59b 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -208,10 +208,17 @@ class BrowserMain extends Disposable { const requestService = new BrowserRequestService(remoteAgentService, configurationService, logService); serviceCollection.set(IRequestService, requestService); - // initialize user data + // Userdata Initialize Service const userDataInitializationService = new UserDataInitializationService(environmentService, fileService, storageService, productService, requestService, logService); serviceCollection.set(IUserDataInitializationService, userDataInitializationService); - await userDataInitializationService.initializeRequiredResources(); + + if (await userDataInitializationService.requiresInitialization()) { + // Initialize required resources - settings & global state + await userDataInitializationService.initializeRequiredResources(); + + // Reload configuration after initializing + await configurationService.reloadConfiguration(); + } return { serviceCollection, logService, storageService }; } diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index f62c408d63f..0202085db6d 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -813,7 +813,7 @@ export class DebugSession implements IDebugSession { } if (this.configurationService.getValue('debug').focusWindowOnBreak) { - this.hostService.focus(); + this.hostService.focus({ force: true /* Application may not be active */ }); } } } diff --git a/src/vs/workbench/contrib/debug/browser/replFilter.ts b/src/vs/workbench/contrib/debug/browser/replFilter.ts index 50b2b862673..a4073b7a2d3 100644 --- a/src/vs/workbench/contrib/debug/browser/replFilter.ts +++ b/src/vs/workbench/contrib/debug/browser/replFilter.ts @@ -51,10 +51,6 @@ export class ReplFilter implements ITreeFilter { } filter(element: IReplElement, parentVisibility: TreeVisibility): TreeFilterResult { - if (this._parsedQueries.length === 0) { - return parentVisibility; - } - let includeQueryPresent = false; let includeQueryMatched = false; @@ -72,7 +68,7 @@ export class ReplFilter implements ITreeFilter { } } - return includeQueryPresent ? includeQueryMatched : parentVisibility; + return includeQueryPresent ? includeQueryMatched : (typeof parentVisibility !== 'undefined' ? parentVisibility : TreeVisibility.Visible); } } diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 1b621fc32bb..2d01d20f70b 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -1434,7 +1434,7 @@ class SCMInputWidget extends Disposable { } hasFocus(): boolean { - return this.inputEditor.hasWidgetFocus(); + return this.inputEditor.hasTextFocus(); } private renderValidation(): void { @@ -1512,7 +1512,7 @@ class SCMCollapseAction extends Action { this.enabled = isAnyProviderCollapsible; this.allCollapsed = isAnyProviderCollapsible && this.viewModel.areAllProvidersCollapsed(); - this.label = this.allCollapsed ? localize('expand all', "Expand All Providers") : localize('collapse all', "Collapse All Providers"); + this.label = this.allCollapsed ? localize('expand all', "Expand All Repositories") : localize('collapse all', "Collapse All Repositories"); this.class = this.allCollapsed ? Codicon.expandAll.classNames : Codicon.collapseAll.classNames; } } diff --git a/src/vs/workbench/services/host/browser/host.ts b/src/vs/workbench/services/host/browser/host.ts index 590778fa56e..78bb77dcccb 100644 --- a/src/vs/workbench/services/host/browser/host.ts +++ b/src/vs/workbench/services/host/browser/host.ts @@ -32,8 +32,14 @@ export interface IHostService { /** * Attempt to bring the window to the foreground and focus it. + * + * @param options Pass `force: true` if you want to make the window take + * focus even if the application does not have focus currently. This option + * should only be used if it is necessary to steal focus from the current + * focused application which may not be VSCode. It may not be supported + * in all environments. */ - focus(): Promise; + focus(options?: { force: boolean }): Promise; //#endregion diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 86aa6287b4a..3b633ceafd1 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -82,8 +82,8 @@ export class NativeHostService extends Disposable implements IHostService { return this.electronService.toggleFullScreen(); } - focus(): Promise { - return this.electronService.focusWindow(); + focus(options?: { force: boolean }): Promise { + return this.electronService.focusWindow(options); } restart(): Promise { diff --git a/src/vs/workbench/services/url/electron-sandbox/urlService.ts b/src/vs/workbench/services/url/electron-sandbox/urlService.ts index cdb0cce5e88..1cf519c5cc4 100644 --- a/src/vs/workbench/services/url/electron-sandbox/urlService.ts +++ b/src/vs/workbench/services/url/electron-sandbox/urlService.ts @@ -66,7 +66,7 @@ export class RelayURLService extends NativeURLService implements IURLHandler, IO const result = await super.open(uri, options); if (result) { - await this.electronService.focusWindow(); + await this.electronService.focusWindow({ force: true /* Application may not be active */ }); } return result; diff --git a/src/vs/workbench/services/userData/browser/userDataInit.ts b/src/vs/workbench/services/userData/browser/userDataInit.ts index d3fc176f380..95f57c555d4 100644 --- a/src/vs/workbench/services/userData/browser/userDataInit.ts +++ b/src/vs/workbench/services/userData/browser/userDataInit.ts @@ -30,6 +30,7 @@ export const IUserDataInitializationService = createDecorator; initializeRequiredResources(): Promise; initializeOtherResources(): Promise; initializeExtensions(instantiationService: IInstantiationService): Promise; @@ -105,6 +106,11 @@ export class UserDataInitializationService implements IUserDataInitializationSer return this._userDataSyncStoreClientPromise; } + async requiresInitialization(): Promise { + const userDataSyncStoreClient = await this.createUserDataSyncStoreClient(); + return !!userDataSyncStoreClient; + } + async initializeRequiredResources(): Promise { return this.initialize([SyncResource.Settings, SyncResource.GlobalState]); } diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 7966cf330a9..ed24e6a26cc 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -1032,7 +1032,7 @@ export class TestHostService implements IHostService { async restart(): Promise { } async reload(): Promise { } - async focus(): Promise { } + async focus(options?: { force: boolean }): Promise { } async openWindow(arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: IOpenWindowOptions): Promise { }