@xterm/xterm 5.6.0-beta.43 → 5.6.0-beta.44

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 (82) hide show
  1. package/css/xterm.css +65 -4
  2. package/lib/xterm.js +1 -1
  3. package/lib/xterm.js.map +1 -1
  4. package/lib/xterm.mjs +34 -7
  5. package/lib/xterm.mjs.map +4 -4
  6. package/package.json +2 -2
  7. package/src/browser/CoreBrowserTerminal.ts +53 -68
  8. package/src/browser/Types.ts +4 -1
  9. package/src/browser/Viewport.ts +142 -370
  10. package/src/browser/decorations/OverviewRulerRenderer.ts +25 -35
  11. package/src/browser/renderer/shared/CharAtlasUtils.ts +4 -0
  12. package/src/browser/services/ThemeService.ts +10 -1
  13. package/src/browser/shared/Constants.ts +8 -0
  14. package/src/common/CoreTerminal.ts +7 -13
  15. package/src/common/Types.ts +0 -6
  16. package/src/common/services/BufferService.ts +2 -2
  17. package/src/common/services/CoreMouseService.ts +2 -0
  18. package/src/common/services/Services.ts +10 -3
  19. package/src/vs/base/browser/browser.ts +141 -0
  20. package/src/vs/base/browser/canIUse.ts +49 -0
  21. package/src/vs/base/browser/dom.ts +2369 -0
  22. package/src/vs/base/browser/fastDomNode.ts +316 -0
  23. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  24. package/src/vs/base/browser/iframe.ts +135 -0
  25. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  26. package/src/vs/base/browser/mouseEvent.ts +229 -0
  27. package/src/vs/base/browser/touch.ts +372 -0
  28. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  29. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  30. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +718 -0
  31. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  32. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  33. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  34. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  35. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  36. package/src/vs/base/browser/ui/widget.ts +57 -0
  37. package/src/vs/base/browser/window.ts +14 -0
  38. package/src/vs/base/common/arrays.ts +887 -0
  39. package/src/vs/base/common/arraysFind.ts +202 -0
  40. package/src/vs/base/common/assert.ts +71 -0
  41. package/src/vs/base/common/async.ts +1992 -0
  42. package/src/vs/base/common/cancellation.ts +148 -0
  43. package/src/vs/base/common/charCode.ts +450 -0
  44. package/src/vs/base/common/collections.ts +140 -0
  45. package/src/vs/base/common/decorators.ts +130 -0
  46. package/src/vs/base/common/equals.ts +146 -0
  47. package/src/vs/base/common/errors.ts +303 -0
  48. package/src/vs/base/common/event.ts +1762 -0
  49. package/src/vs/base/common/functional.ts +32 -0
  50. package/src/vs/base/common/hash.ts +316 -0
  51. package/src/vs/base/common/iterator.ts +159 -0
  52. package/src/vs/base/common/keyCodes.ts +526 -0
  53. package/src/vs/base/common/keybindings.ts +284 -0
  54. package/src/vs/base/common/lazy.ts +47 -0
  55. package/src/vs/base/common/lifecycle.ts +801 -0
  56. package/src/vs/base/common/linkedList.ts +142 -0
  57. package/src/vs/base/common/map.ts +202 -0
  58. package/src/vs/base/common/numbers.ts +98 -0
  59. package/src/vs/base/common/observable.ts +76 -0
  60. package/src/vs/base/common/observableInternal/api.ts +31 -0
  61. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  62. package/src/vs/base/common/observableInternal/base.ts +489 -0
  63. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  64. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  65. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  66. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  67. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  68. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  69. package/src/vs/base/common/platform.ts +281 -0
  70. package/src/vs/base/common/scrollable.ts +522 -0
  71. package/src/vs/base/common/sequence.ts +34 -0
  72. package/src/vs/base/common/stopwatch.ts +43 -0
  73. package/src/vs/base/common/strings.ts +557 -0
  74. package/src/vs/base/common/symbols.ts +9 -0
  75. package/src/vs/base/common/uint.ts +59 -0
  76. package/src/vs/patches/nls.ts +90 -0
  77. package/src/vs/typings/base-common.d.ts +20 -0
  78. package/src/vs/typings/require.d.ts +42 -0
  79. package/src/vs/typings/thenable.d.ts +12 -0
  80. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  81. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  82. package/typings/xterm.d.ts +25 -1
@@ -4,10 +4,14 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
 
6
6
  import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
7
- import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
7
+ import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
8
8
  import { Disposable, toDisposable } from 'common/Lifecycle';
9
9
  import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
10
10
 
11
+ const enum Constants {
12
+ OVERVIEW_RULER_BORDER_WIDTH = 1
13
+ }
14
+
11
15
  // Helper objects to avoid excessive calculation and garbage collection during rendering. These are
12
16
  // static values for each render and can be accessed using the decoration position as the key.
13
17
  const drawHeight = {
@@ -51,6 +55,7 @@ export class OverviewRulerRenderer extends Disposable {
51
55
  @IDecorationService private readonly _decorationService: IDecorationService,
52
56
  @IRenderService private readonly _renderService: IRenderService,
53
57
  @IOptionsService private readonly _optionsService: IOptionsService,
58
+ @IThemeService private readonly _themeService: IThemeService,
54
59
  @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
55
60
  ) {
56
61
  super();
@@ -58,33 +63,18 @@ export class OverviewRulerRenderer extends Disposable {
58
63
  this._canvas.classList.add('xterm-decoration-overview-ruler');
59
64
  this._refreshCanvasDimensions();
60
65
  this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
66
+ this.register(toDisposable(() => this._canvas?.remove()));
67
+
61
68
  const ctx = this._canvas.getContext('2d');
62
69
  if (!ctx) {
63
70
  throw new Error('Ctx cannot be null');
64
71
  } else {
65
72
  this._ctx = ctx;
66
73
  }
67
- this._registerDecorationListeners();
68
- this._registerBufferChangeListeners();
69
- this._registerDimensionChangeListeners();
70
- this.register(toDisposable(() => {
71
- this._canvas?.remove();
72
- }));
73
- }
74
74
 
75
- /**
76
- * On decoration add or remove, redraw
77
- */
78
- private _registerDecorationListeners(): void {
79
75
  this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
80
76
  this.register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true)));
81
- }
82
77
 
83
- /**
84
- * On buffer change, redraw
85
- * and hide the canvas if the alt buffer is active
86
- */
87
- private _registerBufferChangeListeners(): void {
88
78
  this.register(this._renderService.onRenderedViewportChange(() => this._queueRefresh()));
89
79
  this.register(this._bufferService.buffers.onBufferActivate(() => {
90
80
  this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block';
@@ -95,31 +85,25 @@ export class OverviewRulerRenderer extends Disposable {
95
85
  this._refreshColorZonePadding();
96
86
  }
97
87
  }));
98
- }
99
- /**
100
- * On dimension change, update canvas dimensions
101
- * and then redraw
102
- */
103
- private _registerDimensionChangeListeners(): void {
104
- // container height changed
88
+
89
+ // Container height changed
105
90
  this.register(this._renderService.onRender((): void => {
106
91
  if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
107
92
  this._queueRefresh(true);
108
93
  this._containerHeight = this._screenElement.clientHeight;
109
94
  }
110
95
  }));
111
- // overview ruler width changed
112
- this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
113
- // device pixel ratio changed
96
+
114
97
  this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
115
- // set the canvas dimensions
98
+ this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
99
+ this.register(this._themeService.onChangeColors(() => this._queueRefresh()));
116
100
  this._queueRefresh(true);
117
101
  }
118
102
 
119
103
  private _refreshDrawConstants(): void {
120
104
  // width
121
- const outerWidth = Math.floor(this._canvas.width / 3);
122
- const innerWidth = Math.ceil(this._canvas.width / 3);
105
+ const outerWidth = Math.floor((this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH) / 3);
106
+ const innerWidth = Math.ceil((this._canvas.width - Constants.OVERVIEW_RULER_BORDER_WIDTH) / 3);
123
107
  drawWidth.full = this._canvas.width;
124
108
  drawWidth.left = outerWidth;
125
109
  drawWidth.center = innerWidth;
@@ -127,10 +111,10 @@ export class OverviewRulerRenderer extends Disposable {
127
111
  // height
128
112
  this._refreshDrawHeightConstants();
129
113
  // x
130
- drawX.full = 0;
131
- drawX.left = 0;
132
- drawX.center = drawWidth.left;
133
- drawX.right = drawWidth.left + drawWidth.center;
114
+ drawX.full = Constants.OVERVIEW_RULER_BORDER_WIDTH;
115
+ drawX.left = Constants.OVERVIEW_RULER_BORDER_WIDTH;
116
+ drawX.center = Constants.OVERVIEW_RULER_BORDER_WIDTH + drawWidth.left;
117
+ drawX.right = Constants.OVERVIEW_RULER_BORDER_WIDTH + drawWidth.left + drawWidth.center;
134
118
  }
135
119
 
136
120
  private _refreshDrawHeightConstants(): void {
@@ -173,6 +157,7 @@ export class OverviewRulerRenderer extends Disposable {
173
157
  this._colorZoneStore.addDecoration(decoration);
174
158
  }
175
159
  this._ctx.lineWidth = 1;
160
+ this._renderRulerOutline();
176
161
  const zones = this._colorZoneStore.zones;
177
162
  for (const zone of zones) {
178
163
  if (zone.position !== 'full') {
@@ -188,6 +173,11 @@ export class OverviewRulerRenderer extends Disposable {
188
173
  this._shouldUpdateAnchor = false;
189
174
  }
190
175
 
176
+ private _renderRulerOutline(): void {
177
+ this._ctx.fillStyle = this._themeService.colors.overviewRulerBorder.css;
178
+ this._ctx.fillRect(0, 0, Constants.OVERVIEW_RULER_BORDER_WIDTH, this._canvas.height);
179
+ }
180
+
191
181
  private _renderColorZone(zone: IColorZone): void {
192
182
  this._ctx.fillStyle = zone.color;
193
183
  this._ctx.fillRect(
@@ -21,6 +21,10 @@ export function generateConfig(deviceCellWidth: number, deviceCellHeight: number
21
21
  selectionBackgroundOpaque: NULL_COLOR,
22
22
  selectionInactiveBackgroundTransparent: NULL_COLOR,
23
23
  selectionInactiveBackgroundOpaque: NULL_COLOR,
24
+ overviewRulerBorder: NULL_COLOR,
25
+ scrollbarSliderBackground: NULL_COLOR,
26
+ scrollbarSliderHoverBackground: NULL_COLOR,
27
+ scrollbarSliderActiveBackground: NULL_COLOR,
24
28
  // For the static char atlas, we only use the first 16 colors, but we need all 256 for the
25
29
  // dynamic character atlas.
26
30
  ansi: colors.ansi.slice(),
@@ -23,11 +23,12 @@ interface IRestoreColorSet {
23
23
  const DEFAULT_FOREGROUND = css.toColor('#ffffff');
24
24
  const DEFAULT_BACKGROUND = css.toColor('#000000');
25
25
  const DEFAULT_CURSOR = css.toColor('#ffffff');
26
- const DEFAULT_CURSOR_ACCENT = css.toColor('#000000');
26
+ const DEFAULT_CURSOR_ACCENT = DEFAULT_BACKGROUND;
27
27
  const DEFAULT_SELECTION = {
28
28
  css: 'rgba(255, 255, 255, 0.3)',
29
29
  rgba: 0xFFFFFF4D
30
30
  };
31
+ const DEFAULT_OVERVIEW_RULER_BORDER = DEFAULT_FOREGROUND;
31
32
 
32
33
  export class ThemeService extends Disposable implements IThemeService {
33
34
  public serviceBrand: undefined;
@@ -57,6 +58,10 @@ export class ThemeService extends Disposable implements IThemeService {
57
58
  selectionBackgroundOpaque: color.blend(DEFAULT_BACKGROUND, DEFAULT_SELECTION),
58
59
  selectionInactiveBackgroundTransparent: DEFAULT_SELECTION,
59
60
  selectionInactiveBackgroundOpaque: color.blend(DEFAULT_BACKGROUND, DEFAULT_SELECTION),
61
+ scrollbarSliderBackground: color.opacity(DEFAULT_FOREGROUND, 0.2),
62
+ scrollbarSliderHoverBackground: color.opacity(DEFAULT_FOREGROUND, 0.4),
63
+ scrollbarSliderActiveBackground: color.opacity(DEFAULT_FOREGROUND, 0.5),
64
+ overviewRulerBorder: DEFAULT_FOREGROUND,
60
65
  ansi: DEFAULT_ANSI_COLORS.slice(),
61
66
  contrastCache: this._contrastCache,
62
67
  halfContrastCache: this._halfContrastCache
@@ -100,6 +105,10 @@ export class ThemeService extends Disposable implements IThemeService {
100
105
  const opacity = 0.3;
101
106
  colors.selectionInactiveBackgroundTransparent = color.opacity(colors.selectionInactiveBackgroundTransparent, opacity);
102
107
  }
108
+ colors.scrollbarSliderBackground = parseColor(theme.scrollbarSliderBackground, color.opacity(colors.foreground, 0.2));
109
+ colors.scrollbarSliderHoverBackground = parseColor(theme.scrollbarSliderHoverBackground, color.opacity(colors.foreground, 0.4));
110
+ colors.scrollbarSliderActiveBackground = parseColor(theme.scrollbarSliderActiveBackground, color.opacity(colors.foreground, 0.5));
111
+ colors.overviewRulerBorder = parseColor(theme.overviewRulerBorder, DEFAULT_OVERVIEW_RULER_BORDER);
103
112
  colors.ansi = DEFAULT_ANSI_COLORS.slice();
104
113
  colors.ansi[0] = parseColor(theme.black, DEFAULT_ANSI_COLORS[0]);
105
114
  colors.ansi[1] = parseColor(theme.red, DEFAULT_ANSI_COLORS[1]);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2024 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export const enum ViewportConstants {
7
+ DEFAULT_SCROLL_BAR_WIDTH = 14
8
+ }
@@ -27,7 +27,7 @@ import { InstantiationService } from 'common/services/InstantiationService';
27
27
  import { LogService } from 'common/services/LogService';
28
28
  import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
29
29
  import { OptionsService } from 'common/services/OptionsService';
30
- import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent, ScrollSource } from 'common/Types';
30
+ import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent } from 'common/Types';
31
31
  import { CoreService } from 'common/services/CoreService';
32
32
  import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
33
33
  import { CoreMouseService } from 'common/services/CoreMouseService';
@@ -130,18 +130,13 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
130
130
  this.register(forwardEvent(this._bufferService.onResize, this._onResize));
131
131
  this.register(forwardEvent(this.coreService.onData, this._onData));
132
132
  this.register(forwardEvent(this.coreService.onBinary, this._onBinary));
133
- this.register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom()));
133
+ this.register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom(true)));
134
134
  this.register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput()));
135
135
  this.register(this.optionsService.onMultipleOptionChange(['windowsMode', 'windowsPty'], () => this._handleWindowsPtyOptionChange()));
136
- this.register(this._bufferService.onScroll(event => {
137
- this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL });
136
+ this.register(this._bufferService.onScroll(() => {
137
+ this._onScroll.fire({ position: this._bufferService.buffer.ydisp });
138
138
  this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
139
139
  }));
140
- this.register(this._inputHandler.onScroll(event => {
141
- this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL });
142
- this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
143
- }));
144
-
145
140
  // Setup WriteBuffer
146
141
  this._writeBuffer = this.register(new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult)));
147
142
  this.register(forwardEvent(this._writeBuffer.onWriteParsed, this._onWriteParsed));
@@ -198,10 +193,9 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
198
193
  * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used to avoid
199
194
  * unwanted events being handled by the viewport when the event was triggered from the viewport
200
195
  * originally.
201
- * @param source Which component the event came from.
202
196
  */
203
- public scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void {
204
- this._bufferService.scrollLines(disp, suppressScrollEvent, source);
197
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
198
+ this._bufferService.scrollLines(disp, suppressScrollEvent);
205
199
  }
206
200
 
207
201
  public scrollPages(pageCount: number): void {
@@ -212,7 +206,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
212
206
  this.scrollLines(-this._bufferService.buffer.ydisp);
213
207
  }
214
208
 
215
- public scrollToBottom(): void {
209
+ public scrollToBottom(disableSmoothScroll?: boolean): void {
216
210
  this.scrollLines(this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
217
211
  }
218
212
 
@@ -60,12 +60,6 @@ export interface IKeyboardEvent {
60
60
 
61
61
  export interface IScrollEvent {
62
62
  position: number;
63
- source: ScrollSource;
64
- }
65
-
66
- export const enum ScrollSource {
67
- TERMINAL,
68
- VIEWPORT,
69
63
  }
70
64
 
71
65
  export interface ICircularList<T> {
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { EventEmitter } from 'common/EventEmitter';
7
7
  import { Disposable } from 'common/Lifecycle';
8
- import { IAttributeData, IBufferLine, ScrollSource } from 'common/Types';
8
+ import { IAttributeData, IBufferLine } from 'common/Types';
9
9
  import { BufferSet } from 'common/buffer/BufferSet';
10
10
  import { IBuffer, IBufferSet } from 'common/buffer/Types';
11
11
  import { IBufferService, IOptionsService } from 'common/services/Services';
@@ -125,7 +125,7 @@ export class BufferService extends Disposable implements IBufferService {
125
125
  * to avoid unwanted events being handled by the viewport when the event was triggered from the
126
126
  * viewport originally.
127
127
  */
128
- public scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void {
128
+ public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
129
129
  const buffer = this.buffer;
130
130
  if (disp < 0) {
131
131
  if (buffer.ydisp === 0) {
@@ -167,6 +167,8 @@ const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
167
167
  * To send a mouse event call `triggerMouseEvent`.
168
168
  */
169
169
  export class CoreMouseService extends Disposable implements ICoreMouseService {
170
+ public serviceBrand: any;
171
+
170
172
  private _protocols: { [name: string]: ICoreMouseProtocol } = {};
171
173
  private _encodings: { [name: string]: CoreMouseEncoding } = {};
172
174
  private _activeProtocol: string = '';
@@ -3,11 +3,11 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
+ import { IDecoration, IDecorationOptions, ILinkHandler, ILogger, IWindowsPty } from '@xterm/xterm';
6
7
  import { IEvent, IEventEmitter } from 'common/EventEmitter';
8
+ import { CoreMouseEncoding, CoreMouseEventType, CursorInactiveStyle, CursorStyle, IAttributeData, ICharset, IColor, ICoreMouseEvent, ICoreMouseProtocol, IDecPrivateModes, IDisposable, IModes, IOscLinkData, IWindowOptions } from 'common/Types';
7
9
  import { IBuffer, IBufferSet } from 'common/buffer/Types';
8
- import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes, IAttributeData, ScrollSource, IDisposable, IColor, CursorStyle, CursorInactiveStyle, IOscLinkData } from 'common/Types';
9
10
  import { createDecorator } from 'common/services/ServiceRegistry';
10
- import { IDecorationOptions, IDecoration, ILinkHandler, IWindowsPty, ILogger } from '@xterm/xterm';
11
11
 
12
12
  export const IBufferService = createDecorator<IBufferService>('BufferService');
13
13
  export interface IBufferService {
@@ -21,13 +21,15 @@ export interface IBufferService {
21
21
  onResize: IEvent<{ cols: number, rows: number }>;
22
22
  onScroll: IEvent<number>;
23
23
  scroll(eraseAttr: IAttributeData, isWrapped?: boolean): void;
24
- scrollLines(disp: number, suppressScrollEvent?: boolean, source?: ScrollSource): void;
24
+ scrollLines(disp: number, suppressScrollEvent?: boolean): void;
25
25
  resize(cols: number, rows: number): void;
26
26
  reset(): void;
27
27
  }
28
28
 
29
29
  export const ICoreMouseService = createDecorator<ICoreMouseService>('CoreMouseService');
30
30
  export interface ICoreMouseService {
31
+ serviceBrand: undefined;
32
+
31
33
  activeProtocol: string;
32
34
  activeEncoding: string;
33
35
  areMouseEventsActive: boolean;
@@ -219,6 +221,7 @@ export interface ITerminalOptions {
219
221
  disableStdin?: boolean;
220
222
  documentOverride?: any | null;
221
223
  drawBoldTextInBrightColors?: boolean;
224
+ /** @deprecated No longer supported */
222
225
  fastScrollModifier?: 'none' | 'alt' | 'ctrl' | 'shift';
223
226
  fastScrollSensitivity?: number;
224
227
  fontSize?: number;
@@ -263,6 +266,10 @@ export interface ITheme {
263
266
  selectionForeground?: string;
264
267
  selectionBackground?: string;
265
268
  selectionInactiveBackground?: string;
269
+ scrollbarSliderBackground?: string;
270
+ scrollbarSliderHoverBackground?: string;
271
+ scrollbarSliderActiveBackground?: string;
272
+ overviewRulerBorder?: string;
266
273
  black?: string;
267
274
  red?: string;
268
275
  green?: string;
@@ -0,0 +1,141 @@
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 { CodeWindow, mainWindow } from 'vs/base/browser/window';
7
+ import { Emitter } from 'vs/base/common/event';
8
+
9
+ class WindowManager {
10
+
11
+ static readonly INSTANCE = new WindowManager();
12
+
13
+ // --- Zoom Level
14
+
15
+ private readonly mapWindowIdToZoomLevel = new Map<number, number>();
16
+
17
+ private readonly _onDidChangeZoomLevel = new Emitter<number>();
18
+ readonly onDidChangeZoomLevel = this._onDidChangeZoomLevel.event;
19
+
20
+ getZoomLevel(targetWindow: Window): number {
21
+ return this.mapWindowIdToZoomLevel.get(this.getWindowId(targetWindow)) ?? 0;
22
+ }
23
+ setZoomLevel(zoomLevel: number, targetWindow: Window): void {
24
+ if (this.getZoomLevel(targetWindow) === zoomLevel) {
25
+ return;
26
+ }
27
+
28
+ const targetWindowId = this.getWindowId(targetWindow);
29
+ this.mapWindowIdToZoomLevel.set(targetWindowId, zoomLevel);
30
+ this._onDidChangeZoomLevel.fire(targetWindowId);
31
+ }
32
+
33
+ // --- Zoom Factor
34
+
35
+ private readonly mapWindowIdToZoomFactor = new Map<number, number>();
36
+
37
+ getZoomFactor(targetWindow: Window): number {
38
+ return this.mapWindowIdToZoomFactor.get(this.getWindowId(targetWindow)) ?? 1;
39
+ }
40
+ setZoomFactor(zoomFactor: number, targetWindow: Window): void {
41
+ this.mapWindowIdToZoomFactor.set(this.getWindowId(targetWindow), zoomFactor);
42
+ }
43
+
44
+ // --- Fullscreen
45
+
46
+ private readonly _onDidChangeFullscreen = new Emitter<number>();
47
+ readonly onDidChangeFullscreen = this._onDidChangeFullscreen.event;
48
+
49
+ private readonly mapWindowIdToFullScreen = new Map<number, boolean>();
50
+
51
+ setFullscreen(fullscreen: boolean, targetWindow: Window): void {
52
+ if (this.isFullscreen(targetWindow) === fullscreen) {
53
+ return;
54
+ }
55
+
56
+ const windowId = this.getWindowId(targetWindow);
57
+ this.mapWindowIdToFullScreen.set(windowId, fullscreen);
58
+ this._onDidChangeFullscreen.fire(windowId);
59
+ }
60
+ isFullscreen(targetWindow: Window): boolean {
61
+ return !!this.mapWindowIdToFullScreen.get(this.getWindowId(targetWindow));
62
+ }
63
+
64
+ private getWindowId(targetWindow: Window): number {
65
+ return (targetWindow as CodeWindow).vscodeWindowId;
66
+ }
67
+ }
68
+
69
+ export function addMatchMediaChangeListener(targetWindow: Window, query: string | MediaQueryList, callback: (this: MediaQueryList, ev: MediaQueryListEvent) => any): void {
70
+ if (typeof query === 'string') {
71
+ query = targetWindow.matchMedia(query);
72
+ }
73
+ query.addEventListener('change', callback);
74
+ }
75
+
76
+ /** A zoom index, e.g. 1, 2, 3 */
77
+ export function setZoomLevel(zoomLevel: number, targetWindow: Window): void {
78
+ WindowManager.INSTANCE.setZoomLevel(zoomLevel, targetWindow);
79
+ }
80
+ export function getZoomLevel(targetWindow: Window): number {
81
+ return WindowManager.INSTANCE.getZoomLevel(targetWindow);
82
+ }
83
+ export const onDidChangeZoomLevel = WindowManager.INSTANCE.onDidChangeZoomLevel;
84
+
85
+ /** The zoom scale for an index, e.g. 1, 1.2, 1.4 */
86
+ export function getZoomFactor(targetWindow: Window): number {
87
+ return WindowManager.INSTANCE.getZoomFactor(targetWindow);
88
+ }
89
+ export function setZoomFactor(zoomFactor: number, targetWindow: Window): void {
90
+ WindowManager.INSTANCE.setZoomFactor(zoomFactor, targetWindow);
91
+ }
92
+
93
+ export function setFullscreen(fullscreen: boolean, targetWindow: Window): void {
94
+ WindowManager.INSTANCE.setFullscreen(fullscreen, targetWindow);
95
+ }
96
+ export function isFullscreen(targetWindow: Window): boolean {
97
+ return WindowManager.INSTANCE.isFullscreen(targetWindow);
98
+ }
99
+ export const onDidChangeFullscreen = WindowManager.INSTANCE.onDidChangeFullscreen;
100
+
101
+ const userAgent = typeof navigator === 'object' ? navigator.userAgent : '';
102
+
103
+ export const isFirefox = (userAgent.indexOf('Firefox') >= 0);
104
+ export const isWebKit = (userAgent.indexOf('AppleWebKit') >= 0);
105
+ export const isChrome = (userAgent.indexOf('Chrome') >= 0);
106
+ export const isSafari = (!isChrome && (userAgent.indexOf('Safari') >= 0));
107
+ export const isWebkitWebView = (!isChrome && !isSafari && isWebKit);
108
+ export const isElectron = (userAgent.indexOf('Electron/') >= 0);
109
+ export const isAndroid = (userAgent.indexOf('Android') >= 0);
110
+
111
+ let standalone = false;
112
+ if (typeof mainWindow.matchMedia === 'function') {
113
+ const standaloneMatchMedia = mainWindow.matchMedia('(display-mode: standalone) or (display-mode: window-controls-overlay)');
114
+ const fullScreenMatchMedia = mainWindow.matchMedia('(display-mode: fullscreen)');
115
+ standalone = standaloneMatchMedia.matches;
116
+ addMatchMediaChangeListener(mainWindow, standaloneMatchMedia, ({ matches }) => {
117
+ // entering fullscreen would change standaloneMatchMedia.matches to false
118
+ // if standalone is true (running as PWA) and entering fullscreen, skip this change
119
+ if (standalone && fullScreenMatchMedia.matches) {
120
+ return;
121
+ }
122
+ // otherwise update standalone (browser to PWA or PWA to browser)
123
+ standalone = matches;
124
+ });
125
+ }
126
+ export function isStandalone(): boolean {
127
+ return standalone;
128
+ }
129
+
130
+ // Visible means that the feature is enabled, not necessarily being rendered
131
+ // e.g. visible is true even in fullscreen mode where the controls are hidden
132
+ // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/visible
133
+ export function isWCOEnabled(): boolean {
134
+ return (navigator as any)?.windowControlsOverlay?.visible;
135
+ }
136
+
137
+ // Returns the bounding rect of the titlebar area if it is supported and defined
138
+ // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/getTitlebarAreaRect
139
+ export function getWCOBoundingRect(): DOMRect | undefined {
140
+ return (navigator as any)?.windowControlsOverlay?.getTitlebarAreaRect();
141
+ }
@@ -0,0 +1,49 @@
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 browser from 'vs/base/browser/browser';
7
+ import { mainWindow } from 'vs/base/browser/window';
8
+ import * as platform from 'vs/base/common/platform';
9
+
10
+ export const enum KeyboardSupport {
11
+ Always,
12
+ FullScreen,
13
+ None
14
+ }
15
+
16
+ const safeNavigator = typeof navigator === 'object' ? navigator : {} as { [key: string]: any };
17
+
18
+ /**
19
+ * Browser feature we can support in current platform, browser and environment.
20
+ */
21
+ export const BrowserFeatures = {
22
+ clipboard: {
23
+ writeText: (
24
+ platform.isNative
25
+ || (document.queryCommandSupported && document.queryCommandSupported('copy'))
26
+ || !!(safeNavigator && safeNavigator.clipboard && safeNavigator.clipboard.writeText)
27
+ ),
28
+ readText: (
29
+ platform.isNative
30
+ || !!(safeNavigator && safeNavigator.clipboard && safeNavigator.clipboard.readText)
31
+ )
32
+ },
33
+ keyboard: (() => {
34
+ if (platform.isNative || browser.isStandalone()) {
35
+ return KeyboardSupport.Always;
36
+ }
37
+
38
+ if ((<any>safeNavigator).keyboard || browser.isSafari) {
39
+ return KeyboardSupport.FullScreen;
40
+ }
41
+
42
+ return KeyboardSupport.None;
43
+ })(),
44
+
45
+ // 'ontouchstart' in window always evaluates to true with typescript's modern typings. This causes `window` to be
46
+ // `never` later in `window.navigator`. That's why we need the explicit `window as Window` cast
47
+ touch: 'ontouchstart' in mainWindow || safeNavigator.maxTouchPoints > 0,
48
+ pointerEvents: mainWindow.PointerEvent && ('ontouchstart' in mainWindow || navigator.maxTouchPoints > 0)
49
+ };