@xterm/xterm 6.1.0-beta.2 → 6.1.0-beta.200
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +36 -24
- package/src/browser/AccessibilityManager.ts +6 -3
- package/src/browser/Clipboard.ts +6 -3
- package/src/browser/CoreBrowserTerminal.ts +147 -318
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +11 -11
- package/src/browser/OscLinkProvider.ts +4 -2
- package/src/browser/RenderDebouncer.ts +2 -2
- package/src/browser/TimeBasedDebouncer.ts +2 -2
- package/src/browser/Types.ts +12 -11
- package/src/browser/Viewport.ts +55 -20
- package/src/browser/decorations/BufferDecorationRenderer.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +33 -17
- package/src/browser/input/CompositionHelper.ts +44 -8
- package/src/browser/public/Terminal.ts +25 -28
- package/src/browser/renderer/dom/DomRenderer.ts +205 -41
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +19 -13
- package/src/browser/renderer/dom/WidthCache.ts +54 -52
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +8 -2
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +579 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/services/CharSizeService.ts +2 -2
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +1 -1
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +518 -25
- package/src/browser/services/RenderService.ts +22 -16
- package/src/browser/services/SelectionService.ts +16 -8
- package/src/browser/services/Services.ts +40 -17
- package/src/browser/services/ThemeService.ts +2 -2
- package/src/common/Async.ts +105 -0
- package/src/common/CircularList.ts +2 -2
- package/src/common/Color.ts +8 -0
- package/src/common/CoreTerminal.ts +29 -21
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +256 -36
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +13 -3
- package/src/common/SortedList.ts +7 -3
- package/src/common/TaskQueue.ts +14 -5
- package/src/common/Types.ts +36 -16
- package/src/common/Version.ts +9 -0
- package/src/common/buffer/Buffer.ts +22 -16
- package/src/common/buffer/BufferLine.ts +4 -5
- package/src/common/buffer/BufferSet.ts +7 -6
- package/src/common/buffer/CellData.ts +57 -0
- package/src/common/buffer/Marker.ts +2 -2
- package/src/common/buffer/Types.ts +6 -2
- package/src/common/data/Charsets.ts +1 -1
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +14 -7
- package/src/common/input/KittyKeyboard.ts +519 -0
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +34 -2
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +245 -0
- package/src/common/parser/Constants.ts +22 -4
- package/src/common/parser/DcsParser.ts +5 -5
- package/src/common/parser/EscapeSequenceParser.ts +155 -43
- package/src/common/parser/OscParser.ts +5 -5
- package/src/common/parser/Types.ts +34 -1
- package/src/common/public/BufferLineApiView.ts +2 -2
- package/src/common/public/BufferNamespaceApi.ts +2 -2
- package/src/common/public/ParserApi.ts +3 -0
- package/src/common/services/BufferService.ts +8 -5
- package/src/common/services/CharsetService.ts +4 -0
- package/src/common/services/CoreService.ts +18 -4
- package/src/common/services/DecorationService.ts +24 -8
- package/src/common/services/LogService.ts +1 -31
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +21 -132
- package/src/common/services/OptionsService.ts +13 -7
- package/src/common/services/Services.ts +47 -44
- package/src/common/services/UnicodeService.ts +1 -1
- package/typings/xterm.d.ts +320 -45
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -0,0 +1,485 @@
|
|
|
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 * as DomUtils from '../Dom';
|
|
7
|
+
import { Disposable, IDisposable, toDisposable } from 'common/Lifecycle';
|
|
8
|
+
|
|
9
|
+
const mainWindow = (typeof window === 'object' ? window : globalThis) as Window & typeof globalThis;
|
|
10
|
+
|
|
11
|
+
function tail<T>(array: ArrayLike<T>, n: number = 0): T | undefined {
|
|
12
|
+
return array[array.length - (1 + n)];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function memoize(_target: any, key: string, descriptor: PropertyDescriptor): void {
|
|
16
|
+
let fnKey: string | null = null;
|
|
17
|
+
let fn: Function | null = null;
|
|
18
|
+
|
|
19
|
+
if (typeof descriptor.value === 'function') {
|
|
20
|
+
fnKey = 'value';
|
|
21
|
+
fn = descriptor.value;
|
|
22
|
+
|
|
23
|
+
if (fn!.length !== 0) {
|
|
24
|
+
console.warn('Memoize should only be used in functions with zero parameters');
|
|
25
|
+
}
|
|
26
|
+
} else if (typeof descriptor.get === 'function') {
|
|
27
|
+
fnKey = 'get';
|
|
28
|
+
fn = descriptor.get;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!fn || !fnKey) {
|
|
32
|
+
throw new Error('not supported');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const memoizeKey = `$memoize$${key}`;
|
|
36
|
+
const descriptorAny = descriptor as { [key: string]: any };
|
|
37
|
+
descriptorAny[fnKey] = function (...args: any[]) {
|
|
38
|
+
if (!this.hasOwnProperty(memoizeKey)) {
|
|
39
|
+
Object.defineProperty(this, memoizeKey, {
|
|
40
|
+
configurable: false,
|
|
41
|
+
enumerable: false,
|
|
42
|
+
writable: false,
|
|
43
|
+
value: fn.apply(this, args)
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (this as { [key: string]: any })[memoizeKey];
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
class LinkedListNode<E> {
|
|
52
|
+
|
|
53
|
+
public static readonly Undefined = new LinkedListNode<any>(undefined);
|
|
54
|
+
|
|
55
|
+
public element: E;
|
|
56
|
+
public next: LinkedListNode<E>;
|
|
57
|
+
public prev: LinkedListNode<E>;
|
|
58
|
+
|
|
59
|
+
public constructor(element: E) {
|
|
60
|
+
this.element = element;
|
|
61
|
+
this.next = LinkedListNode.Undefined;
|
|
62
|
+
this.prev = LinkedListNode.Undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
class LinkedList<E> {
|
|
67
|
+
|
|
68
|
+
private _first: LinkedListNode<E> = LinkedListNode.Undefined;
|
|
69
|
+
private _last: LinkedListNode<E> = LinkedListNode.Undefined;
|
|
70
|
+
|
|
71
|
+
public push(element: E): () => void {
|
|
72
|
+
return this._insert(element, true);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private _insert(element: E, atTheEnd: boolean): () => void {
|
|
76
|
+
const newNode = new LinkedListNode(element);
|
|
77
|
+
if (this._first === LinkedListNode.Undefined) {
|
|
78
|
+
this._first = newNode;
|
|
79
|
+
this._last = newNode;
|
|
80
|
+
|
|
81
|
+
} else if (atTheEnd) {
|
|
82
|
+
const oldLast = this._last;
|
|
83
|
+
this._last = newNode;
|
|
84
|
+
newNode.prev = oldLast;
|
|
85
|
+
oldLast.next = newNode;
|
|
86
|
+
|
|
87
|
+
} else {
|
|
88
|
+
const oldFirst = this._first;
|
|
89
|
+
this._first = newNode;
|
|
90
|
+
newNode.next = oldFirst;
|
|
91
|
+
oldFirst.prev = newNode;
|
|
92
|
+
}
|
|
93
|
+
let didRemove = false;
|
|
94
|
+
return () => {
|
|
95
|
+
if (!didRemove) {
|
|
96
|
+
didRemove = true;
|
|
97
|
+
this._remove(newNode);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private _remove(node: LinkedListNode<E>): void {
|
|
103
|
+
if (node.prev !== LinkedListNode.Undefined && node.next !== LinkedListNode.Undefined) {
|
|
104
|
+
const anchor = node.prev;
|
|
105
|
+
anchor.next = node.next;
|
|
106
|
+
node.next.prev = anchor;
|
|
107
|
+
|
|
108
|
+
} else if (node.prev === LinkedListNode.Undefined && node.next === LinkedListNode.Undefined) {
|
|
109
|
+
this._first = LinkedListNode.Undefined;
|
|
110
|
+
this._last = LinkedListNode.Undefined;
|
|
111
|
+
|
|
112
|
+
} else if (node.next === LinkedListNode.Undefined) {
|
|
113
|
+
this._last = this._last.prev!;
|
|
114
|
+
this._last.next = LinkedListNode.Undefined;
|
|
115
|
+
|
|
116
|
+
} else if (node.prev === LinkedListNode.Undefined) {
|
|
117
|
+
this._first = this._first.next!;
|
|
118
|
+
this._first.prev = LinkedListNode.Undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public *[Symbol.iterator](): Iterator<E> {
|
|
123
|
+
let node = this._first;
|
|
124
|
+
while (node !== LinkedListNode.Undefined) {
|
|
125
|
+
yield node.element;
|
|
126
|
+
node = node.next;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export namespace EventType {
|
|
132
|
+
export const TAP = '-xterm-gesturetap';
|
|
133
|
+
export const CHANGE = '-xterm-gesturechange';
|
|
134
|
+
export const START = '-xterm-gesturestart';
|
|
135
|
+
export const END = '-xterm-gesturesend';
|
|
136
|
+
export const CONTEXT_MENU = '-xterm-gesturecontextmenu';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface ITouchData {
|
|
140
|
+
id: number;
|
|
141
|
+
initialTarget: EventTarget;
|
|
142
|
+
initialTimeStamp: number;
|
|
143
|
+
initialPageX: number;
|
|
144
|
+
initialPageY: number;
|
|
145
|
+
rollingTimestamps: number[];
|
|
146
|
+
rollingPageX: number[];
|
|
147
|
+
rollingPageY: number[];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface IGestureEvent extends MouseEvent {
|
|
151
|
+
initialTarget: EventTarget | undefined;
|
|
152
|
+
translationX: number;
|
|
153
|
+
translationY: number;
|
|
154
|
+
pageX: number;
|
|
155
|
+
pageY: number;
|
|
156
|
+
clientX: number;
|
|
157
|
+
clientY: number;
|
|
158
|
+
tapCount: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
interface ITouch {
|
|
162
|
+
identifier: number;
|
|
163
|
+
screenX: number;
|
|
164
|
+
screenY: number;
|
|
165
|
+
clientX: number;
|
|
166
|
+
clientY: number;
|
|
167
|
+
pageX: number;
|
|
168
|
+
pageY: number;
|
|
169
|
+
radiusX: number;
|
|
170
|
+
radiusY: number;
|
|
171
|
+
rotationAngle: number;
|
|
172
|
+
force: number;
|
|
173
|
+
target: Element;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
interface ITouchList {
|
|
177
|
+
[i: number]: ITouch;
|
|
178
|
+
length: number;
|
|
179
|
+
item(index: number): ITouch;
|
|
180
|
+
identifiedTouch(id: number): ITouch;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
interface ITouchEvent extends Event {
|
|
184
|
+
touches: ITouchList;
|
|
185
|
+
targetTouches: ITouchList;
|
|
186
|
+
changedTouches: ITouchList;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class Gesture extends Disposable {
|
|
190
|
+
|
|
191
|
+
private static readonly _scrollFriction = -0.005;
|
|
192
|
+
private static _instance: Gesture;
|
|
193
|
+
private static readonly _holdDelay = 700;
|
|
194
|
+
|
|
195
|
+
private _dispatched = false;
|
|
196
|
+
private readonly _targets = new LinkedList<HTMLElement>();
|
|
197
|
+
private readonly _ignoreTargets = new LinkedList<HTMLElement>();
|
|
198
|
+
private _handle: IDisposable | null;
|
|
199
|
+
|
|
200
|
+
private readonly _activeTouches: { [id: number]: ITouchData };
|
|
201
|
+
|
|
202
|
+
private _lastSetTapCountTime: number;
|
|
203
|
+
|
|
204
|
+
private static readonly _clearTapCountTime = 400; // ms
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
private constructor() {
|
|
208
|
+
super();
|
|
209
|
+
|
|
210
|
+
this._activeTouches = {};
|
|
211
|
+
this._handle = null;
|
|
212
|
+
this._lastSetTapCountTime = 0;
|
|
213
|
+
|
|
214
|
+
const targetWindow = mainWindow;
|
|
215
|
+
this._register(DomUtils.addDisposableListener(targetWindow.document, 'touchstart', (e: ITouchEvent) => this._handleTouchStart(e), { passive: false }));
|
|
216
|
+
this._register(DomUtils.addDisposableListener(targetWindow.document, 'touchend', (e: ITouchEvent) => this._handleTouchEnd(targetWindow, e)));
|
|
217
|
+
this._register(DomUtils.addDisposableListener(targetWindow.document, 'touchmove', (e: ITouchEvent) => this._handleTouchMove(e), { passive: false }));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public static addTarget(element: HTMLElement): IDisposable {
|
|
221
|
+
if (!Gesture.isTouchDevice()) {
|
|
222
|
+
return Disposable.None;
|
|
223
|
+
}
|
|
224
|
+
if (!Gesture._instance) {
|
|
225
|
+
Gesture._instance = new Gesture();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const remove = Gesture._instance._targets.push(element);
|
|
229
|
+
return toDisposable(remove);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
public static ignoreTarget(element: HTMLElement): IDisposable {
|
|
233
|
+
if (!Gesture.isTouchDevice()) {
|
|
234
|
+
return Disposable.None;
|
|
235
|
+
}
|
|
236
|
+
if (!Gesture._instance) {
|
|
237
|
+
Gesture._instance = new Gesture();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const remove = Gesture._instance._ignoreTargets.push(element);
|
|
241
|
+
return toDisposable(remove);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@memoize
|
|
245
|
+
public static isTouchDevice(): boolean {
|
|
246
|
+
return 'ontouchstart' in mainWindow || navigator.maxTouchPoints > 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public override dispose(): void {
|
|
250
|
+
if (this._handle) {
|
|
251
|
+
this._handle.dispose();
|
|
252
|
+
this._handle = null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
super.dispose();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private _handleTouchStart(e: ITouchEvent): void {
|
|
259
|
+
const timestamp = Date.now();
|
|
260
|
+
|
|
261
|
+
if (this._handle) {
|
|
262
|
+
this._handle.dispose();
|
|
263
|
+
this._handle = null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
for (let i = 0, len = e.targetTouches.length; i < len; i++) {
|
|
267
|
+
const touch = e.targetTouches.item(i);
|
|
268
|
+
|
|
269
|
+
this._activeTouches[touch.identifier] = {
|
|
270
|
+
id: touch.identifier,
|
|
271
|
+
initialTarget: touch.target,
|
|
272
|
+
initialTimeStamp: timestamp,
|
|
273
|
+
initialPageX: touch.pageX,
|
|
274
|
+
initialPageY: touch.pageY,
|
|
275
|
+
rollingTimestamps: [timestamp],
|
|
276
|
+
rollingPageX: [touch.pageX],
|
|
277
|
+
rollingPageY: [touch.pageY]
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const evt = this._newGestureEvent(EventType.START, touch.target);
|
|
281
|
+
evt.pageX = touch.pageX;
|
|
282
|
+
evt.pageY = touch.pageY;
|
|
283
|
+
this._dispatchEvent(evt);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (this._dispatched) {
|
|
287
|
+
e.preventDefault();
|
|
288
|
+
e.stopPropagation();
|
|
289
|
+
this._dispatched = false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private _handleTouchEnd(targetWindow: Window, e: ITouchEvent): void {
|
|
294
|
+
const timestamp = Date.now();
|
|
295
|
+
|
|
296
|
+
const activeTouchCount = Object.keys(this._activeTouches).length;
|
|
297
|
+
|
|
298
|
+
for (let i = 0, len = e.changedTouches.length; i < len; i++) {
|
|
299
|
+
|
|
300
|
+
const touch = e.changedTouches.item(i);
|
|
301
|
+
|
|
302
|
+
if (!this._activeTouches.hasOwnProperty(String(touch.identifier))) {
|
|
303
|
+
console.warn('move of an UNKNOWN touch', touch);
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const data = this._activeTouches[touch.identifier];
|
|
308
|
+
const holdTime = Date.now() - data.initialTimeStamp;
|
|
309
|
+
|
|
310
|
+
if (holdTime < Gesture._holdDelay
|
|
311
|
+
&& Math.abs(data.initialPageX - tail(data.rollingPageX)!) < 30
|
|
312
|
+
&& Math.abs(data.initialPageY - tail(data.rollingPageY)!) < 30) {
|
|
313
|
+
|
|
314
|
+
const evt = this._newGestureEvent(EventType.TAP, data.initialTarget);
|
|
315
|
+
evt.pageX = tail(data.rollingPageX)!;
|
|
316
|
+
evt.pageY = tail(data.rollingPageY)!;
|
|
317
|
+
this._dispatchEvent(evt);
|
|
318
|
+
|
|
319
|
+
} else if (holdTime >= Gesture._holdDelay
|
|
320
|
+
&& Math.abs(data.initialPageX - tail(data.rollingPageX)!) < 30
|
|
321
|
+
&& Math.abs(data.initialPageY - tail(data.rollingPageY)!) < 30) {
|
|
322
|
+
|
|
323
|
+
const evt = this._newGestureEvent(EventType.CONTEXT_MENU, data.initialTarget);
|
|
324
|
+
evt.pageX = tail(data.rollingPageX)!;
|
|
325
|
+
evt.pageY = tail(data.rollingPageY)!;
|
|
326
|
+
this._dispatchEvent(evt);
|
|
327
|
+
|
|
328
|
+
} else if (activeTouchCount === 1) {
|
|
329
|
+
const finalX = tail(data.rollingPageX)!;
|
|
330
|
+
const finalY = tail(data.rollingPageY)!;
|
|
331
|
+
|
|
332
|
+
const deltaT = tail(data.rollingTimestamps)! - data.rollingTimestamps[0];
|
|
333
|
+
const deltaX = finalX - data.rollingPageX[0];
|
|
334
|
+
const deltaY = finalY - data.rollingPageY[0];
|
|
335
|
+
|
|
336
|
+
const dispatchTo = [...this._targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));
|
|
337
|
+
this._inertia(targetWindow, dispatchTo, timestamp,
|
|
338
|
+
Math.abs(deltaX) / deltaT,
|
|
339
|
+
deltaX > 0 ? 1 : -1,
|
|
340
|
+
finalX,
|
|
341
|
+
Math.abs(deltaY) / deltaT,
|
|
342
|
+
deltaY > 0 ? 1 : -1,
|
|
343
|
+
finalY
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
this._dispatchEvent(this._newGestureEvent(EventType.END, data.initialTarget));
|
|
349
|
+
delete this._activeTouches[touch.identifier];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (this._dispatched) {
|
|
353
|
+
e.preventDefault();
|
|
354
|
+
e.stopPropagation();
|
|
355
|
+
this._dispatched = false;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private _newGestureEvent(type: string, initialTarget?: EventTarget): IGestureEvent {
|
|
360
|
+
const event = document.createEvent('CustomEvent') as unknown as IGestureEvent;
|
|
361
|
+
event.initEvent(type, false, true);
|
|
362
|
+
event.initialTarget = initialTarget;
|
|
363
|
+
event.tapCount = 0;
|
|
364
|
+
return event;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private _dispatchEvent(event: IGestureEvent): void {
|
|
368
|
+
if (event.type === EventType.TAP) {
|
|
369
|
+
const currentTime = (new Date()).getTime();
|
|
370
|
+
let setTapCount = 0;
|
|
371
|
+
if (currentTime - this._lastSetTapCountTime > Gesture._clearTapCountTime) {
|
|
372
|
+
setTapCount = 1;
|
|
373
|
+
} else {
|
|
374
|
+
setTapCount = 2;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
this._lastSetTapCountTime = currentTime;
|
|
378
|
+
event.tapCount = setTapCount;
|
|
379
|
+
} else if (event.type === EventType.CHANGE || event.type === EventType.CONTEXT_MENU) {
|
|
380
|
+
this._lastSetTapCountTime = 0;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (event.initialTarget instanceof Node) {
|
|
384
|
+
for (const ignoreTarget of this._ignoreTargets) {
|
|
385
|
+
if (ignoreTarget.contains(event.initialTarget)) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const targets: [number, HTMLElement][] = [];
|
|
391
|
+
for (const target of this._targets) {
|
|
392
|
+
if (target.contains(event.initialTarget)) {
|
|
393
|
+
let depth = 0;
|
|
394
|
+
let now: Node | null = event.initialTarget;
|
|
395
|
+
while (now && now !== target) {
|
|
396
|
+
depth++;
|
|
397
|
+
now = now.parentElement;
|
|
398
|
+
}
|
|
399
|
+
targets.push([depth, target]);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
targets.sort((a, b) => a[0] - b[0]);
|
|
404
|
+
|
|
405
|
+
for (const [, target] of targets) {
|
|
406
|
+
target.dispatchEvent(event);
|
|
407
|
+
this._dispatched = true;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
private _inertia(targetWindow: Window, dispatchTo: ReadonlyArray<EventTarget>, t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
|
|
413
|
+
this._handle = DomUtils.scheduleAtNextAnimationFrame(targetWindow, () => {
|
|
414
|
+
const now = Date.now();
|
|
415
|
+
|
|
416
|
+
const deltaT = now - t1;
|
|
417
|
+
let deltaPosX = 0;
|
|
418
|
+
let deltaPosY = 0;
|
|
419
|
+
let stopped = true;
|
|
420
|
+
|
|
421
|
+
vX += Gesture._scrollFriction * deltaT;
|
|
422
|
+
vY += Gesture._scrollFriction * deltaT;
|
|
423
|
+
|
|
424
|
+
if (vX > 0) {
|
|
425
|
+
stopped = false;
|
|
426
|
+
deltaPosX = dirX * vX * deltaT;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (vY > 0) {
|
|
430
|
+
stopped = false;
|
|
431
|
+
deltaPosY = dirY * vY * deltaT;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const evt = this._newGestureEvent(EventType.CHANGE);
|
|
435
|
+
evt.translationX = deltaPosX;
|
|
436
|
+
evt.translationY = deltaPosY;
|
|
437
|
+
dispatchTo.forEach(d => d.dispatchEvent(evt));
|
|
438
|
+
|
|
439
|
+
if (!stopped) {
|
|
440
|
+
this._inertia(targetWindow, dispatchTo, now, vX, dirX, x + deltaPosX, vY, dirY, y + deltaPosY);
|
|
441
|
+
}
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
private _handleTouchMove(e: ITouchEvent): void {
|
|
446
|
+
const timestamp = Date.now();
|
|
447
|
+
|
|
448
|
+
for (let i = 0, len = e.changedTouches.length; i < len; i++) {
|
|
449
|
+
|
|
450
|
+
const touch = e.changedTouches.item(i);
|
|
451
|
+
|
|
452
|
+
if (!this._activeTouches.hasOwnProperty(String(touch.identifier))) {
|
|
453
|
+
console.warn('end of an UNKNOWN touch', touch);
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const data = this._activeTouches[touch.identifier];
|
|
458
|
+
|
|
459
|
+
const evt = this._newGestureEvent(EventType.CHANGE, data.initialTarget);
|
|
460
|
+
evt.translationX = touch.pageX - tail(data.rollingPageX)!;
|
|
461
|
+
evt.translationY = touch.pageY - tail(data.rollingPageY)!;
|
|
462
|
+
evt.pageX = touch.pageX;
|
|
463
|
+
evt.pageY = touch.pageY;
|
|
464
|
+
evt.clientX = touch.clientX;
|
|
465
|
+
evt.clientY = touch.clientY;
|
|
466
|
+
this._dispatchEvent(evt);
|
|
467
|
+
|
|
468
|
+
if (data.rollingPageX.length > 3) {
|
|
469
|
+
data.rollingPageX.shift();
|
|
470
|
+
data.rollingPageY.shift();
|
|
471
|
+
data.rollingTimestamps.shift();
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
data.rollingPageX.push(touch.pageX);
|
|
475
|
+
data.rollingPageY.push(touch.pageY);
|
|
476
|
+
data.rollingTimestamps.push(timestamp);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (this._dispatched) {
|
|
480
|
+
e.preventDefault();
|
|
481
|
+
e.stopPropagation();
|
|
482
|
+
this._dispatched = false;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
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 { AbstractScrollbar, ISimplifiedPointerEvent, IScrollbarHost } from './abstractScrollbar';
|
|
7
|
+
import { IScrollableElementResolvedOptions } from './scrollableElementOptions';
|
|
8
|
+
import { ScrollbarState } from './scrollbarState';
|
|
9
|
+
import { INewScrollPosition, Scrollable, ScrollbarVisibility, IScrollEvent } from './scrollable';
|
|
10
|
+
import type { ScrollbarArrow } from './scrollbarArrow';
|
|
11
|
+
|
|
12
|
+
export class VerticalScrollbar extends AbstractScrollbar {
|
|
13
|
+
private _arrowUp: ScrollbarArrow | undefined;
|
|
14
|
+
private _arrowDown: ScrollbarArrow | undefined;
|
|
15
|
+
private _arrowScrollDelta: number = 0;
|
|
16
|
+
|
|
17
|
+
constructor(scrollable: Scrollable, options: IScrollableElementResolvedOptions, host: IScrollbarHost) {
|
|
18
|
+
const scrollDimensions = scrollable.getScrollDimensions();
|
|
19
|
+
const scrollPosition = scrollable.getCurrentScrollPosition();
|
|
20
|
+
const hasArrows = options.verticalHasArrows;
|
|
21
|
+
super({
|
|
22
|
+
lazyRender: options.lazyRender,
|
|
23
|
+
host: host,
|
|
24
|
+
scrollbarState: new ScrollbarState(
|
|
25
|
+
(hasArrows ? options.verticalScrollbarSize : 0),
|
|
26
|
+
(options.vertical === ScrollbarVisibility.HIDDEN ? 0 : options.verticalScrollbarSize),
|
|
27
|
+
0,
|
|
28
|
+
scrollDimensions.height,
|
|
29
|
+
scrollDimensions.scrollHeight,
|
|
30
|
+
scrollPosition.scrollTop
|
|
31
|
+
),
|
|
32
|
+
visibility: options.vertical,
|
|
33
|
+
extraScrollbarClassName: 'xterm-vertical',
|
|
34
|
+
scrollable: scrollable,
|
|
35
|
+
scrollByPage: options.scrollByPage
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this._setArrows(hasArrows, options.verticalScrollbarSize);
|
|
39
|
+
|
|
40
|
+
this._createSlider(0, Math.floor((options.verticalScrollbarSize - options.verticalSliderSize) / 2), options.verticalSliderSize, undefined);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected _updateSlider(sliderSize: number, sliderPosition: number): void {
|
|
44
|
+
this.slider.setHeight(sliderSize);
|
|
45
|
+
this.slider.setTop(sliderPosition);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected _renderDomNode(largeSize: number, smallSize: number): void {
|
|
49
|
+
this.domNode.setWidth(smallSize);
|
|
50
|
+
this.domNode.setHeight(largeSize);
|
|
51
|
+
this.domNode.setRight(0);
|
|
52
|
+
this.domNode.setTop(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public handleScroll(e: IScrollEvent): boolean {
|
|
56
|
+
this._shouldRender = this._handleElementScrollSize(e.scrollHeight) || this._shouldRender;
|
|
57
|
+
this._shouldRender = this._handleElementScrollPosition(e.scrollTop) || this._shouldRender;
|
|
58
|
+
this._shouldRender = this._handleElementSize(e.height) || this._shouldRender;
|
|
59
|
+
return this._shouldRender;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
protected _pointerDownRelativePosition(offsetX: number, offsetY: number): number {
|
|
63
|
+
return offsetY;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
protected _sliderPointerPosition(e: ISimplifiedPointerEvent): number {
|
|
67
|
+
return e.pageY;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected _sliderOrthogonalPointerPosition(e: ISimplifiedPointerEvent): number {
|
|
71
|
+
return e.pageX;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected _updateScrollbarSize(size: number): void {
|
|
75
|
+
this.slider.setWidth(size);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public writeScrollPosition(target: INewScrollPosition, scrollPosition: number): void {
|
|
79
|
+
target.scrollTop = scrollPosition;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private _arrowScroll(delta: number): void {
|
|
83
|
+
const currentPosition = this._scrollable.getCurrentScrollPosition();
|
|
84
|
+
this._scrollable.setScrollPositionNow({ scrollTop: currentPosition.scrollTop + delta });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private _setArrows(showArrows: boolean, size: number): void {
|
|
88
|
+
this._arrowScrollDelta = size;
|
|
89
|
+
if (!this._arrowUp || !this._arrowDown) {
|
|
90
|
+
const arrowDelta = 0;
|
|
91
|
+
this._arrowUp = this._createArrow({
|
|
92
|
+
className: 'xterm-scra xterm-arrow-up',
|
|
93
|
+
top: arrowDelta,
|
|
94
|
+
left: arrowDelta,
|
|
95
|
+
bgWidth: size,
|
|
96
|
+
bgHeight: size,
|
|
97
|
+
handleActivate: () => this._arrowScroll(-this._arrowScrollDelta)
|
|
98
|
+
});
|
|
99
|
+
this._arrowDown = this._createArrow({
|
|
100
|
+
className: 'xterm-scra xterm-arrow-down',
|
|
101
|
+
bottom: arrowDelta,
|
|
102
|
+
left: arrowDelta,
|
|
103
|
+
bgWidth: size,
|
|
104
|
+
bgHeight: size,
|
|
105
|
+
handleActivate: () => this._arrowScroll(this._arrowScrollDelta)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this._updateArrowSize(this._arrowUp, size);
|
|
110
|
+
this._updateArrowSize(this._arrowDown, size);
|
|
111
|
+
|
|
112
|
+
if (!this._arrowUp || !this._arrowDown) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const display = showArrows ? '' : 'none';
|
|
117
|
+
this._arrowUp.bgDomNode.style.display = display;
|
|
118
|
+
this._arrowUp.domNode.style.display = display;
|
|
119
|
+
this._arrowDown.bgDomNode.style.display = display;
|
|
120
|
+
this._arrowDown.domNode.style.display = display;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private _updateArrowSize(arrow: ScrollbarArrow | undefined, size: number): void {
|
|
124
|
+
if (!arrow) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
arrow.bgDomNode.style.width = `${size}px`;
|
|
128
|
+
arrow.bgDomNode.style.height = `${size}px`;
|
|
129
|
+
arrow.domNode.style.width = `${size}px`;
|
|
130
|
+
arrow.domNode.style.height = `${size}px`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public updateOptions(options: IScrollableElementResolvedOptions): void {
|
|
134
|
+
const arrowSize = options.verticalHasArrows ? options.verticalScrollbarSize : 0;
|
|
135
|
+
this._scrollbarState.setArrowSize(arrowSize);
|
|
136
|
+
this._setArrows(options.verticalHasArrows, options.verticalScrollbarSize);
|
|
137
|
+
this.updateScrollbarSize(options.vertical === ScrollbarVisibility.HIDDEN ? 0 : options.verticalScrollbarSize);
|
|
138
|
+
this._scrollbarState.setOppositeScrollbarSize(0);
|
|
139
|
+
this._visibilityController.setVisibility(options.vertical);
|
|
140
|
+
this._scrollByPage = options.scrollByPage;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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 * as dom from '../Dom';
|
|
7
|
+
import { IMouseEvent, StandardMouseEvent } from './mouseEvent';
|
|
8
|
+
import { Disposable } from 'common/Lifecycle';
|
|
9
|
+
|
|
10
|
+
export abstract class Widget extends Disposable {
|
|
11
|
+
|
|
12
|
+
protected _onclick(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {
|
|
13
|
+
this._register(dom.addDisposableListener(domNode, dom.eventType.CLICK, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e))));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
protected _onmouseover(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {
|
|
17
|
+
this._register(dom.addDisposableListener(domNode, dom.eventType.MOUSE_OVER, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e))));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
protected _onmouseleave(domNode: HTMLElement, listener: (e: IMouseEvent) => void): void {
|
|
21
|
+
this._register(dom.addDisposableListener(domNode, dom.eventType.MOUSE_LEAVE, (e: MouseEvent) => listener(new StandardMouseEvent(dom.getWindow(domNode), e))));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { IOptionsService } from 'common/services/Services';
|
|
7
7
|
import { ICharSizeService } from 'browser/services/Services';
|
|
8
|
-
import { Disposable } from '
|
|
9
|
-
import { Emitter } from '
|
|
8
|
+
import { Disposable } from 'common/Lifecycle';
|
|
9
|
+
import { Emitter } from 'common/Event';
|
|
10
10
|
|
|
11
11
|
export class CharSizeService extends Disposable implements ICharSizeService {
|
|
12
12
|
public serviceBrand: undefined;
|
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ICoreBrowserService } from './Services';
|
|
7
|
-
import { Emitter,
|
|
8
|
-
import { addDisposableListener } from '
|
|
9
|
-
import { Disposable, MutableDisposable, toDisposable } from '
|
|
7
|
+
import { Emitter, EventUtils } from 'common/Event';
|
|
8
|
+
import { addDisposableListener } from 'browser/Dom';
|
|
9
|
+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
|
|
10
10
|
|
|
11
11
|
export class CoreBrowserService extends Disposable implements ICoreBrowserService {
|
|
12
12
|
public serviceBrand: undefined;
|
|
13
13
|
|
|
14
14
|
private _isFocused = false;
|
|
15
15
|
private _cachedIsFocused: boolean | undefined = undefined;
|
|
16
|
-
private _screenDprMonitor
|
|
16
|
+
private _screenDprMonitor: ScreenDprMonitor;
|
|
17
17
|
|
|
18
18
|
private readonly _onDprChange = this._register(new Emitter<number>());
|
|
19
19
|
public readonly onDprChange = this._onDprChange.event;
|
|
@@ -27,9 +27,11 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
|
|
|
27
27
|
) {
|
|
28
28
|
super();
|
|
29
29
|
|
|
30
|
+
this._screenDprMonitor = this._register(new ScreenDprMonitor(this._window));
|
|
31
|
+
|
|
30
32
|
// Monitor device pixel ratio
|
|
31
33
|
this._register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
|
|
32
|
-
this._register(
|
|
34
|
+
this._register(EventUtils.forward(this._screenDprMonitor.onDprChange, this._onDprChange));
|
|
33
35
|
|
|
34
36
|
this._register(addDisposableListener(this._textarea, 'focus', () => this._isFocused = true));
|
|
35
37
|
this._register(addDisposableListener(this._textarea, 'blur', () => this._isFocused = false));
|