Skip to content

Commit 4da2db8

Browse files
authored
Merge pull request #3637 from meganrogge/master
polish decorations
2 parents 71bfbe4 + 8dfed8f commit 4da2db8

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed

src/browser/services/DecorationService.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,14 @@ export class DecorationService extends Disposable implements IDecorationService
1616
private _screenElement: HTMLElement | undefined;
1717
private _renderService: IRenderService | undefined;
1818

19-
constructor(
20-
@IBufferService private readonly _bufferService: IBufferService,
21-
@IInstantiationService private readonly _instantiationService: IInstantiationService) {
22-
super();
23-
}
19+
constructor(@IInstantiationService private readonly _instantiationService: IInstantiationService) { super(); }
2420

2521
public attachToDom(screenElement: HTMLElement, renderService: IRenderService): void {
2622
this._renderService = renderService;
2723
this._screenElement = screenElement;
2824
this._container = document.createElement('div');
2925
this._container.classList.add('xterm-decoration-container');
3026
screenElement.appendChild(this._container);
31-
this.refresh();
3227
this.register(this._renderService.onRenderedBufferChange(() => this.refresh()));
3328
this.register(this._renderService.onDimensionsChange(() => this.refresh(true)));
3429
}
@@ -43,29 +38,29 @@ export class DecorationService extends Disposable implements IDecorationService
4338
return decoration;
4439
}
4540

46-
public refresh(recreate?: boolean): void {
47-
if (!this._bufferService || !this._renderService) {
41+
public refresh(shouldRecreate?: boolean): void {
42+
if (!this._renderService) {
4843
return;
4944
}
5045
for (const decoration of this._decorations) {
51-
decoration.render(this._renderService, recreate);
46+
decoration.render(this._renderService, shouldRecreate);
5247
}
5348
}
5449

5550
public dispose(): void {
5651
for (const decoration of this._decorations) {
5752
decoration.dispose();
5853
}
59-
if (this._container) {
60-
this._screenElement?.removeChild(this._container);
54+
if (this._screenElement && this._container && this._screenElement.contains(this._container)) {
55+
this._screenElement.removeChild(this._container);
6156
}
6257
}
6358
}
6459
export class Decoration extends Disposable implements IDecoration {
65-
private static _nextId = 1;
6660
private readonly _marker: IMarker;
6761
private _element: HTMLElement | undefined;
68-
private readonly _id: number = Decoration._nextId++;
62+
private _altBufferActive: boolean = false;
63+
6964
public isDisposed: boolean = false;
7065

7166
public get element(): HTMLElement | undefined { return this._element; }
@@ -90,24 +85,28 @@ export class Decoration extends Disposable implements IDecoration {
9085
super();
9186
this.x = options.x ?? 0;
9287
this._marker = options.marker;
88+
this._marker.onDispose(() => this.dispose());
9389
this.anchor = options.anchor || 'left';
9490
this.width = options.width || 1;
9591
this.height = options.height || 1;
92+
this.register(this._bufferService.buffers.onBufferActivate((event) => this._altBufferActive = event.activeBuffer === this._bufferService.buffers.alt));
9693
}
9794

98-
public render(renderService: IRenderService, recreate?: boolean): void {
99-
if (!this._element || recreate) {
100-
this._createElement(renderService, recreate);
95+
public render(renderService: IRenderService, shouldRecreate?: boolean): void {
96+
if (!this._element || shouldRecreate) {
97+
this._createElement(renderService, shouldRecreate);
10198
}
10299
if (this._container && this._element && !this._container.contains(this._element)) {
103100
this._container.append(this._element);
104101
}
105102
this._refreshStyle(renderService);
106-
this._onRender.fire(this._element!);
103+
if (this._element) {
104+
this._onRender.fire(this._element);
105+
}
107106
}
108107

109-
private _createElement(renderService: IRenderService, recreate?: boolean): void {
110-
if (recreate && this._element) {
108+
private _createElement(renderService: IRenderService, shouldRecreate?: boolean): void {
109+
if (shouldRecreate && this._element && this._container.contains(this._element)) {
111110
this._container.removeChild(this._element);
112111
}
113112
this._element = document.createElement('div');
@@ -117,7 +116,8 @@ export class Decoration extends Disposable implements IDecoration {
117116
this._element.style.top = `${(this.marker.line - this._bufferService.buffers.active.ydisp) * renderService.dimensions.scaledCellHeight}px`;
118117

119118
if (this.x && this.x > this._bufferService.cols) {
120-
this._element!.style.display = 'none';
119+
// exceeded the container width, so hide
120+
this._element.style.display = 'none';
121121
}
122122
if (this.anchor === 'right') {
123123
this._element.style.right = this.x ? `${this.x * renderService.dimensions.scaledCellWidth}px` : '';
@@ -129,9 +129,13 @@ export class Decoration extends Disposable implements IDecoration {
129129
if (this.isDisposed) {
130130
return;
131131
}
132-
this._container.removeChild(this._element!);
132+
if (!this.marker.isDisposed) {
133+
this.marker.dispose();
134+
}
135+
if (this._element && this._container.contains(this._element)) {
136+
this._container.removeChild(this._element);
137+
}
133138
this.isDisposed = true;
134-
this._marker.dispose();
135139
// Emit before super.dispose such that dispose listeners get a change to react
136140
this._onDispose.fire();
137141
super.dispose();
@@ -140,13 +144,16 @@ export class Decoration extends Disposable implements IDecoration {
140144
}
141145

142146
private _refreshStyle(renderService: IRenderService): void {
147+
if (!this._element) {
148+
return;
149+
}
143150
const line = this.marker.line - this._bufferService.buffers.active.ydisp;
144151
if (line < 0 || line > this._bufferService.rows) {
145152
// outside of viewport
146-
this._element!.style.display = 'none';
153+
this._element.style.display = 'none';
147154
} else {
148-
this._element!.style.top = `${line * renderService.dimensions.scaledCellHeight}px`;
149-
this._element!.style.display = 'block';
155+
this._element.style.top = `${line * renderService.dimensions.scaledCellHeight}px`;
156+
this._element.style.display = this._altBufferActive ? 'none' : 'block';
150157
}
151158
}
152159
}

src/common/InputHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,7 @@ export class InputHandler extends Disposable implements IInputHandler {
12921292
this._resetBufferLine(j);
12931293
}
12941294
this._dirtyRowService.markDirty(0);
1295+
this._bufferService.buffer.clearMarkers();
12951296
break;
12961297
case 3:
12971298
// Clear scrollback (everything not in viewport)

0 commit comments

Comments
 (0)