@xterm/addon-webgl 0.20.0-beta.2 → 0.20.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.
@@ -13,7 +13,8 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeS
13
13
  import { CharData, IBufferLine, ICellData } from 'common/Types';
14
14
  import { AttributeData } from 'common/buffer/AttributeData';
15
15
  import { CellData } from 'common/buffer/CellData';
16
- import { Attributes, Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
16
+ import { Attributes, Content, FgFlags, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
17
+ import { TextBlinkStateManager } from 'browser/renderer/shared/TextBlinkStateManager';
17
18
  import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
18
19
  import { Terminal } from '@xterm/xterm';
19
20
  import { GlyphRenderer } from './GlyphRenderer';
@@ -22,14 +23,15 @@ import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET
22
23
  import { IWebGL2RenderingContext, type ITextureAtlas } from './Types';
23
24
  import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
24
25
  import { IRenderLayer } from './renderLayer/Types';
25
- import { Emitter, Event } from 'vs/base/common/event';
26
- import { addDisposableListener } from 'vs/base/browser/dom';
27
- import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
26
+ import { Emitter, EventUtils } from 'common/Event';
27
+ import { addDisposableListener } from 'browser/Dom';
28
+ import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
28
29
  import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
29
30
 
30
31
  export class WebglRenderer extends Disposable implements IRenderer {
31
32
  private _renderLayers: IRenderLayer[];
32
- private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = new MutableDisposable();
33
+ private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = this._register(new MutableDisposable());
34
+ private _textBlinkStateManager: TextBlinkStateManager;
33
35
  private _charAtlasDisposable = this._register(new MutableDisposable());
34
36
  private _charAtlas: ITextureAtlas | undefined;
35
37
  private _devicePixelRatio: number;
@@ -37,8 +39,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
37
39
  private _observerDisposable = this._register(new MutableDisposable());
38
40
 
39
41
  private _model: RenderModel = new RenderModel();
42
+ private _rowHasBlinkingCells: boolean[] = [];
43
+ private _rowHasBlinkingCellsCount: number = 0;
40
44
  private _workCell: ICellData = new CellData();
41
- private _workCell2: ICellData = new CellData();
42
45
  private _cellColorResolver: CellColorResolver;
43
46
 
44
47
  private _canvas: HTMLCanvasElement;
@@ -72,6 +75,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
72
75
  private readonly _decorationService: IDecorationService,
73
76
  private readonly _optionsService: IOptionsService,
74
77
  private readonly _themeService: IThemeService,
78
+ private readonly _customGlyphs: boolean = true,
75
79
  preserveDrawingBuffer?: boolean
76
80
  ) {
77
81
  super();
@@ -104,6 +108,12 @@ export class WebglRenderer extends Disposable implements IRenderer {
104
108
  this._updateDimensions();
105
109
  this._updateCursorBlink();
106
110
  this._register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
111
+ this._textBlinkStateManager = this._register(new TextBlinkStateManager(
112
+ () => this._requestRedrawViewport(),
113
+ this._coreBrowserService,
114
+ this._optionsService
115
+ ));
116
+ this._resetBlinkingRowState();
107
117
 
108
118
  this._deviceMaxTextureSize = this._gl.getParameter(this._gl.MAX_TEXTURE_SIZE);
109
119
 
@@ -135,6 +145,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
135
145
  this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, w, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
136
146
  }));
137
147
 
148
+ this._register(addDisposableListener(this._coreBrowserService.mainDocument, 'mousedown', () => this._cursorBlinkStateManager.value?.restartBlinkAnimation()));
149
+
138
150
  this._core.screenElement!.appendChild(this._canvas);
139
151
 
140
152
  [this._rectangleRenderer.value, this._glyphRenderer.value] = this._initializeWebGLState();
@@ -175,6 +187,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
175
187
  this._updateDimensions();
176
188
 
177
189
  this._model.resize(this._terminal.cols, this._terminal.rows);
190
+ this._resetBlinkingRowState();
178
191
 
179
192
  // Resize all render layers
180
193
  for (const l of this._renderLayers) {
@@ -201,6 +214,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
201
214
  // Force a full refresh. Resizing `_glyphRenderer` should clear it already,
202
215
  // so there is no need to clear it again here.
203
216
  this._clearModel(false);
217
+
218
+ // Render synchronously to avoid flicker when the canvas is cleared
219
+ this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1, sync: true });
204
220
  }
205
221
 
206
222
  public handleCharSizeChanged(): void {
@@ -225,6 +241,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
225
241
  this._requestRedrawViewport();
226
242
  }
227
243
 
244
+ public handleViewportVisibilityChange(isVisible: boolean): void {
245
+ this._textBlinkStateManager.setViewportVisible(isVisible);
246
+ }
247
+
228
248
  public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
229
249
  for (const l of this._renderLayers) {
230
250
  l.handleSelectionChanged(this._terminal, start, end, columnSelectMode);
@@ -278,13 +298,14 @@ export class WebglRenderer extends Disposable implements IRenderer {
278
298
  this.dimensions.device.char.width,
279
299
  this.dimensions.device.char.height,
280
300
  this._coreBrowserService.dpr,
281
- this._deviceMaxTextureSize
301
+ this._deviceMaxTextureSize,
302
+ this._customGlyphs
282
303
  );
283
304
  if (this._charAtlas !== atlas) {
284
305
  this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
285
306
  this._charAtlasDisposable.value = combinedDisposable(
286
- Event.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
287
- Event.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
307
+ EventUtils.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
308
+ EventUtils.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
288
309
  );
289
310
  }
290
311
  this._charAtlas = atlas;
@@ -316,6 +337,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
316
337
  l.reset(this._terminal);
317
338
  }
318
339
 
340
+ this._resetBlinkingRowState();
341
+ this._textBlinkStateManager.setNeedsBlinkInViewport(false);
342
+
319
343
  this._cursorBlinkStateManager.value?.restartBlinkAnimation();
320
344
  this._updateCursorBlink();
321
345
  }
@@ -413,6 +437,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
413
437
  for (y = start; y <= end; y++) {
414
438
  row = y + terminal.buffer.ydisp;
415
439
  line = terminal.buffer.lines.get(row)!;
440
+ let rowHasBlinkingCells = false;
416
441
  this._model.lineLengths[y] = 0;
417
442
  isCursorRow = cursorY === row;
418
443
  skipJoinedCheckUntilX = 0;
@@ -470,8 +495,12 @@ export class WebglRenderer extends Disposable implements IRenderer {
470
495
  code = cell.getCode();
471
496
  i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
472
497
 
498
+ if (!rowHasBlinkingCells && cell.isBlink()) {
499
+ rowHasBlinkingCells = true;
500
+ }
501
+
473
502
  // Load colors/resolve overrides into work colors
474
- this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width);
503
+ this._cellColorResolver.resolve(cell, x, row, this.dimensions.device.cell.width, this.dimensions.device.cell.height);
475
504
 
476
505
  // Override colors for cursor cell
477
506
  if (isCursorVisible && row === cursorY) {
@@ -499,6 +528,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
499
528
  }
500
529
  }
501
530
 
531
+ if (this._textBlinkStateManager.isEnabled && !this._textBlinkStateManager.isBlinkOn && cell.isBlink()) {
532
+ this._cellColorResolver.result.fg |= FgFlags.INVISIBLE;
533
+ }
534
+
502
535
  if (code !== NULL_CELL_CODE) {
503
536
  this._model.lineLengths[y] = x + 1;
504
537
  }
@@ -545,11 +578,31 @@ export class WebglRenderer extends Disposable implements IRenderer {
545
578
  x--; // Go back to the previous update cell for next iteration
546
579
  }
547
580
  }
581
+ this._setRowBlinkState(y, rowHasBlinkingCells);
548
582
  }
549
583
  if (modelUpdated) {
550
584
  this._rectangleRenderer.value!.updateBackgrounds(this._model);
551
585
  }
552
586
  this._rectangleRenderer.value!.updateCursor(this._model);
587
+ this._updateTextBlinkState();
588
+ }
589
+
590
+ private _resetBlinkingRowState(): void {
591
+ this._rowHasBlinkingCells = new Array(this._terminal.rows).fill(false);
592
+ this._rowHasBlinkingCellsCount = 0;
593
+ }
594
+
595
+ private _setRowBlinkState(row: number, hasBlinkingCells: boolean): void {
596
+ const previous = this._rowHasBlinkingCells[row];
597
+ if (previous === hasBlinkingCells) {
598
+ return;
599
+ }
600
+ this._rowHasBlinkingCells[row] = hasBlinkingCells;
601
+ this._rowHasBlinkingCellsCount += hasBlinkingCells ? 1 : -1;
602
+ }
603
+
604
+ private _updateTextBlinkState(): void {
605
+ this._textBlinkStateManager.setNeedsBlinkInViewport(this._rowHasBlinkingCellsCount > 0);
553
606
  }
554
607
 
555
608
  /**
@@ -615,7 +668,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
615
668
  // the change as it's an exact multiple of the cell sizes.
616
669
  this._canvas.width = width;
617
670
  this._canvas.height = height;
618
- this._requestRedrawViewport();
671
+ // Render synchronously to avoid flicker when the canvas is cleared
672
+ this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1, sync: true });
619
673
  }
620
674
 
621
675
  private _requestRedrawViewport(): void {