@xterm/xterm 5.4.0-beta.1

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.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/css/xterm.css +209 -0
  4. package/lib/xterm.js +2 -0
  5. package/lib/xterm.js.map +1 -0
  6. package/package.json +101 -0
  7. package/src/browser/AccessibilityManager.ts +278 -0
  8. package/src/browser/Clipboard.ts +93 -0
  9. package/src/browser/ColorContrastCache.ts +34 -0
  10. package/src/browser/Lifecycle.ts +33 -0
  11. package/src/browser/Linkifier2.ts +416 -0
  12. package/src/browser/LocalizableStrings.ts +12 -0
  13. package/src/browser/OscLinkProvider.ts +128 -0
  14. package/src/browser/RenderDebouncer.ts +83 -0
  15. package/src/browser/Terminal.ts +1317 -0
  16. package/src/browser/TimeBasedDebouncer.ts +86 -0
  17. package/src/browser/Types.d.ts +181 -0
  18. package/src/browser/Viewport.ts +401 -0
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +134 -0
  20. package/src/browser/decorations/ColorZoneStore.ts +117 -0
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +218 -0
  22. package/src/browser/input/CompositionHelper.ts +246 -0
  23. package/src/browser/input/Mouse.ts +54 -0
  24. package/src/browser/input/MoveToCell.ts +249 -0
  25. package/src/browser/public/Terminal.ts +260 -0
  26. package/src/browser/renderer/dom/DomRenderer.ts +509 -0
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +526 -0
  28. package/src/browser/renderer/dom/WidthCache.ts +160 -0
  29. package/src/browser/renderer/shared/CellColorResolver.ts +137 -0
  30. package/src/browser/renderer/shared/CharAtlasCache.ts +96 -0
  31. package/src/browser/renderer/shared/CharAtlasUtils.ts +75 -0
  32. package/src/browser/renderer/shared/Constants.ts +14 -0
  33. package/src/browser/renderer/shared/CursorBlinkStateManager.ts +146 -0
  34. package/src/browser/renderer/shared/CustomGlyphs.ts +687 -0
  35. package/src/browser/renderer/shared/DevicePixelObserver.ts +41 -0
  36. package/src/browser/renderer/shared/README.md +1 -0
  37. package/src/browser/renderer/shared/RendererUtils.ts +58 -0
  38. package/src/browser/renderer/shared/SelectionRenderModel.ts +91 -0
  39. package/src/browser/renderer/shared/TextureAtlas.ts +1082 -0
  40. package/src/browser/renderer/shared/Types.d.ts +173 -0
  41. package/src/browser/selection/SelectionModel.ts +144 -0
  42. package/src/browser/selection/Types.d.ts +15 -0
  43. package/src/browser/services/CharSizeService.ts +102 -0
  44. package/src/browser/services/CharacterJoinerService.ts +339 -0
  45. package/src/browser/services/CoreBrowserService.ts +137 -0
  46. package/src/browser/services/MouseService.ts +46 -0
  47. package/src/browser/services/RenderService.ts +279 -0
  48. package/src/browser/services/SelectionService.ts +1031 -0
  49. package/src/browser/services/Services.ts +147 -0
  50. package/src/browser/services/ThemeService.ts +237 -0
  51. package/src/common/CircularList.ts +241 -0
  52. package/src/common/Clone.ts +23 -0
  53. package/src/common/Color.ts +357 -0
  54. package/src/common/CoreTerminal.ts +284 -0
  55. package/src/common/EventEmitter.ts +78 -0
  56. package/src/common/InputHandler.ts +3461 -0
  57. package/src/common/Lifecycle.ts +108 -0
  58. package/src/common/MultiKeyMap.ts +42 -0
  59. package/src/common/Platform.ts +44 -0
  60. package/src/common/SortedList.ts +118 -0
  61. package/src/common/TaskQueue.ts +166 -0
  62. package/src/common/TypedArrayUtils.ts +17 -0
  63. package/src/common/Types.d.ts +553 -0
  64. package/src/common/WindowsMode.ts +27 -0
  65. package/src/common/buffer/AttributeData.ts +196 -0
  66. package/src/common/buffer/Buffer.ts +654 -0
  67. package/src/common/buffer/BufferLine.ts +524 -0
  68. package/src/common/buffer/BufferRange.ts +13 -0
  69. package/src/common/buffer/BufferReflow.ts +223 -0
  70. package/src/common/buffer/BufferSet.ts +134 -0
  71. package/src/common/buffer/CellData.ts +94 -0
  72. package/src/common/buffer/Constants.ts +149 -0
  73. package/src/common/buffer/Marker.ts +43 -0
  74. package/src/common/buffer/Types.d.ts +52 -0
  75. package/src/common/data/Charsets.ts +256 -0
  76. package/src/common/data/EscapeSequences.ts +153 -0
  77. package/src/common/input/Keyboard.ts +398 -0
  78. package/src/common/input/TextDecoder.ts +346 -0
  79. package/src/common/input/UnicodeV6.ts +145 -0
  80. package/src/common/input/WriteBuffer.ts +246 -0
  81. package/src/common/input/XParseColor.ts +80 -0
  82. package/src/common/parser/Constants.ts +58 -0
  83. package/src/common/parser/DcsParser.ts +192 -0
  84. package/src/common/parser/EscapeSequenceParser.ts +792 -0
  85. package/src/common/parser/OscParser.ts +238 -0
  86. package/src/common/parser/Params.ts +229 -0
  87. package/src/common/parser/Types.d.ts +275 -0
  88. package/src/common/public/AddonManager.ts +53 -0
  89. package/src/common/public/BufferApiView.ts +35 -0
  90. package/src/common/public/BufferLineApiView.ts +29 -0
  91. package/src/common/public/BufferNamespaceApi.ts +36 -0
  92. package/src/common/public/ParserApi.ts +37 -0
  93. package/src/common/public/UnicodeApi.ts +27 -0
  94. package/src/common/services/BufferService.ts +151 -0
  95. package/src/common/services/CharsetService.ts +34 -0
  96. package/src/common/services/CoreMouseService.ts +318 -0
  97. package/src/common/services/CoreService.ts +87 -0
  98. package/src/common/services/DecorationService.ts +140 -0
  99. package/src/common/services/InstantiationService.ts +85 -0
  100. package/src/common/services/LogService.ts +124 -0
  101. package/src/common/services/OptionsService.ts +202 -0
  102. package/src/common/services/OscLinkService.ts +115 -0
  103. package/src/common/services/ServiceRegistry.ts +49 -0
  104. package/src/common/services/Services.ts +373 -0
  105. package/src/common/services/UnicodeService.ts +111 -0
  106. package/src/headless/Terminal.ts +136 -0
  107. package/src/headless/public/Terminal.ts +195 -0
  108. package/typings/xterm.d.ts +1857 -0
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Copyright (c) 2018 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { IBufferLine, ICellData, CharData } from 'common/Types';
7
+ import { ICharacterJoiner } from 'browser/Types';
8
+ import { AttributeData } from 'common/buffer/AttributeData';
9
+ import { WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants';
10
+ import { CellData } from 'common/buffer/CellData';
11
+ import { IBufferService } from 'common/services/Services';
12
+ import { ICharacterJoinerService } from 'browser/services/Services';
13
+
14
+ export class JoinedCellData extends AttributeData implements ICellData {
15
+ private _width: number;
16
+ // .content carries no meaning for joined CellData, simply nullify it
17
+ // thus we have to overload all other .content accessors
18
+ public content: number = 0;
19
+ public fg: number;
20
+ public bg: number;
21
+ public combinedData: string = '';
22
+
23
+ constructor(firstCell: ICellData, chars: string, width: number) {
24
+ super();
25
+ this.fg = firstCell.fg;
26
+ this.bg = firstCell.bg;
27
+ this.combinedData = chars;
28
+ this._width = width;
29
+ }
30
+
31
+ public isCombined(): number {
32
+ // always mark joined cell data as combined
33
+ return Content.IS_COMBINED_MASK;
34
+ }
35
+
36
+ public getWidth(): number {
37
+ return this._width;
38
+ }
39
+
40
+ public getChars(): string {
41
+ return this.combinedData;
42
+ }
43
+
44
+ public getCode(): number {
45
+ // code always gets the highest possible fake codepoint (read as -1)
46
+ // this is needed as code is used by caches as identifier
47
+ return 0x1FFFFF;
48
+ }
49
+
50
+ public setFromCharData(value: CharData): void {
51
+ throw new Error('not implemented');
52
+ }
53
+
54
+ public getAsCharData(): CharData {
55
+ return [this.fg, this.getChars(), this.getWidth(), this.getCode()];
56
+ }
57
+ }
58
+
59
+ export class CharacterJoinerService implements ICharacterJoinerService {
60
+ public serviceBrand: undefined;
61
+
62
+ private _characterJoiners: ICharacterJoiner[] = [];
63
+ private _nextCharacterJoinerId: number = 0;
64
+ private _workCell: CellData = new CellData();
65
+
66
+ constructor(
67
+ @IBufferService private _bufferService: IBufferService
68
+ ) { }
69
+
70
+ public register(handler: (text: string) => [number, number][]): number {
71
+ const joiner: ICharacterJoiner = {
72
+ id: this._nextCharacterJoinerId++,
73
+ handler
74
+ };
75
+
76
+ this._characterJoiners.push(joiner);
77
+ return joiner.id;
78
+ }
79
+
80
+ public deregister(joinerId: number): boolean {
81
+ for (let i = 0; i < this._characterJoiners.length; i++) {
82
+ if (this._characterJoiners[i].id === joinerId) {
83
+ this._characterJoiners.splice(i, 1);
84
+ return true;
85
+ }
86
+ }
87
+
88
+ return false;
89
+ }
90
+
91
+ public getJoinedCharacters(row: number): [number, number][] {
92
+ if (this._characterJoiners.length === 0) {
93
+ return [];
94
+ }
95
+
96
+ const line = this._bufferService.buffer.lines.get(row);
97
+ if (!line || line.length === 0) {
98
+ return [];
99
+ }
100
+
101
+ const ranges: [number, number][] = [];
102
+ const lineStr = line.translateToString(true);
103
+
104
+ // Because some cells can be represented by multiple javascript characters,
105
+ // we track the cell and the string indexes separately. This allows us to
106
+ // translate the string ranges we get from the joiners back into cell ranges
107
+ // for use when rendering
108
+ let rangeStartColumn = 0;
109
+ let currentStringIndex = 0;
110
+ let rangeStartStringIndex = 0;
111
+ let rangeAttrFG = line.getFg(0);
112
+ let rangeAttrBG = line.getBg(0);
113
+
114
+ for (let x = 0; x < line.getTrimmedLength(); x++) {
115
+ line.loadCell(x, this._workCell);
116
+
117
+ if (this._workCell.getWidth() === 0) {
118
+ // If this character is of width 0, skip it.
119
+ continue;
120
+ }
121
+
122
+ // End of range
123
+ if (this._workCell.fg !== rangeAttrFG || this._workCell.bg !== rangeAttrBG) {
124
+ // If we ended up with a sequence of more than one character,
125
+ // look for ranges to join.
126
+ if (x - rangeStartColumn > 1) {
127
+ const joinedRanges = this._getJoinedRanges(
128
+ lineStr,
129
+ rangeStartStringIndex,
130
+ currentStringIndex,
131
+ line,
132
+ rangeStartColumn
133
+ );
134
+ for (let i = 0; i < joinedRanges.length; i++) {
135
+ ranges.push(joinedRanges[i]);
136
+ }
137
+ }
138
+
139
+ // Reset our markers for a new range.
140
+ rangeStartColumn = x;
141
+ rangeStartStringIndex = currentStringIndex;
142
+ rangeAttrFG = this._workCell.fg;
143
+ rangeAttrBG = this._workCell.bg;
144
+ }
145
+
146
+ currentStringIndex += this._workCell.getChars().length || WHITESPACE_CELL_CHAR.length;
147
+ }
148
+
149
+ // Process any trailing ranges.
150
+ if (this._bufferService.cols - rangeStartColumn > 1) {
151
+ const joinedRanges = this._getJoinedRanges(
152
+ lineStr,
153
+ rangeStartStringIndex,
154
+ currentStringIndex,
155
+ line,
156
+ rangeStartColumn
157
+ );
158
+ for (let i = 0; i < joinedRanges.length; i++) {
159
+ ranges.push(joinedRanges[i]);
160
+ }
161
+ }
162
+
163
+ return ranges;
164
+ }
165
+
166
+ /**
167
+ * Given a segment of a line of text, find all ranges of text that should be
168
+ * joined in a single rendering unit. Ranges are internally converted to
169
+ * column ranges, rather than string ranges.
170
+ * @param line String representation of the full line of text
171
+ * @param startIndex Start position of the range to search in the string (inclusive)
172
+ * @param endIndex End position of the range to search in the string (exclusive)
173
+ */
174
+ private _getJoinedRanges(line: string, startIndex: number, endIndex: number, lineData: IBufferLine, startCol: number): [number, number][] {
175
+ const text = line.substring(startIndex, endIndex);
176
+ // At this point we already know that there is at least one joiner so
177
+ // we can just pull its value and assign it directly rather than
178
+ // merging it into an empty array, which incurs unnecessary writes.
179
+ let allJoinedRanges: [number, number][] = [];
180
+ try {
181
+ allJoinedRanges = this._characterJoiners[0].handler(text);
182
+ } catch (error) {
183
+ console.error(error);
184
+ }
185
+ for (let i = 1; i < this._characterJoiners.length; i++) {
186
+ // We merge any overlapping ranges across the different joiners
187
+ try {
188
+ const joinerRanges = this._characterJoiners[i].handler(text);
189
+ for (let j = 0; j < joinerRanges.length; j++) {
190
+ CharacterJoinerService._mergeRanges(allJoinedRanges, joinerRanges[j]);
191
+ }
192
+ } catch (error) {
193
+ console.error(error);
194
+ }
195
+ }
196
+ this._stringRangesToCellRanges(allJoinedRanges, lineData, startCol);
197
+ return allJoinedRanges;
198
+ }
199
+
200
+ /**
201
+ * Modifies the provided ranges in-place to adjust for variations between
202
+ * string length and cell width so that the range represents a cell range,
203
+ * rather than the string range the joiner provides.
204
+ * @param ranges String ranges containing start (inclusive) and end (exclusive) index
205
+ * @param line Cell data for the relevant line in the terminal
206
+ * @param startCol Offset within the line to start from
207
+ */
208
+ private _stringRangesToCellRanges(ranges: [number, number][], line: IBufferLine, startCol: number): void {
209
+ let currentRangeIndex = 0;
210
+ let currentRangeStarted = false;
211
+ let currentStringIndex = 0;
212
+ let currentRange = ranges[currentRangeIndex];
213
+
214
+ // If we got through all of the ranges, stop searching
215
+ if (!currentRange) {
216
+ return;
217
+ }
218
+
219
+ for (let x = startCol; x < this._bufferService.cols; x++) {
220
+ const width = line.getWidth(x);
221
+ const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length;
222
+
223
+ // We skip zero-width characters when creating the string to join the text
224
+ // so we do the same here
225
+ if (width === 0) {
226
+ continue;
227
+ }
228
+
229
+ // Adjust the start of the range
230
+ if (!currentRangeStarted && currentRange[0] <= currentStringIndex) {
231
+ currentRange[0] = x;
232
+ currentRangeStarted = true;
233
+ }
234
+
235
+ // Adjust the end of the range
236
+ if (currentRange[1] <= currentStringIndex) {
237
+ currentRange[1] = x;
238
+
239
+ // We're finished with this range, so we move to the next one
240
+ currentRange = ranges[++currentRangeIndex];
241
+
242
+ // If there are no more ranges left, stop searching
243
+ if (!currentRange) {
244
+ break;
245
+ }
246
+
247
+ // Ranges can be on adjacent characters. Because the end index of the
248
+ // ranges are exclusive, this means that the index for the start of a
249
+ // range can be the same as the end index of the previous range. To
250
+ // account for the start of the next range, we check here just in case.
251
+ if (currentRange[0] <= currentStringIndex) {
252
+ currentRange[0] = x;
253
+ currentRangeStarted = true;
254
+ } else {
255
+ currentRangeStarted = false;
256
+ }
257
+ }
258
+
259
+ // Adjust the string index based on the character length to line up with
260
+ // the column adjustment
261
+ currentStringIndex += length;
262
+ }
263
+
264
+ // If there is still a range left at the end, it must extend all the way to
265
+ // the end of the line.
266
+ if (currentRange) {
267
+ currentRange[1] = this._bufferService.cols;
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Merges the range defined by the provided start and end into the list of
273
+ * existing ranges. The merge is done in place on the existing range for
274
+ * performance and is also returned.
275
+ * @param ranges Existing range list
276
+ * @param newRange Tuple of two numbers representing the new range to merge in.
277
+ * @returns The ranges input with the new range merged in place
278
+ */
279
+ private static _mergeRanges(ranges: [number, number][], newRange: [number, number]): [number, number][] {
280
+ let inRange = false;
281
+ for (let i = 0; i < ranges.length; i++) {
282
+ const range = ranges[i];
283
+ if (!inRange) {
284
+ if (newRange[1] <= range[0]) {
285
+ // Case 1: New range is before the search range
286
+ ranges.splice(i, 0, newRange);
287
+ return ranges;
288
+ }
289
+
290
+ if (newRange[1] <= range[1]) {
291
+ // Case 2: New range is either wholly contained within the
292
+ // search range or overlaps with the front of it
293
+ range[0] = Math.min(newRange[0], range[0]);
294
+ return ranges;
295
+ }
296
+
297
+ if (newRange[0] < range[1]) {
298
+ // Case 3: New range either wholly contains the search range
299
+ // or overlaps with the end of it
300
+ range[0] = Math.min(newRange[0], range[0]);
301
+ inRange = true;
302
+ }
303
+
304
+ // Case 4: New range starts after the search range
305
+ continue;
306
+ } else {
307
+ if (newRange[1] <= range[0]) {
308
+ // Case 5: New range extends from previous range but doesn't
309
+ // reach the current one
310
+ ranges[i - 1][1] = newRange[1];
311
+ return ranges;
312
+ }
313
+
314
+ if (newRange[1] <= range[1]) {
315
+ // Case 6: New range extends from prvious range into the
316
+ // current range
317
+ ranges[i - 1][1] = Math.max(newRange[1], range[1]);
318
+ ranges.splice(i, 1);
319
+ return ranges;
320
+ }
321
+
322
+ // Case 7: New range extends from previous range past the
323
+ // end of the current range
324
+ ranges.splice(i, 1);
325
+ i--;
326
+ }
327
+ }
328
+
329
+ if (inRange) {
330
+ // Case 8: New range extends past the last existing range
331
+ ranges[ranges.length - 1][1] = newRange[1];
332
+ } else {
333
+ // Case 9: New range starts after the last existing range
334
+ ranges.push(newRange);
335
+ }
336
+
337
+ return ranges;
338
+ }
339
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
7
+ import { ICoreBrowserService } from './Services';
8
+ import { EventEmitter, forwardEvent } from 'common/EventEmitter';
9
+ import { addDisposableDomListener } from 'browser/Lifecycle';
10
+
11
+ export class CoreBrowserService extends Disposable implements ICoreBrowserService {
12
+ public serviceBrand: undefined;
13
+
14
+ private _isFocused = false;
15
+ private _cachedIsFocused: boolean | undefined = undefined;
16
+ private _screenDprMonitor = new ScreenDprMonitor(this._window);
17
+
18
+ private readonly _onDprChange = this.register(new EventEmitter<number>());
19
+ public readonly onDprChange = this._onDprChange.event;
20
+ private readonly _onWindowChange = this.register(new EventEmitter<Window & typeof globalThis>());
21
+ public readonly onWindowChange = this._onWindowChange.event;
22
+
23
+ constructor(
24
+ private _textarea: HTMLTextAreaElement,
25
+ private _window: Window & typeof globalThis,
26
+ public readonly mainDocument: Document
27
+ ) {
28
+ super();
29
+
30
+ // Monitor device pixel ratio
31
+ this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
32
+ this.register(forwardEvent(this._screenDprMonitor.onDprChange, this._onDprChange));
33
+
34
+ this._textarea.addEventListener('focus', () => this._isFocused = true);
35
+ this._textarea.addEventListener('blur', () => this._isFocused = false);
36
+ }
37
+
38
+ public get window(): Window & typeof globalThis {
39
+ return this._window;
40
+ }
41
+
42
+ public set window(value: Window & typeof globalThis) {
43
+ if (this._window !== value) {
44
+ this._window = value;
45
+ this._onWindowChange.fire(this._window);
46
+ }
47
+ }
48
+
49
+ public get dpr(): number {
50
+ return this.window.devicePixelRatio;
51
+ }
52
+
53
+ public get isFocused(): boolean {
54
+ if (this._cachedIsFocused === undefined) {
55
+ this._cachedIsFocused = this._isFocused && this._textarea.ownerDocument.hasFocus();
56
+ queueMicrotask(() => this._cachedIsFocused = undefined);
57
+ }
58
+ return this._cachedIsFocused;
59
+ }
60
+ }
61
+
62
+
63
+ /**
64
+ * The screen device pixel ratio monitor allows listening for when the
65
+ * window.devicePixelRatio value changes. This is done not with polling but with
66
+ * the use of window.matchMedia to watch media queries. When the event fires,
67
+ * the listener will be reattached using a different media query to ensure that
68
+ * any further changes will register.
69
+ *
70
+ * The listener should fire on both window zoom changes and switching to a
71
+ * monitor with a different DPI.
72
+ */
73
+ class ScreenDprMonitor extends Disposable {
74
+ private _currentDevicePixelRatio: number;
75
+ private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
76
+ private _resolutionMediaMatchList: MediaQueryList | undefined;
77
+ private _windowResizeListener = this.register(new MutableDisposable());
78
+
79
+ private readonly _onDprChange = this.register(new EventEmitter<number>());
80
+ public readonly onDprChange = this._onDprChange.event;
81
+
82
+ constructor(private _parentWindow: Window) {
83
+ super();
84
+
85
+ // Initialize listener and dpr value
86
+ this._outerListener = () => this._setDprAndFireIfDiffers();
87
+ this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
88
+ this._updateDpr();
89
+
90
+ // Monitor active window resize
91
+ this._setWindowResizeListener();
92
+
93
+ // Setup additional disposables
94
+ this.register(toDisposable(() => this.clearListener()));
95
+ }
96
+
97
+
98
+ public setWindow(parentWindow: Window): void {
99
+ this._parentWindow = parentWindow;
100
+ this._setWindowResizeListener();
101
+ this._setDprAndFireIfDiffers();
102
+ }
103
+
104
+ private _setWindowResizeListener(): void {
105
+ this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers());
106
+ }
107
+
108
+ private _setDprAndFireIfDiffers(): void {
109
+ if (this._parentWindow.devicePixelRatio !== this._currentDevicePixelRatio) {
110
+ this._onDprChange.fire(this._parentWindow.devicePixelRatio);
111
+ }
112
+ this._updateDpr();
113
+ }
114
+
115
+ private _updateDpr(): void {
116
+ if (!this._outerListener) {
117
+ return;
118
+ }
119
+
120
+ // Clear listeners for old DPR
121
+ this._resolutionMediaMatchList?.removeListener(this._outerListener);
122
+
123
+ // Add listeners for new DPR
124
+ this._currentDevicePixelRatio = this._parentWindow.devicePixelRatio;
125
+ this._resolutionMediaMatchList = this._parentWindow.matchMedia(`screen and (resolution: ${this._parentWindow.devicePixelRatio}dppx)`);
126
+ this._resolutionMediaMatchList.addListener(this._outerListener);
127
+ }
128
+
129
+ public clearListener(): void {
130
+ if (!this._resolutionMediaMatchList || !this._outerListener) {
131
+ return;
132
+ }
133
+ this._resolutionMediaMatchList.removeListener(this._outerListener);
134
+ this._resolutionMediaMatchList = undefined;
135
+ this._outerListener = undefined;
136
+ }
137
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Copyright (c) 2017 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { ICharSizeService, IRenderService, IMouseService } from './Services';
7
+ import { getCoords, getCoordsRelativeToElement } from 'browser/input/Mouse';
8
+
9
+ export class MouseService implements IMouseService {
10
+ public serviceBrand: undefined;
11
+
12
+ constructor(
13
+ @IRenderService private readonly _renderService: IRenderService,
14
+ @ICharSizeService private readonly _charSizeService: ICharSizeService
15
+ ) {
16
+ }
17
+
18
+ public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {
19
+ return getCoords(
20
+ window,
21
+ event,
22
+ element,
23
+ colCount,
24
+ rowCount,
25
+ this._charSizeService.hasValidSize,
26
+ this._renderService.dimensions.css.cell.width,
27
+ this._renderService.dimensions.css.cell.height,
28
+ isSelection
29
+ );
30
+ }
31
+
32
+ public getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined {
33
+ const coords = getCoordsRelativeToElement(window, event, element);
34
+ if (!this._charSizeService.hasValidSize) {
35
+ return undefined;
36
+ }
37
+ coords[0] = Math.min(Math.max(coords[0], 0), this._renderService.dimensions.css.canvas.width - 1);
38
+ coords[1] = Math.min(Math.max(coords[1], 0), this._renderService.dimensions.css.canvas.height - 1);
39
+ return {
40
+ col: Math.floor(coords[0] / this._renderService.dimensions.css.cell.width),
41
+ row: Math.floor(coords[1] / this._renderService.dimensions.css.cell.height),
42
+ x: Math.floor(coords[0]),
43
+ y: Math.floor(coords[1])
44
+ };
45
+ }
46
+ }