@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,134 @@
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 { ICoreBrowserService, IRenderService } from 'browser/services/Services';
7
+ import { Disposable, toDisposable } from 'common/Lifecycle';
8
+ import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
9
+
10
+ export class BufferDecorationRenderer extends Disposable {
11
+ private readonly _container: HTMLElement;
12
+ private readonly _decorationElements: Map<IInternalDecoration, HTMLElement> = new Map();
13
+
14
+ private _animationFrame: number | undefined;
15
+ private _altBufferIsActive: boolean = false;
16
+ private _dimensionsChanged: boolean = false;
17
+
18
+ constructor(
19
+ private readonly _screenElement: HTMLElement,
20
+ @IBufferService private readonly _bufferService: IBufferService,
21
+ @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
22
+ @IDecorationService private readonly _decorationService: IDecorationService,
23
+ @IRenderService private readonly _renderService: IRenderService
24
+ ) {
25
+ super();
26
+
27
+ this._container = document.createElement('div');
28
+ this._container.classList.add('xterm-decoration-container');
29
+ this._screenElement.appendChild(this._container);
30
+
31
+ this.register(this._renderService.onRenderedViewportChange(() => this._doRefreshDecorations()));
32
+ this.register(this._renderService.onDimensionsChange(() => {
33
+ this._dimensionsChanged = true;
34
+ this._queueRefresh();
35
+ }));
36
+ this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh()));
37
+ this.register(this._bufferService.buffers.onBufferActivate(() => {
38
+ this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt;
39
+ }));
40
+ this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh()));
41
+ this.register(this._decorationService.onDecorationRemoved(decoration => this._removeDecoration(decoration)));
42
+ this.register(toDisposable(() => {
43
+ this._container.remove();
44
+ this._decorationElements.clear();
45
+ }));
46
+ }
47
+
48
+ private _queueRefresh(): void {
49
+ if (this._animationFrame !== undefined) {
50
+ return;
51
+ }
52
+ this._animationFrame = this._renderService.addRefreshCallback(() => {
53
+ this._doRefreshDecorations();
54
+ this._animationFrame = undefined;
55
+ });
56
+ }
57
+
58
+ private _doRefreshDecorations(): void {
59
+ for (const decoration of this._decorationService.decorations) {
60
+ this._renderDecoration(decoration);
61
+ }
62
+ this._dimensionsChanged = false;
63
+ }
64
+
65
+ private _renderDecoration(decoration: IInternalDecoration): void {
66
+ this._refreshStyle(decoration);
67
+ if (this._dimensionsChanged) {
68
+ this._refreshXPosition(decoration);
69
+ }
70
+ }
71
+
72
+ private _createElement(decoration: IInternalDecoration): HTMLElement {
73
+ const element = this._coreBrowserService.mainDocument.createElement('div');
74
+ element.classList.add('xterm-decoration');
75
+ element.classList.toggle('xterm-decoration-top-layer', decoration?.options?.layer === 'top');
76
+ element.style.width = `${Math.round((decoration.options.width || 1) * this._renderService.dimensions.css.cell.width)}px`;
77
+ element.style.height = `${(decoration.options.height || 1) * this._renderService.dimensions.css.cell.height}px`;
78
+ element.style.top = `${(decoration.marker.line - this._bufferService.buffers.active.ydisp) * this._renderService.dimensions.css.cell.height}px`;
79
+ element.style.lineHeight = `${this._renderService.dimensions.css.cell.height}px`;
80
+
81
+ const x = decoration.options.x ?? 0;
82
+ if (x && x > this._bufferService.cols) {
83
+ // exceeded the container width, so hide
84
+ element.style.display = 'none';
85
+ }
86
+ this._refreshXPosition(decoration, element);
87
+
88
+ return element;
89
+ }
90
+
91
+ private _refreshStyle(decoration: IInternalDecoration): void {
92
+ const line = decoration.marker.line - this._bufferService.buffers.active.ydisp;
93
+ if (line < 0 || line >= this._bufferService.rows) {
94
+ // outside of viewport
95
+ if (decoration.element) {
96
+ decoration.element.style.display = 'none';
97
+ decoration.onRenderEmitter.fire(decoration.element);
98
+ }
99
+ } else {
100
+ let element = this._decorationElements.get(decoration);
101
+ if (!element) {
102
+ element = this._createElement(decoration);
103
+ decoration.element = element;
104
+ this._decorationElements.set(decoration, element);
105
+ this._container.appendChild(element);
106
+ decoration.onDispose(() => {
107
+ this._decorationElements.delete(decoration);
108
+ element!.remove();
109
+ });
110
+ }
111
+ element.style.top = `${line * this._renderService.dimensions.css.cell.height}px`;
112
+ element.style.display = this._altBufferIsActive ? 'none' : 'block';
113
+ decoration.onRenderEmitter.fire(element);
114
+ }
115
+ }
116
+
117
+ private _refreshXPosition(decoration: IInternalDecoration, element: HTMLElement | undefined = decoration.element): void {
118
+ if (!element) {
119
+ return;
120
+ }
121
+ const x = decoration.options.x ?? 0;
122
+ if ((decoration.options.anchor || 'left') === 'right') {
123
+ element.style.right = x ? `${x * this._renderService.dimensions.css.cell.width}px` : '';
124
+ } else {
125
+ element.style.left = x ? `${x * this._renderService.dimensions.css.cell.width}px` : '';
126
+ }
127
+ }
128
+
129
+ private _removeDecoration(decoration: IInternalDecoration): void {
130
+ this._decorationElements.get(decoration)?.remove();
131
+ this._decorationElements.delete(decoration);
132
+ decoration.dispose();
133
+ }
134
+ }
@@ -0,0 +1,117 @@
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 { IInternalDecoration } from 'common/services/Services';
7
+
8
+ export interface IColorZoneStore {
9
+ readonly zones: IColorZone[];
10
+ clear(): void;
11
+ addDecoration(decoration: IInternalDecoration): void;
12
+ /**
13
+ * Sets the amount of padding in lines that will be added between zones, if new lines intersect
14
+ * the padding they will be merged into the same zone.
15
+ */
16
+ setPadding(padding: { [position: string]: number }): void;
17
+ }
18
+
19
+ export interface IColorZone {
20
+ /** Color in a format supported by canvas' fillStyle. */
21
+ color: string;
22
+ position: 'full' | 'left' | 'center' | 'right' | undefined;
23
+ startBufferLine: number;
24
+ endBufferLine: number;
25
+ }
26
+
27
+ interface IMinimalDecorationForColorZone {
28
+ marker: Pick<IInternalDecoration['marker'], 'line'>;
29
+ options: Pick<IInternalDecoration['options'], 'overviewRulerOptions'>;
30
+ }
31
+
32
+ export class ColorZoneStore implements IColorZoneStore {
33
+ private _zones: IColorZone[] = [];
34
+
35
+ // The zone pool is used to keep zone objects from being freed between clearing the color zone
36
+ // store and fetching the zones. This helps reduce GC pressure since the color zones are
37
+ // accumulated on potentially every scroll event.
38
+ private _zonePool: IColorZone[] = [];
39
+ private _zonePoolIndex = 0;
40
+
41
+ private _linePadding: { [position: string]: number } = {
42
+ full: 0,
43
+ left: 0,
44
+ center: 0,
45
+ right: 0
46
+ };
47
+
48
+ public get zones(): IColorZone[] {
49
+ // Trim the zone pool to free unused memory
50
+ this._zonePool.length = Math.min(this._zonePool.length, this._zones.length);
51
+ return this._zones;
52
+ }
53
+
54
+ public clear(): void {
55
+ this._zones.length = 0;
56
+ this._zonePoolIndex = 0;
57
+ }
58
+
59
+ public addDecoration(decoration: IMinimalDecorationForColorZone): void {
60
+ if (!decoration.options.overviewRulerOptions) {
61
+ return;
62
+ }
63
+ for (const z of this._zones) {
64
+ if (z.color === decoration.options.overviewRulerOptions.color &&
65
+ z.position === decoration.options.overviewRulerOptions.position) {
66
+ if (this._lineIntersectsZone(z, decoration.marker.line)) {
67
+ return;
68
+ }
69
+ if (this._lineAdjacentToZone(z, decoration.marker.line, decoration.options.overviewRulerOptions.position)) {
70
+ this._addLineToZone(z, decoration.marker.line);
71
+ return;
72
+ }
73
+ }
74
+ }
75
+ // Create using zone pool if possible
76
+ if (this._zonePoolIndex < this._zonePool.length) {
77
+ this._zonePool[this._zonePoolIndex].color = decoration.options.overviewRulerOptions.color;
78
+ this._zonePool[this._zonePoolIndex].position = decoration.options.overviewRulerOptions.position;
79
+ this._zonePool[this._zonePoolIndex].startBufferLine = decoration.marker.line;
80
+ this._zonePool[this._zonePoolIndex].endBufferLine = decoration.marker.line;
81
+ this._zones.push(this._zonePool[this._zonePoolIndex++]);
82
+ return;
83
+ }
84
+ // Create
85
+ this._zones.push({
86
+ color: decoration.options.overviewRulerOptions.color,
87
+ position: decoration.options.overviewRulerOptions.position,
88
+ startBufferLine: decoration.marker.line,
89
+ endBufferLine: decoration.marker.line
90
+ });
91
+ this._zonePool.push(this._zones[this._zones.length - 1]);
92
+ this._zonePoolIndex++;
93
+ }
94
+
95
+ public setPadding(padding: { [position: string]: number }): void {
96
+ this._linePadding = padding;
97
+ }
98
+
99
+ private _lineIntersectsZone(zone: IColorZone, line: number): boolean {
100
+ return (
101
+ line >= zone.startBufferLine &&
102
+ line <= zone.endBufferLine
103
+ );
104
+ }
105
+
106
+ private _lineAdjacentToZone(zone: IColorZone, line: number, position: IColorZone['position']): boolean {
107
+ return (
108
+ (line >= zone.startBufferLine - this._linePadding[position || 'full']) &&
109
+ (line <= zone.endBufferLine + this._linePadding[position || 'full'])
110
+ );
111
+ }
112
+
113
+ private _addLineToZone(zone: IColorZone, line: number): void {
114
+ zone.startBufferLine = Math.min(zone.startBufferLine, line);
115
+ zone.endBufferLine = Math.max(zone.endBufferLine, line);
116
+ }
117
+ }
@@ -0,0 +1,218 @@
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 { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
7
+ import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
8
+ import { Disposable, toDisposable } from 'common/Lifecycle';
9
+ import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
10
+
11
+ // Helper objects to avoid excessive calculation and garbage collection during rendering. These are
12
+ // static values for each render and can be accessed using the decoration position as the key.
13
+ const drawHeight = {
14
+ full: 0,
15
+ left: 0,
16
+ center: 0,
17
+ right: 0
18
+ };
19
+ const drawWidth = {
20
+ full: 0,
21
+ left: 0,
22
+ center: 0,
23
+ right: 0
24
+ };
25
+ const drawX = {
26
+ full: 0,
27
+ left: 0,
28
+ center: 0,
29
+ right: 0
30
+ };
31
+
32
+ export class OverviewRulerRenderer extends Disposable {
33
+ private readonly _canvas: HTMLCanvasElement;
34
+ private readonly _ctx: CanvasRenderingContext2D;
35
+ private readonly _colorZoneStore: IColorZoneStore = new ColorZoneStore();
36
+ private get _width(): number {
37
+ return this._optionsService.options.overviewRulerWidth || 0;
38
+ }
39
+ private _animationFrame: number | undefined;
40
+
41
+ private _shouldUpdateDimensions: boolean | undefined = true;
42
+ private _shouldUpdateAnchor: boolean | undefined = true;
43
+ private _lastKnownBufferLength: number = 0;
44
+
45
+ private _containerHeight: number | undefined;
46
+
47
+ constructor(
48
+ private readonly _viewportElement: HTMLElement,
49
+ private readonly _screenElement: HTMLElement,
50
+ @IBufferService private readonly _bufferService: IBufferService,
51
+ @IDecorationService private readonly _decorationService: IDecorationService,
52
+ @IRenderService private readonly _renderService: IRenderService,
53
+ @IOptionsService private readonly _optionsService: IOptionsService,
54
+ @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
55
+ ) {
56
+ super();
57
+ this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
58
+ this._canvas.classList.add('xterm-decoration-overview-ruler');
59
+ this._refreshCanvasDimensions();
60
+ this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
61
+ const ctx = this._canvas.getContext('2d');
62
+ if (!ctx) {
63
+ throw new Error('Ctx cannot be null');
64
+ } else {
65
+ this._ctx = ctx;
66
+ }
67
+ this._registerDecorationListeners();
68
+ this._registerBufferChangeListeners();
69
+ this._registerDimensionChangeListeners();
70
+ this.register(toDisposable(() => {
71
+ this._canvas?.remove();
72
+ }));
73
+ }
74
+
75
+ /**
76
+ * On decoration add or remove, redraw
77
+ */
78
+ private _registerDecorationListeners(): void {
79
+ this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
80
+ this.register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true)));
81
+ }
82
+
83
+ /**
84
+ * On buffer change, redraw
85
+ * and hide the canvas if the alt buffer is active
86
+ */
87
+ private _registerBufferChangeListeners(): void {
88
+ this.register(this._renderService.onRenderedViewportChange(() => this._queueRefresh()));
89
+ this.register(this._bufferService.buffers.onBufferActivate(() => {
90
+ this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block';
91
+ }));
92
+ this.register(this._bufferService.onScroll(() => {
93
+ if (this._lastKnownBufferLength !== this._bufferService.buffers.normal.lines.length) {
94
+ this._refreshDrawHeightConstants();
95
+ this._refreshColorZonePadding();
96
+ }
97
+ }));
98
+ }
99
+ /**
100
+ * On dimension change, update canvas dimensions
101
+ * and then redraw
102
+ */
103
+ private _registerDimensionChangeListeners(): void {
104
+ // container height changed
105
+ this.register(this._renderService.onRender((): void => {
106
+ if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
107
+ this._queueRefresh(true);
108
+ this._containerHeight = this._screenElement.clientHeight;
109
+ }
110
+ }));
111
+ // overview ruler width changed
112
+ this.register(this._optionsService.onSpecificOptionChange('overviewRulerWidth', () => this._queueRefresh(true)));
113
+ // device pixel ratio changed
114
+ this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
115
+ // set the canvas dimensions
116
+ this._queueRefresh(true);
117
+ }
118
+
119
+ private _refreshDrawConstants(): void {
120
+ // width
121
+ const outerWidth = Math.floor(this._canvas.width / 3);
122
+ const innerWidth = Math.ceil(this._canvas.width / 3);
123
+ drawWidth.full = this._canvas.width;
124
+ drawWidth.left = outerWidth;
125
+ drawWidth.center = innerWidth;
126
+ drawWidth.right = outerWidth;
127
+ // height
128
+ this._refreshDrawHeightConstants();
129
+ // x
130
+ drawX.full = 0;
131
+ drawX.left = 0;
132
+ drawX.center = drawWidth.left;
133
+ drawX.right = drawWidth.left + drawWidth.center;
134
+ }
135
+
136
+ private _refreshDrawHeightConstants(): void {
137
+ drawHeight.full = Math.round(2 * this._coreBrowserService.dpr);
138
+ // Calculate actual pixels per line
139
+ const pixelsPerLine = this._canvas.height / this._bufferService.buffer.lines.length;
140
+ // Clamp actual pixels within a range
141
+ const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowserService.dpr);
142
+ drawHeight.left = nonFullHeight;
143
+ drawHeight.center = nonFullHeight;
144
+ drawHeight.right = nonFullHeight;
145
+ }
146
+
147
+ private _refreshColorZonePadding(): void {
148
+ this._colorZoneStore.setPadding({
149
+ full: Math.floor(this._bufferService.buffers.active.lines.length / (this._canvas.height - 1) * drawHeight.full),
150
+ left: Math.floor(this._bufferService.buffers.active.lines.length / (this._canvas.height - 1) * drawHeight.left),
151
+ center: Math.floor(this._bufferService.buffers.active.lines.length / (this._canvas.height - 1) * drawHeight.center),
152
+ right: Math.floor(this._bufferService.buffers.active.lines.length / (this._canvas.height - 1) * drawHeight.right)
153
+ });
154
+ this._lastKnownBufferLength = this._bufferService.buffers.normal.lines.length;
155
+ }
156
+
157
+ private _refreshCanvasDimensions(): void {
158
+ this._canvas.style.width = `${this._width}px`;
159
+ this._canvas.width = Math.round(this._width * this._coreBrowserService.dpr);
160
+ this._canvas.style.height = `${this._screenElement.clientHeight}px`;
161
+ this._canvas.height = Math.round(this._screenElement.clientHeight * this._coreBrowserService.dpr);
162
+ this._refreshDrawConstants();
163
+ this._refreshColorZonePadding();
164
+ }
165
+
166
+ private _refreshDecorations(): void {
167
+ if (this._shouldUpdateDimensions) {
168
+ this._refreshCanvasDimensions();
169
+ }
170
+ this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
171
+ this._colorZoneStore.clear();
172
+ for (const decoration of this._decorationService.decorations) {
173
+ this._colorZoneStore.addDecoration(decoration);
174
+ }
175
+ this._ctx.lineWidth = 1;
176
+ const zones = this._colorZoneStore.zones;
177
+ for (const zone of zones) {
178
+ if (zone.position !== 'full') {
179
+ this._renderColorZone(zone);
180
+ }
181
+ }
182
+ for (const zone of zones) {
183
+ if (zone.position === 'full') {
184
+ this._renderColorZone(zone);
185
+ }
186
+ }
187
+ this._shouldUpdateDimensions = false;
188
+ this._shouldUpdateAnchor = false;
189
+ }
190
+
191
+ private _renderColorZone(zone: IColorZone): void {
192
+ this._ctx.fillStyle = zone.color;
193
+ this._ctx.fillRect(
194
+ /* x */ drawX[zone.position || 'full'],
195
+ /* y */ Math.round(
196
+ (this._canvas.height - 1) * // -1 to ensure at least 2px are allowed for decoration on last line
197
+ (zone.startBufferLine / this._bufferService.buffers.active.lines.length) - drawHeight[zone.position || 'full'] / 2
198
+ ),
199
+ /* w */ drawWidth[zone.position || 'full'],
200
+ /* h */ Math.round(
201
+ (this._canvas.height - 1) * // -1 to ensure at least 2px are allowed for decoration on last line
202
+ ((zone.endBufferLine - zone.startBufferLine) / this._bufferService.buffers.active.lines.length) + drawHeight[zone.position || 'full']
203
+ )
204
+ );
205
+ }
206
+
207
+ private _queueRefresh(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void {
208
+ this._shouldUpdateDimensions = updateCanvasDimensions || this._shouldUpdateDimensions;
209
+ this._shouldUpdateAnchor = updateAnchor || this._shouldUpdateAnchor;
210
+ if (this._animationFrame !== undefined) {
211
+ return;
212
+ }
213
+ this._animationFrame = this._coreBrowserService.window.requestAnimationFrame(() => {
214
+ this._refreshDecorations();
215
+ this._animationFrame = undefined;
216
+ });
217
+ }
218
+ }