Path: blob/main/src/vs/editor/browser/controller/editContext/native/nativeEditContextUtils.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { addDisposableListener, getActiveElement, getShadowRoot } from '../../../../../base/browser/dom.js';6import { IDisposable, Disposable } from '../../../../../base/common/lifecycle.js';7import { ILogService } from '../../../../../platform/log/common/log.js';89export interface ITypeData {10text: string;11replacePrevCharCnt: number;12replaceNextCharCnt: number;13positionDelta: number;14}1516export class FocusTracker extends Disposable {17private _isFocused: boolean = false;18private _isPaused: boolean = false;1920constructor(21@ILogService _logService: ILogService,22private readonly _domNode: HTMLElement,23private readonly _onFocusChange: (newFocusValue: boolean) => void,24) {25super();26this._register(addDisposableListener(this._domNode, 'focus', () => {27_logService.trace('NativeEditContext.focus');28if (this._isPaused) {29return;30}31// Here we don't trust the browser and instead we check32// that the active element is the one we are tracking33// (this happens when cmd+tab is used to switch apps)34this.refreshFocusState();35}));36this._register(addDisposableListener(this._domNode, 'blur', () => {37_logService.trace('NativeEditContext.blur');38if (this._isPaused) {39return;40}41this._handleFocusedChanged(false);42}));43}4445public pause(): void {46this._isPaused = true;47}4849public resume(): void {50this._isPaused = false;51this.refreshFocusState();52}5354private _handleFocusedChanged(focused: boolean): void {55if (this._isFocused === focused) {56return;57}58this._isFocused = focused;59this._onFocusChange(this._isFocused);60}6162public focus(): void {63this._domNode.focus();64this.refreshFocusState();65}6667public refreshFocusState(): void {68const shadowRoot = getShadowRoot(this._domNode);69const activeElement = shadowRoot ? shadowRoot.activeElement : getActiveElement();70const focused = this._domNode === activeElement;71this._handleFocusedChanged(focused);72}7374get isFocused(): boolean {75return this._isFocused;76}77}7879export function editContextAddDisposableListener<K extends keyof EditContextEventHandlersEventMap>(target: EventTarget, type: K, listener: (this: GlobalEventHandlers, ev: EditContextEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions): IDisposable {80target.addEventListener(type, listener as any, options);81return {82dispose() {83target.removeEventListener(type, listener as any);84}85};86}878889