@xterm/addon-webgl 0.19.0-beta.9 → 0.19.0-beta.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@xterm/addon-webgl",
3
- "version": "0.19.0-beta.9",
3
+ "version": "0.19.0-beta.90",
4
4
  "author": {
5
5
  "name": "The xterm.js authors",
6
6
  "url": "https://xtermjs.org/"
7
7
  },
8
8
  "main": "lib/addon-webgl.js",
9
+ "module": "lib/addon-webgl.mjs",
9
10
  "types": "typings/addon-webgl.d.ts",
10
11
  "repository": "https://github.com/xtermjs/xterm.js/tree/master/addons/addon-webgl",
11
12
  "license": "MIT",
@@ -20,9 +21,10 @@
20
21
  "prepackage": "npm run build",
21
22
  "package": "../../node_modules/.bin/webpack",
22
23
  "prepublishOnly": "npm run package",
23
- "start-server-only": "node ../../demo/start-server-only"
24
+ "start": "node ../../demo/start"
24
25
  },
25
26
  "peerDependencies": {
26
- "@xterm/xterm": "^5.0.0"
27
- }
27
+ "@xterm/xterm": "^5.6.0-beta.90"
28
+ },
29
+ "commit": "c21f32d012fb23b20a3d3de46e109ad9295fc1a4"
28
30
  }
@@ -7,7 +7,7 @@ import { allowRescaling, throwIfFalsy } from 'browser/renderer/shared/RendererUt
7
7
  import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
8
8
  import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
9
9
  import { NULL_CELL_CODE } from 'common/buffer/Constants';
10
- import { Disposable, toDisposable } from 'common/Lifecycle';
10
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
11
11
  import { Terminal } from '@xterm/xterm';
12
12
  import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
13
13
  import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
@@ -127,7 +127,7 @@ export class GlyphRenderer extends Disposable {
127
127
  }
128
128
 
129
129
  this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, createFragmentShaderSource(TextureAtlas.maxAtlasPages)));
130
- this.register(toDisposable(() => gl.deleteProgram(this._program)));
130
+ this._register(toDisposable(() => gl.deleteProgram(this._program)));
131
131
 
132
132
  // Uniform locations
133
133
  this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
@@ -141,7 +141,7 @@ export class GlyphRenderer extends Disposable {
141
141
  // Setup a_unitquad, this defines the 4 vertices of a rectangle
142
142
  const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
143
143
  const unitQuadVerticesBuffer = gl.createBuffer();
144
- this.register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
144
+ this._register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
145
145
  gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
146
146
  gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
147
147
  gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
@@ -152,13 +152,13 @@ export class GlyphRenderer extends Disposable {
152
152
  // triangle strip
153
153
  const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]);
154
154
  const elementIndicesBuffer = gl.createBuffer();
155
- this.register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
155
+ this._register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
156
156
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
157
157
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
158
158
 
159
159
  // Setup attributes
160
160
  this._attributesBuffer = throwIfFalsy(gl.createBuffer());
161
- this.register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
161
+ this._register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
162
162
  gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
163
163
  gl.enableVertexAttribArray(VertexAttribLocations.OFFSET);
164
164
  gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0);
@@ -193,7 +193,7 @@ export class GlyphRenderer extends Disposable {
193
193
  this._atlasTextures = [];
194
194
  for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) {
195
195
  const glTexture = new GLTexture(throwIfFalsy(gl.createTexture()));
196
- this.register(toDisposable(() => gl.deleteTexture(glTexture.texture)));
196
+ this._register(toDisposable(() => gl.deleteTexture(glTexture.texture)));
197
197
  gl.activeTexture(gl.TEXTURE0 + i);
198
198
  gl.bindTexture(gl.TEXTURE_2D, glTexture.texture);
199
199
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
@@ -238,9 +238,9 @@ export class GlyphRenderer extends Disposable {
238
238
 
239
239
  // Get the glyph
240
240
  if (chars && chars.length > 1) {
241
- $glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, false);
241
+ $glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, false, this._terminal.element);
242
242
  } else {
243
- $glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, false);
243
+ $glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, false, this._terminal.element);
244
244
  }
245
245
 
246
246
  $leftCellPadding = Math.floor((this._dimensions.device.cell.width - this._dimensions.device.char.width) / 2);
@@ -8,7 +8,7 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types';
8
8
  import { IThemeService } from 'browser/services/Services';
9
9
  import { ReadonlyColorSet } from 'browser/Types';
10
10
  import { Attributes, FgFlags } from 'common/buffer/Constants';
11
- import { Disposable, toDisposable } from 'common/Lifecycle';
11
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
12
12
  import { IColor } from 'common/Types';
13
13
  import { Terminal } from '@xterm/xterm';
14
14
  import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
@@ -96,7 +96,7 @@ export class RectangleRenderer extends Disposable {
96
96
  const gl = this._gl;
97
97
 
98
98
  this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
99
- this.register(toDisposable(() => gl.deleteProgram(this._program)));
99
+ this._register(toDisposable(() => gl.deleteProgram(this._program)));
100
100
 
101
101
  // Uniform locations
102
102
  this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
@@ -108,7 +108,7 @@ export class RectangleRenderer extends Disposable {
108
108
  // Setup a_unitquad, this defines the 4 vertices of a rectangle
109
109
  const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
110
110
  const unitQuadVerticesBuffer = gl.createBuffer();
111
- this.register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
111
+ this._register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
112
112
  gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
113
113
  gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
114
114
  gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
@@ -119,13 +119,13 @@ export class RectangleRenderer extends Disposable {
119
119
  // triangle strip
120
120
  const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]);
121
121
  const elementIndicesBuffer = gl.createBuffer();
122
- this.register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
122
+ this._register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
123
123
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
124
124
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
125
125
 
126
126
  // Setup attributes
127
127
  this._attributesBuffer = throwIfFalsy(gl.createBuffer());
128
- this.register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
128
+ this._register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
129
129
  gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
130
130
  gl.enableVertexAttribArray(VertexAttribLocations.POSITION);
131
131
  gl.vertexAttribPointer(VertexAttribLocations.POSITION, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 0);
@@ -138,7 +138,7 @@ export class RectangleRenderer extends Disposable {
138
138
  gl.vertexAttribDivisor(VertexAttribLocations.COLOR, 1);
139
139
 
140
140
  this._updateCachedColors(_themeService.colors);
141
- this.register(this._themeService.onChangeColors(e => {
141
+ this._register(this._themeService.onChangeColors(e => {
142
142
  this._updateCachedColors(e);
143
143
  this._updateViewportRectangle();
144
144
  }));
package/src/WebglAddon.ts CHANGED
@@ -7,25 +7,25 @@ import type { ITerminalAddon, Terminal } from '@xterm/xterm';
7
7
  import type { WebglAddon as IWebglApi } from '@xterm/addon-webgl';
8
8
  import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
9
9
  import { ITerminal } from 'browser/Types';
10
- import { EventEmitter, forwardEvent } from 'common/EventEmitter';
11
- import { Disposable, toDisposable } from 'common/Lifecycle';
10
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
12
11
  import { getSafariVersion, isSafari } from 'common/Platform';
13
12
  import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
14
13
  import { IWebGL2RenderingContext } from './Types';
15
14
  import { WebglRenderer } from './WebglRenderer';
16
15
  import { setTraceLogger } from 'common/services/LogService';
16
+ import { Emitter, Event } from 'vs/base/common/event';
17
17
 
18
18
  export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi {
19
19
  private _terminal?: Terminal;
20
20
  private _renderer?: WebglRenderer;
21
21
 
22
- private readonly _onChangeTextureAtlas = this.register(new EventEmitter<HTMLCanvasElement>());
22
+ private readonly _onChangeTextureAtlas = this._register(new Emitter<HTMLCanvasElement>());
23
23
  public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
24
- private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
24
+ private readonly _onAddTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
25
25
  public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
26
- private readonly _onRemoveTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
26
+ private readonly _onRemoveTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
27
27
  public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
28
- private readonly _onContextLoss = this.register(new EventEmitter<void>());
28
+ private readonly _onContextLoss = this._register(new Emitter<void>());
29
29
  public readonly onContextLoss = this._onContextLoss.event;
30
30
 
31
31
  constructor(
@@ -49,7 +49,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
49
49
  public activate(terminal: Terminal): void {
50
50
  const core = (terminal as any)._core as ITerminal;
51
51
  if (!terminal.element) {
52
- this.register(core.onWillOpen(() => this.activate(terminal)));
52
+ this._register(core.onWillOpen(() => this.activate(terminal)));
53
53
  return;
54
54
  }
55
55
 
@@ -70,7 +70,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
70
70
  // bundled separately to the core module
71
71
  setTraceLogger(logService);
72
72
 
73
- this._renderer = this.register(new WebglRenderer(
73
+ this._renderer = this._register(new WebglRenderer(
74
74
  terminal,
75
75
  characterJoinerService,
76
76
  charSizeService,
@@ -81,13 +81,16 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
81
81
  themeService,
82
82
  this._preserveDrawingBuffer
83
83
  ));
84
- this.register(forwardEvent(this._renderer.onContextLoss, this._onContextLoss));
85
- this.register(forwardEvent(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas));
86
- this.register(forwardEvent(this._renderer.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas));
87
- this.register(forwardEvent(this._renderer.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas));
84
+ this._register(Event.forward(this._renderer.onContextLoss, this._onContextLoss));
85
+ this._register(Event.forward(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas));
86
+ this._register(Event.forward(this._renderer.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas));
87
+ this._register(Event.forward(this._renderer.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas));
88
88
  renderService.setRenderer(this._renderer);
89
89
 
90
- this.register(toDisposable(() => {
90
+ this._register(toDisposable(() => {
91
+ if ((this._terminal as any)._core._store._isDisposed) {
92
+ return;
93
+ }
91
94
  const renderService: IRenderService = (this._terminal as any)._core._renderService;
92
95
  renderService.setRenderer((this._terminal as any)._core._createRenderer());
93
96
  renderService.handleResize(terminal.cols, terminal.rows);
@@ -3,7 +3,6 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { addDisposableDomListener } from 'browser/Lifecycle';
7
6
  import { ITerminal } from 'browser/Types';
8
7
  import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
9
8
  import { acquireTextureAtlas, removeTerminalFromCache } from 'browser/renderer/shared/CharAtlasCache';
@@ -12,8 +11,6 @@ import { observeDevicePixelDimensions } from 'browser/renderer/shared/DevicePixe
12
11
  import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
13
12
  import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ITextureAtlas } from 'browser/renderer/shared/Types';
14
13
  import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
15
- import { EventEmitter, forwardEvent } from 'common/EventEmitter';
16
- import { Disposable, MutableDisposable, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
17
14
  import { CharData, IBufferLine, ICellData } from 'common/Types';
18
15
  import { AttributeData } from 'common/buffer/AttributeData';
19
16
  import { CellData } from 'common/buffer/CellData';
@@ -26,14 +23,18 @@ import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET
26
23
  import { IWebGL2RenderingContext } from './Types';
27
24
  import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
28
25
  import { IRenderLayer } from './renderLayer/Types';
26
+ import { Emitter, Event } from 'vs/base/common/event';
27
+ import { addDisposableListener } from 'vs/base/browser/dom';
28
+ import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
29
29
 
30
30
  export class WebglRenderer extends Disposable implements IRenderer {
31
31
  private _renderLayers: IRenderLayer[];
32
32
  private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = new MutableDisposable();
33
- private _charAtlasDisposable = this.register(new MutableDisposable());
33
+ private _charAtlasDisposable = this._register(new MutableDisposable());
34
34
  private _charAtlas: ITextureAtlas | undefined;
35
35
  private _devicePixelRatio: number;
36
- private _observerDisposable = this.register(new MutableDisposable());
36
+ private _deviceMaxTextureSize: number;
37
+ private _observerDisposable = this._register(new MutableDisposable());
37
38
 
38
39
  private _model: RenderModel = new RenderModel();
39
40
  private _workCell: ICellData = new CellData();
@@ -42,8 +43,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
42
43
 
43
44
  private _canvas: HTMLCanvasElement;
44
45
  private _gl: IWebGL2RenderingContext;
45
- private _rectangleRenderer: MutableDisposable<RectangleRenderer> = this.register(new MutableDisposable());
46
- private _glyphRenderer: MutableDisposable<GlyphRenderer> = this.register(new MutableDisposable());
46
+ private _rectangleRenderer: MutableDisposable<RectangleRenderer> = this._register(new MutableDisposable());
47
+ private _glyphRenderer: MutableDisposable<GlyphRenderer> = this._register(new MutableDisposable());
47
48
 
48
49
  public readonly dimensions: IRenderDimensions;
49
50
 
@@ -51,15 +52,15 @@ export class WebglRenderer extends Disposable implements IRenderer {
51
52
  private _isAttached: boolean;
52
53
  private _contextRestorationTimeout: number | undefined;
53
54
 
54
- private readonly _onChangeTextureAtlas = this.register(new EventEmitter<HTMLCanvasElement>());
55
+ private readonly _onChangeTextureAtlas = this._register(new Emitter<HTMLCanvasElement>());
55
56
  public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
56
- private readonly _onAddTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
57
+ private readonly _onAddTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
57
58
  public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
58
- private readonly _onRemoveTextureAtlasCanvas = this.register(new EventEmitter<HTMLCanvasElement>());
59
+ private readonly _onRemoveTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
59
60
  public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
60
- private readonly _onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>());
61
+ private readonly _onRequestRedraw = this._register(new Emitter<IRequestRedrawEvent>());
61
62
  public readonly onRequestRedraw = this._onRequestRedraw.event;
62
- private readonly _onContextLoss = this.register(new EventEmitter<void>());
63
+ private readonly _onContextLoss = this._register(new Emitter<void>());
63
64
  public readonly onContextLoss = this._onContextLoss.event;
64
65
 
65
66
  constructor(
@@ -75,7 +76,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
75
76
  ) {
76
77
  super();
77
78
 
78
- this.register(this._themeService.onChangeColors(() => this._handleColorChange()));
79
+ this._register(this._themeService.onChangeColors(() => this._handleColorChange()));
79
80
 
80
81
  this._cellColorResolver = new CellColorResolver(this._terminal, this._optionsService, this._model.selection, this._decorationService, this._coreBrowserService, this._themeService);
81
82
 
@@ -88,7 +89,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
88
89
  this._devicePixelRatio = this._coreBrowserService.dpr;
89
90
  this._updateDimensions();
90
91
  this._updateCursorBlink();
91
- this.register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
92
+ this._register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
92
93
 
93
94
  this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
94
95
 
@@ -102,7 +103,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
102
103
  throw new Error('WebGL2 not supported ' + this._gl);
103
104
  }
104
105
 
105
- this.register(addDisposableDomListener(this._canvas, 'webglcontextlost', (e) => {
106
+ this._deviceMaxTextureSize = this._gl.getParameter(this._gl.MAX_TEXTURE_SIZE);
107
+
108
+ this._register(addDisposableListener(this._canvas, 'webglcontextlost', (e) => {
106
109
  console.log('webglcontextlost event received');
107
110
  // Prevent the default behavior in order to enable WebGL context restoration.
108
111
  e.preventDefault();
@@ -114,7 +117,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
114
117
  this._onContextLoss.fire(e);
115
118
  }, 3000 /* ms */);
116
119
  }));
117
- this.register(addDisposableDomListener(this._canvas, 'webglcontextrestored', (e) => {
120
+ this._register(addDisposableListener(this._canvas, 'webglcontextrestored', (e) => {
118
121
  console.warn('webglcontextrestored event received');
119
122
  clearTimeout(this._contextRestorationTimeout);
120
123
  this._contextRestorationTimeout = undefined;
@@ -126,7 +129,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
126
129
  }));
127
130
 
128
131
  this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, this._coreBrowserService.window, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
129
- this.register(this._coreBrowserService.onWindowChange(w => {
132
+ this._register(this._coreBrowserService.onWindowChange(w => {
130
133
  this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, w, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
131
134
  }));
132
135
 
@@ -136,7 +139,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
136
139
 
137
140
  this._isAttached = this._coreBrowserService.window.document.body.contains(this._core.screenElement!);
138
141
 
139
- this.register(toDisposable(() => {
142
+ this._register(toDisposable(() => {
140
143
  for (const l of this._renderLayers) {
141
144
  l.dispose();
142
145
  }
@@ -272,14 +275,15 @@ export class WebglRenderer extends Disposable implements IRenderer {
272
275
  this.dimensions.device.cell.height,
273
276
  this.dimensions.device.char.width,
274
277
  this.dimensions.device.char.height,
275
- this._coreBrowserService.dpr
278
+ this._coreBrowserService.dpr,
279
+ this._deviceMaxTextureSize
276
280
  );
277
281
  if (this._charAtlas !== atlas) {
278
282
  this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
279
- this._charAtlasDisposable.value = getDisposeArrayDisposable([
280
- forwardEvent(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
281
- forwardEvent(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
282
- ]);
283
+ this._charAtlasDisposable.value = combinedDisposable(
284
+ Event.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
285
+ Event.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
286
+ );
283
287
  }
284
288
  this._charAtlas = atlas;
285
289
  this._charAtlas.warmUp();
@@ -314,14 +318,6 @@ export class WebglRenderer extends Disposable implements IRenderer {
314
318
  this._updateCursorBlink();
315
319
  }
316
320
 
317
- public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
318
- return -1;
319
- }
320
-
321
- public deregisterCharacterJoiner(joinerId: number): boolean {
322
- return false;
323
- }
324
-
325
321
  public renderRows(start: number, end: number): void {
326
322
  if (!this._isAttached) {
327
323
  if (this._coreBrowserService.window.document.body.contains(this._core.screenElement!) && this._charSizeService.width && this._charSizeService.height) {
@@ -362,7 +358,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
362
358
  }
363
359
 
364
360
  private _updateCursorBlink(): void {
365
- if (this._terminal.options.cursorBlink) {
361
+ if (this._coreService.decPrivateModes.cursorBlink ?? this._terminal.options.cursorBlink) {
366
362
  this._cursorBlinkStateManager.value = new CursorBlinkStateManager(() => {
367
363
  this._requestRedrawCursor();
368
364
  }, this._coreBrowserService);
@@ -385,8 +381,11 @@ export class WebglRenderer extends Disposable implements IRenderer {
385
381
  let line: IBufferLine;
386
382
  let joinedRanges: [number, number][];
387
383
  let isJoined: boolean;
384
+ let skipJoinedCheckUntilX: number = 0;
385
+ let isValidJoinRange: boolean = true;
388
386
  let lastCharX: number;
389
387
  let range: [number, number];
388
+ let isCursorRow: boolean;
390
389
  let chars: string;
391
390
  let code: number;
392
391
  let width: number;
@@ -395,6 +394,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
395
394
  let j: number;
396
395
  start = clamp(start, terminal.rows - 1, 0);
397
396
  end = clamp(end, terminal.rows - 1, 0);
397
+ const cursorStyle = this._coreService.decPrivateModes.cursorStyle ?? terminal.options.cursorStyle ?? 'block';
398
398
 
399
399
  const cursorY = this._terminal.buffer.active.baseY + this._terminal.buffer.active.cursorY;
400
400
  const viewportRelativeCursorY = cursorY - terminal.buffer.ydisp;
@@ -412,6 +412,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
412
412
  row = y + terminal.buffer.ydisp;
413
413
  line = terminal.buffer.lines.get(row)!;
414
414
  this._model.lineLengths[y] = 0;
415
+ isCursorRow = cursorY === row;
416
+ skipJoinedCheckUntilX = 0;
415
417
  joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
416
418
  for (x = 0; x < terminal.cols; x++) {
417
419
  lastBg = this._cellColorResolver.result.bg;
@@ -423,25 +425,43 @@ export class WebglRenderer extends Disposable implements IRenderer {
423
425
 
424
426
  // If true, indicates that the current character(s) to draw were joined.
425
427
  isJoined = false;
428
+
429
+ // Indicates whether this cell is part of a joined range that should be ignored as it cannot
430
+ // be rendered entirely, like the selection state differs across the range.
431
+ isValidJoinRange = (x >= skipJoinedCheckUntilX);
432
+
426
433
  lastCharX = x;
427
434
 
428
435
  // Process any joined character ranges as needed. Because of how the
429
436
  // ranges are produced, we know that they are valid for the characters
430
437
  // and attributes of our input.
431
- if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
432
- isJoined = true;
438
+ if (joinedRanges.length > 0 && x === joinedRanges[0][0] && isValidJoinRange) {
433
439
  range = joinedRanges.shift()!;
434
440
 
435
- // We already know the exact start and end column of the joined range,
436
- // so we get the string and width representing it directly.
437
- cell = new JoinedCellData(
438
- cell,
439
- line!.translateToString(true, range[0], range[1]),
440
- range[1] - range[0]
441
- );
442
-
443
- // Skip over the cells occupied by this range in the loop
444
- lastCharX = range[1] - 1;
441
+ // If the ligature's selection state is not consistent, don't join it. This helps the
442
+ // selection render correctly regardless whether they should be joined.
443
+ const firstSelectionState = this._model.selection.isCellSelected(this._terminal, range[0], row);
444
+ for (i = range[0] + 1; i < range[1]; i++) {
445
+ isValidJoinRange &&= (firstSelectionState === this._model.selection.isCellSelected(this._terminal, i, row));
446
+ }
447
+ // Similarly, if the cursor is in the ligature, don't join it.
448
+ isValidJoinRange &&= !isCursorRow || cursorX < range[0] || cursorX >= range[1];
449
+ if (!isValidJoinRange) {
450
+ skipJoinedCheckUntilX = range[1];
451
+ } else {
452
+ isJoined = true;
453
+
454
+ // We already know the exact start and end column of the joined range,
455
+ // so we get the string and width representing it directly.
456
+ cell = new JoinedCellData(
457
+ cell,
458
+ line!.translateToString(true, range[0], range[1]),
459
+ range[1] - range[0]
460
+ );
461
+
462
+ // Skip over the cells occupied by this range in the loop
463
+ lastCharX = range[1] - 1;
464
+ }
445
465
  }
446
466
 
447
467
  chars = cell.getChars();
@@ -458,8 +478,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
458
478
  x: cursorX,
459
479
  y: viewportRelativeCursorY,
460
480
  width: cell.getWidth(),
461
- style: this._coreBrowserService.isFocused ?
462
- (terminal.options.cursorStyle || 'block') : terminal.options.cursorInactiveStyle,
481
+ style: this._coreBrowserService.isFocused ? cursorStyle : terminal.options.cursorInactiveStyle,
463
482
  cursorWidth: terminal.options.cursorWidth,
464
483
  dpr: this._devicePixelRatio
465
484
  };
@@ -467,9 +486,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
467
486
  }
468
487
  if (x >= cursorX && x <= lastCursorX &&
469
488
  ((this._coreBrowserService.isFocused &&
470
- (terminal.options.cursorStyle || 'block') === 'block') ||
489
+ cursorStyle === 'block') ||
471
490
  (this._coreBrowserService.isFocused === false &&
472
- terminal.options.cursorInactiveStyle === 'block'))) {
491
+ terminal.options.cursorInactiveStyle === 'block'))
492
+ ) {
473
493
  this._cellColorResolver.result.fg =
474
494
  Attributes.CM_RGB | (this._themeService.colors.cursorAccent.rgba >> 8 & Attributes.RGB_MASK);
475
495
  this._cellColorResolver.result.bg =
@@ -510,14 +530,17 @@ export class WebglRenderer extends Disposable implements IRenderer {
510
530
  cell = this._workCell;
511
531
 
512
532
  // Null out non-first cells
513
- for (x++; x < lastCharX; x++) {
533
+ for (x++; x <= lastCharX; x++) {
514
534
  j = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
515
535
  this._glyphRenderer.value!.updateCell(x, y, NULL_CELL_CODE, 0, 0, 0, NULL_CELL_CHAR, 0, 0);
516
536
  this._model.cells[j] = NULL_CELL_CODE;
537
+ // Don't re-resolve the cell color since multi-colored ligature backgrounds are not
538
+ // supported
517
539
  this._model.cells[j + RENDER_MODEL_BG_OFFSET] = this._cellColorResolver.result.bg;
518
540
  this._model.cells[j + RENDER_MODEL_FG_OFFSET] = this._cellColorResolver.result.fg;
519
541
  this._model.cells[j + RENDER_MODEL_EXT_OFFSET] = this._cellColorResolver.result.ext;
520
542
  }
543
+ x--; // Go back to the previous update cell for next iteration
521
544
  }
522
545
  }
523
546
  }
@@ -9,7 +9,7 @@ import { TEXT_BASELINE } from 'browser/renderer/shared/Constants';
9
9
  import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
10
10
  import { IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
11
11
  import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
12
- import { Disposable, toDisposable } from 'common/Lifecycle';
12
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
13
13
  import { CellData } from 'common/buffer/CellData';
14
14
  import { IOptionsService } from 'common/services/Services';
15
15
  import { Terminal } from '@xterm/xterm';
@@ -43,11 +43,11 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
43
43
  this._canvas.style.zIndex = zIndex.toString();
44
44
  this._initCanvas();
45
45
  this._container.appendChild(this._canvas);
46
- this.register(this._themeService.onChangeColors(e => {
46
+ this._register(this._themeService.onChangeColors(e => {
47
47
  this._refreshCharAtlas(terminal, e);
48
48
  this.reset(terminal);
49
49
  }));
50
- this.register(toDisposable(() => {
50
+ this._register(toDisposable(() => {
51
51
  this._canvas.remove();
52
52
  }));
53
53
  }
@@ -94,7 +94,8 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
94
94
  if (this._deviceCharWidth <= 0 && this._deviceCharHeight <= 0) {
95
95
  return;
96
96
  }
97
- this._charAtlas = acquireTextureAtlas(terminal, this._optionsService.rawOptions, colorSet, this._deviceCellWidth, this._deviceCellHeight, this._deviceCharWidth, this._deviceCharHeight, this._coreBrowserService.dpr);
97
+
98
+ this._charAtlas = acquireTextureAtlas(terminal, this._optionsService.rawOptions, colorSet, this._deviceCellWidth, this._deviceCellHeight, this._deviceCharWidth, this._deviceCharHeight, this._coreBrowserService.dpr, 2048);
98
99
  this._charAtlas.warmUp();
99
100
  }
100
101
 
@@ -26,8 +26,8 @@ export class LinkRenderLayer extends BaseRenderLayer {
26
26
  ) {
27
27
  super(terminal, container, 'link', zIndex, true, coreBrowserService, optionsService, themeService);
28
28
 
29
- this.register(linkifier2.onShowLinkUnderline(e => this._handleShowLinkUnderline(e)));
30
- this.register(linkifier2.onHideLinkUnderline(e => this._handleHideLinkUnderline(e)));
29
+ this._register(linkifier2.onShowLinkUnderline(e => this._handleShowLinkUnderline(e)));
30
+ this._register(linkifier2.onHideLinkUnderline(e => this._handleHideLinkUnderline(e)));
31
31
  }
32
32
 
33
33
  public resize(terminal: Terminal, dim: IRenderDimensions): void {
@@ -7,7 +7,7 @@ import { Terminal, ITerminalAddon, IEvent } from '@xterm/xterm';
7
7
 
8
8
  declare module '@xterm/addon-webgl' {
9
9
  /**
10
- * An xterm.js addon that provides search functionality.
10
+ * An xterm.js addon that provides hardware-accelerated rendering functionality via WebGL.
11
11
  */
12
12
  export class WebglAddon implements ITerminalAddon {
13
13
  public textureAtlas?: HTMLCanvasElement;
@@ -27,6 +27,11 @@ declare module '@xterm/addon-webgl' {
27
27
  */
28
28
  public readonly onAddTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
29
29
 
30
+ /**
31
+ * An event that is fired when the a page is removed from the texture atlas.
32
+ */
33
+ public readonly onRemoveTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
34
+
30
35
  constructor(preserveDrawingBuffer?: boolean);
31
36
 
32
37
  /**
File without changes