From 9eeb60b7f286a104f844e99b3a69974bbad72f97 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 26 Oct 2023 10:37:39 +0200 Subject: [PATCH] Aux window: Chord timeout much smaller in aux window (fix #196184) (#196687) --- .../host/browser/browserHostService.ts | 26 ++++++++------- .../electron-sandbox/nativeHostService.ts | 33 ++++++++++++++----- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 008e5065ab3..4f56301f2f9 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; @@ -14,7 +14,7 @@ import { isResourceEditorInput, pathsToEditors } from 'vs/workbench/common/edito import { whenEditorClosed } from 'vs/workbench/browser/editor'; import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService, Verbosity } from 'vs/platform/label/common/label'; -import { ModifierKeyEmitter, trackFocus } from 'vs/base/browser/dom'; +import { ModifierKeyEmitter, getActiveDocument, getActiveWindow, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; import { Disposable } from 'vs/base/common/lifecycle'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { memoize } from 'vs/base/common/decorators'; @@ -179,18 +179,22 @@ export class BrowserHostService extends Disposable implements IHostService { @memoize get onDidChangeFocus(): Event { - const focusTracker = this._register(trackFocus(window)); - const onVisibilityChange = this._register(new DomEmitter(window.document, 'visibilitychange')); + const emitter = this._register(new Emitter()); - return Event.latch(Event.any( - Event.map(focusTracker.onDidFocus, () => this.hasFocus), - Event.map(focusTracker.onDidBlur, () => this.hasFocus), - Event.map(onVisibilityChange.event, () => this.hasFocus) - )); + this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => { + const focusTracker = disposables.add(trackFocus(window)); + const onVisibilityChange = disposables.add(new DomEmitter(window.document, 'visibilitychange')); + + disposables.add(focusTracker.onDidFocus(() => emitter.fire(this.hasFocus))); + disposables.add(focusTracker.onDidBlur(() => emitter.fire(this.hasFocus))); + disposables.add(onVisibilityChange.event(() => emitter.fire(this.hasFocus))); + }, { window, disposables: this._store })); + + return emitter.event; } get hasFocus(): boolean { - return document.hasFocus(); + return getActiveDocument().hasFocus(); } async hadLastFocus(): Promise { @@ -198,7 +202,7 @@ export class BrowserHostService extends Disposable implements IHostService { } async focus(): Promise { - window.focus(); + getActiveWindow().focus(); } //#endregion diff --git a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts index 66d55f33f98..47b619b855f 100644 --- a/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts +++ b/src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event } from 'vs/base/common/event'; +import { Emitter, Event } from 'vs/base/common/event'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { INativeHostService } from 'vs/platform/native/common/native'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -15,7 +15,9 @@ import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHos import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { isAuxiliaryWindow } from 'vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService'; -import { getActiveWindow } from 'vs/base/browser/dom'; +import { getActiveDocument, getActiveWindow, onDidRegisterWindow, trackFocus } from 'vs/base/browser/dom'; +import { DomEmitter } from 'vs/base/browser/event'; +import { memoize } from 'vs/base/common/decorators'; class WorkbenchNativeHostService extends NativeHostService { @@ -41,14 +43,29 @@ class WorkbenchHostService extends Disposable implements IHostService { //#region Focus - get onDidChangeFocus(): Event { return this._onDidChangeFocus; } - private _onDidChangeFocus: Event = Event.latch(Event.any( - Event.map(Event.filter(this.nativeHostService.onDidFocusWindow, id => id === this.nativeHostService.windowId), () => this.hasFocus), - Event.map(Event.filter(this.nativeHostService.onDidBlurWindow, id => id === this.nativeHostService.windowId), () => this.hasFocus) - ), undefined, this._store); + @memoize + get onDidChangeFocus(): Event { + const emitter = this._register(new Emitter()); + + // Main window: track via native API + this._register(Event.filter(this.nativeHostService.onDidFocusWindow, id => id === this.nativeHostService.windowId, this._store)(() => emitter.fire(this.hasFocus))); + this._register(Event.filter(this.nativeHostService.onDidBlurWindow, id => id === this.nativeHostService.windowId, this._store)(() => emitter.fire(this.hasFocus))); + + // Aux windows: track via DOM APIs + this._register(onDidRegisterWindow(({ window, disposables }) => { + const focusTracker = disposables.add(trackFocus(window)); + const onVisibilityChange = disposables.add(new DomEmitter(window.document, 'visibilitychange')); + + disposables.add(focusTracker.onDidFocus(() => emitter.fire(this.hasFocus))); + disposables.add(focusTracker.onDidBlur(() => emitter.fire(this.hasFocus))); + disposables.add(onVisibilityChange.event(() => emitter.fire(this.hasFocus))); + })); + + return emitter.event; + } get hasFocus(): boolean { - return document.hasFocus(); + return getActiveDocument().hasFocus(); } async hadLastFocus(): Promise {