diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index dc9446a34e1..b3832d12ec4 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -80,7 +80,6 @@ import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encry import { ActiveWindowManager } from 'vs/platform/windows/node/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -import { DisplayMainService, IDisplayMainService } from 'vs/platform/display/electron-main/displayMainService'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { isEqualOrParent } from 'vs/base/common/extpath'; import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; @@ -559,9 +558,6 @@ export class CodeApplication extends Disposable { // Keyboard Layout services.set(IKeyboardLayoutMainService, new SyncDescriptor(KeyboardLayoutMainService)); - // Display - services.set(IDisplayMainService, new SyncDescriptor(DisplayMainService)); - // Native Host services.set(INativeHostMainService, new SyncDescriptor(NativeHostMainService, [sharedProcess])); @@ -633,10 +629,6 @@ export class CodeApplication extends Disposable { const keyboardLayoutChannel = ProxyChannel.fromService(accessor.get(IKeyboardLayoutMainService)); mainProcessElectronServer.registerChannel('keyboardLayout', keyboardLayoutChannel); - // Display - const displayChannel = ProxyChannel.fromService(accessor.get(IDisplayMainService)); - mainProcessElectronServer.registerChannel('display', displayChannel); - // Native host (main & shared process) this.nativeHostMainService = accessor.get(INativeHostMainService); const nativeHostChannel = ProxyChannel.fromService(this.nativeHostMainService); diff --git a/src/vs/platform/display/common/displayMainService.ts b/src/vs/platform/display/common/displayMainService.ts deleted file mode 100644 index 44d79f8d545..00000000000 --- a/src/vs/platform/display/common/displayMainService.ts +++ /dev/null @@ -1,11 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; - -export interface IDisplayMainService { - readonly _serviceBrand: undefined; - readonly onDidDisplayChanged: Event; -} diff --git a/src/vs/platform/display/electron-main/displayMainService.ts b/src/vs/platform/display/electron-main/displayMainService.ts deleted file mode 100644 index e360fc48693..00000000000 --- a/src/vs/platform/display/electron-main/displayMainService.ts +++ /dev/null @@ -1,47 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IDisplayMainService as ICommonDisplayMainService } from 'vs/platform/display/common/displayMainService'; -import { Emitter } from 'vs/base/common/event'; -import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { app, Display, screen } from 'electron'; -import { RunOnceScheduler } from 'vs/base/common/async'; - -export const IDisplayMainService = createDecorator('displayMainService'); - -export interface IDisplayMainService extends ICommonDisplayMainService { } - -export class DisplayMainService extends Disposable implements ICommonDisplayMainService { - - declare readonly _serviceBrand: undefined; - - private readonly _onDidDisplayChanged = this._register(new Emitter()); - readonly onDidDisplayChanged = this._onDidDisplayChanged.event; - - constructor() { - super(); - - const displayChangedScheduler = this._register(new RunOnceScheduler(() => { - this._onDidDisplayChanged.fire(); - }, 100)); - - app.whenReady().then(() => { - - const displayChangedListener = (event: Event, display: Display, changedMetrics?: string[]) => { - displayChangedScheduler.schedule(); - }; - - screen.on('display-metrics-changed', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-metrics-changed', displayChangedListener))); - - screen.on('display-added', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-added', displayChangedListener))); - - screen.on('display-removed', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-removed', displayChangedListener))); - }); - } -} diff --git a/src/vs/platform/native/common/native.ts b/src/vs/platform/native/common/native.ts index 2c8414ba871..b07c29774d5 100644 --- a/src/vs/platform/native/common/native.ts +++ b/src/vs/platform/native/common/native.ts @@ -45,6 +45,8 @@ export interface ICommonNativeHostService { readonly onDidFocusWindow: Event; readonly onDidBlurWindow: Event; + readonly onDidChangeDisplay: Event; + readonly onDidResumeOS: Event; readonly onDidChangeColorScheme: Event; diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index 989cf596f6f..9007e3216da 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -5,7 +5,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IWindowsMainService, ICodeWindow, OpenContext } from 'vs/platform/windows/electron-main/windows'; -import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme } from 'electron'; +import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Menu, BrowserWindow, app, clipboard, powerMonitor, nativeTheme, screen, Display } from 'electron'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { IOpenedWindow, IOpenWindowOptions, IWindowOpenable, IOpenEmptyWindowOptions, IColorScheme } from 'vs/platform/windows/common/windows'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs'; @@ -74,6 +74,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Events readonly onDidOpenWindow = Event.map(this.windowsMainService.onDidOpenWindow, window => window.id); @@ -95,8 +96,20 @@ export class NativeHostMainService extends Disposable implements INativeHostMain private readonly _onDidChangePassword = this._register(new Emitter<{ account: string, service: string }>()); readonly onDidChangePassword = this._onDidChangePassword.event; + readonly onDidChangeDisplay = Event.debounce(Event.any( + Event.filter(Event.fromNodeEventEmitter(screen, 'display-metrics-changed', (event: Electron.Event, display: Display, changedMetrics?: string[]) => changedMetrics), changedMetrics => { + // Electron will emit 'display-metrics-changed' events even when actually + // going fullscreen, because the dock hides. However, we do not want to + // react on this event as there is no change in display bounds. + return !(Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea'); + }), + Event.fromNodeEventEmitter(screen, 'display-added'), + Event.fromNodeEventEmitter(screen, 'display-removed') + ), () => { }, 100); + //#endregion + //#region Window async getWindows(): Promise { @@ -234,6 +247,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Dialog async showMessageBox(windowId: number | undefined, options: MessageBoxOptions): Promise { @@ -313,6 +327,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region OS async showItemInFolder(windowId: number | undefined, path: string): Promise { @@ -502,6 +517,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region macOS Touchbar async newWindowTab(): Promise { @@ -537,6 +553,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Lifecycle async notifyReady(windowId: number | undefined): Promise { @@ -591,6 +608,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Connectivity async resolveProxy(windowId: number | undefined, url: string): Promise { @@ -605,6 +623,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Development async openDevTools(windowId: number | undefined, options?: OpenDevToolsOptions): Promise { @@ -635,6 +654,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Registry (windows) async windowsGetStringRegKey(windowId: number | undefined, hive: 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG', path: string, name: string): Promise { @@ -652,6 +672,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain //#endregion + //#region Credentials private static readonly MAX_PASSWORD_LENGTH = 2500; diff --git a/src/vs/platform/windows/electron-main/window.ts b/src/vs/platform/windows/electron-main/window.ts index 52ff422eb91..0eebc9dc8be 100644 --- a/src/vs/platform/windows/electron-main/window.ts +++ b/src/vs/platform/windows/electron-main/window.ts @@ -17,7 +17,7 @@ import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import product from 'vs/platform/product/common/product'; import { WindowMinimumSize, IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor, INativeWindowConfiguration } from 'vs/platform/windows/common/windows'; -import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { browserCodeLoadingCacheStrategy, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { defaultWindowState, ICodeWindow, ILoadEvent, IWindowState, WindowError, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; @@ -26,7 +26,6 @@ import { IBackupMainService } from 'vs/platform/backup/electron-main/backup'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/common/extensionGalleryService'; import { IThemeMainService } from 'vs/platform/theme/electron-main/themeMainService'; -import { RunOnceScheduler } from 'vs/base/common/async'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; @@ -37,6 +36,7 @@ import { ByteSize, IFileService } from 'vs/platform/files/common/files'; import { FileAccess, Schemas } from 'vs/base/common/network'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { INativeHostMainService } from 'vs/platform/native/electron-main/nativeHostMainService'; export interface IWindowCreationOptions { state: IWindowState; @@ -118,7 +118,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { @IBackupMainService private readonly backupMainService: IBackupMainService, @ITelemetryService private readonly telemetryService: ITelemetryService, @IDialogMainService private readonly dialogMainService: IDialogMainService, - @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService + @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, + @INativeHostMainService private readonly nativeHostMainService: INativeHostMainService ) { super(); @@ -468,7 +469,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { }); if (isMacintosh) { - const displayChangedScheduler = this._register(new RunOnceScheduler(() => { + this._register(this.nativeHostMainService.onDidChangeDisplay(() => { if (!this._win) { return; // disposed } @@ -480,27 +481,7 @@ export class CodeWindow extends Disposable implements ICodeWindow { this.setFullScreen(false); this.setFullScreen(true); } - }, 100)); - - const displayChangedListener = (event: Event, display: Display, changedMetrics?: string[]) => { - if (Array.isArray(changedMetrics) && changedMetrics.length === 1 && changedMetrics[0] === 'workArea') { - // Electron will emit 'display-metrics-changed' events even when actually - // going fullscreen, because the dock hides. However, we do not want to - // react on this event as there is no change in display bounds. - return; - } - - displayChangedScheduler.schedule(); - }; - - screen.on('display-metrics-changed', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-metrics-changed', displayChangedListener))); - - screen.on('display-added', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-added', displayChangedListener))); - - screen.on('display-removed', displayChangedListener); - this._register(toDisposable(() => screen.removeListener('display-removed', displayChangedListener))); + })); } // Window (Un)Maximize diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts index 94cfd235857..ac3c31c9f3e 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts @@ -7,21 +7,19 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services'; -import { IDisplayMainService } from 'vs/platform/display/common/displayMainService'; -import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc'; +import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { clearAllFontInfos } from 'vs/editor/browser/config/configuration'; class DisplayChangeRemeasureFonts extends Disposable implements IWorkbenchContribution { constructor( - @IMainProcessService mainProcessService: IMainProcessService + @INativeHostService nativeHostService: INativeHostService ) { super(); - const displayMainService = ProxyChannel.toService(mainProcessService.getChannel('display')); - displayMainService.onDidDisplayChanged(() => { + + this._register(nativeHostService.onDidChangeDisplay(() => { clearAllFontInfos(); - }); + })); } } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index f2c26043db4..b84e30fae04 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -167,6 +167,7 @@ export class TestNativeHostService implements INativeHostService { onDidResumeOS: Event = Event.None; onDidChangeColorScheme = Event.None; onDidChangePassword = Event.None; + onDidChangeDisplay = Event.None; windowCount = Promise.resolve(1); getWindowCount(): Promise { return this.windowCount; }