Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/browser/controller/editContext/native/nativeEditContextUtils.ts
3296 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 { addDisposableListener, getActiveElement, getShadowRoot } from '../../../../../base/browser/dom.js';
7
import { IDisposable, Disposable } from '../../../../../base/common/lifecycle.js';
8
import { ILogService } from '../../../../../platform/log/common/log.js';
9
10
export interface ITypeData {
11
text: string;
12
replacePrevCharCnt: number;
13
replaceNextCharCnt: number;
14
positionDelta: number;
15
}
16
17
export class FocusTracker extends Disposable {
18
private _isFocused: boolean = false;
19
private _isPaused: boolean = false;
20
21
constructor(
22
@ILogService _logService: ILogService,
23
private readonly _domNode: HTMLElement,
24
private readonly _onFocusChange: (newFocusValue: boolean) => void,
25
) {
26
super();
27
this._register(addDisposableListener(this._domNode, 'focus', () => {
28
_logService.trace('NativeEditContext.focus');
29
if (this._isPaused) {
30
return;
31
}
32
// Here we don't trust the browser and instead we check
33
// that the active element is the one we are tracking
34
// (this happens when cmd+tab is used to switch apps)
35
this.refreshFocusState();
36
}));
37
this._register(addDisposableListener(this._domNode, 'blur', () => {
38
_logService.trace('NativeEditContext.blur');
39
if (this._isPaused) {
40
return;
41
}
42
this._handleFocusedChanged(false);
43
}));
44
}
45
46
public pause(): void {
47
this._isPaused = true;
48
}
49
50
public resume(): void {
51
this._isPaused = false;
52
this.refreshFocusState();
53
}
54
55
private _handleFocusedChanged(focused: boolean): void {
56
if (this._isFocused === focused) {
57
return;
58
}
59
this._isFocused = focused;
60
this._onFocusChange(this._isFocused);
61
}
62
63
public focus(): void {
64
this._domNode.focus();
65
this.refreshFocusState();
66
}
67
68
public refreshFocusState(): void {
69
const shadowRoot = getShadowRoot(this._domNode);
70
const activeElement = shadowRoot ? shadowRoot.activeElement : getActiveElement();
71
const focused = this._domNode === activeElement;
72
this._handleFocusedChanged(focused);
73
}
74
75
get isFocused(): boolean {
76
return this._isFocused;
77
}
78
}
79
80
export function editContextAddDisposableListener<K extends keyof EditContextEventHandlersEventMap>(target: EventTarget, type: K, listener: (this: GlobalEventHandlers, ev: EditContextEventHandlersEventMap[K]) => any, options?: boolean | AddEventListenerOptions): IDisposable {
81
target.addEventListener(type, listener as any, options);
82
return {
83
dispose() {
84
target.removeEventListener(type, listener as any);
85
}
86
};
87
}
88
89