Merge pull request #3702 from meganrogge/overviewrulerFix

This commit is contained in:
Megan Rogge
2022-03-22 20:04:00 -04:00
committed by GitHub
5 changed files with 74 additions and 25 deletions
@@ -38,6 +38,11 @@ export class OverviewRulerRenderer extends Disposable {
} }
private _animationFrame: number | undefined; private _animationFrame: number | undefined;
private _shouldUpdateDimensions: boolean | undefined = true;
private _shouldUpdateAnchor: boolean | undefined = true;
private _containerHeight: number | undefined;
constructor( constructor(
private readonly _viewportElement: HTMLElement, private readonly _viewportElement: HTMLElement,
private readonly _screenElement: HTMLElement, private readonly _screenElement: HTMLElement,
@@ -57,22 +62,53 @@ export class OverviewRulerRenderer extends Disposable {
} else { } else {
this._ctx = ctx; this._ctx = ctx;
} }
this._queueRefresh(true); this._registerDecorationListeners();
this._registerBufferChangeListeners();
this._registerDimensionChangeListeners();
}
/**
* On decoration add or remove, redraw
*/
private _registerDecorationListeners(): void {
this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
this.register(this._decorationService.onDecorationRemoved(decoration => this._removeDecoration(decoration)));
}
/**
* On buffer change, redraw
* and hide the canvas if the alt buffer is active
*/
private _registerBufferChangeListeners(): void {
this.register(this._renderService.onRenderedBufferChange(() => this._queueRefresh()));
this.register(this._bufferService.buffers.onBufferActivate(() => { this.register(this._bufferService.buffers.onBufferActivate(() => {
this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block'; this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block';
})); }));
this.register(this._renderService.onRenderedBufferChange(() => this._queueRefresh())); }
this.register(this._renderService.onDimensionsChange(() => this._queueRefresh(true, true))); /**
this.register(addDisposableDomListener(window, 'resize', () => this._queueRefresh(true))); * On dimension change, update canvas dimensions
this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true))); * and then redraw
this.register(this._decorationService.onDecorationRemoved(decoration => this._removeDecoration(decoration))); */
this.register(this._optionsService.onOptionChange(o => { private _registerDimensionChangeListeners(): void {
if (o === 'overviewRulerWidth') { // container height changed
this._refreshDrawConstants(); this.register(this._renderService.onRender((): void => {
this._queueRefresh(); if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
this._queueRefresh(true);
this._containerHeight = this._screenElement.clientHeight;
} }
})); }));
this._refreshDrawConstants(); // overview ruler width changed
this.register(this._optionsService.onOptionChange(o => {
if (o === 'overviewRulerWidth') {
this._queueRefresh(true);
}
}));
// device pixel ratio changed
this.register(addDisposableDomListener(window, 'resize', () => {
this._queueRefresh(true);
}));
// set the canvas dimensions
this._queueRefresh(true);
} }
public override dispose(): void { public override dispose(): void {
@@ -104,8 +140,8 @@ export class OverviewRulerRenderer extends Disposable {
drawX.right = drawWidth.left + drawWidth.center; drawX.right = drawWidth.left + drawWidth.center;
} }
private _refreshStyle(decoration: IInternalDecoration, updateAnchor?: boolean): void { private _refreshStyle(decoration: IInternalDecoration): void {
if (updateAnchor) { if (this._shouldUpdateAnchor) {
if (decoration.options.anchor === 'right') { if (decoration.options.anchor === 'right') {
this._canvas.style.right = decoration.options.x ? `${decoration.options.x * this._renderService.dimensions.actualCellWidth}px` : ''; this._canvas.style.right = decoration.options.x ? `${decoration.options.x * this._renderService.dimensions.actualCellWidth}px` : '';
} else { } else {
@@ -122,7 +158,7 @@ export class OverviewRulerRenderer extends Disposable {
/* x */ drawX[decoration.options.overviewRulerOptions.position!], /* x */ drawX[decoration.options.overviewRulerOptions.position!],
/* y */ Math.round( /* y */ Math.round(
(this._canvas.height - 1) * // -1 to ensure at least 2px are allowed for decoration on last line (this._canvas.height - 1) * // -1 to ensure at least 2px are allowed for decoration on last line
(decoration.options.marker.line / this._bufferService.buffers.active.lines.length) - drawHeight[decoration.options.overviewRulerOptions.position!] / 2 (decoration.options.marker.line / this._bufferService.buffers.active.lines.length) - drawHeight[decoration.options.overviewRulerOptions.position!] / 2
), ),
/* w */ drawWidth[decoration.options.overviewRulerOptions.position!], /* w */ drawWidth[decoration.options.overviewRulerOptions.position!],
/* h */ drawHeight[decoration.options.overviewRulerOptions.position!] /* h */ drawHeight[decoration.options.overviewRulerOptions.position!]
@@ -131,44 +167,48 @@ export class OverviewRulerRenderer extends Disposable {
private _refreshCanvasDimensions(): void { private _refreshCanvasDimensions(): void {
this._canvas.style.width = `${this._width}px`; this._canvas.style.width = `${this._width}px`;
this._canvas.style.height = `${this._screenElement.clientHeight}px`;
this._canvas.width = Math.round(this._width * window.devicePixelRatio); this._canvas.width = Math.round(this._width * window.devicePixelRatio);
this._canvas.style.height = `${this._screenElement.clientHeight}px`;
this._canvas.height = Math.round(this._screenElement.clientHeight * window.devicePixelRatio); this._canvas.height = Math.round(this._screenElement.clientHeight * window.devicePixelRatio);
this._refreshDrawConstants(); this._refreshDrawConstants();
} }
private _refreshDecorations(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void { private _refreshDecorations(): void {
if (updateCanvasDimensions) { if (this._shouldUpdateDimensions) {
this._refreshCanvasDimensions(); this._refreshCanvasDimensions();
} }
this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
for (const decoration of this._decorationService.decorations) { for (const decoration of this._decorationService.decorations) {
if (decoration.options.overviewRulerOptions && decoration.options.overviewRulerOptions.position !== 'full') { if (decoration.options.overviewRulerOptions && decoration.options.overviewRulerOptions.position !== 'full') {
this._renderDecoration(decoration, updateAnchor); this._renderDecoration(decoration);
} }
} }
for (const decoration of this._decorationService.decorations) { for (const decoration of this._decorationService.decorations) {
if (decoration.options.overviewRulerOptions && decoration.options.overviewRulerOptions.position === 'full') { if (decoration.options.overviewRulerOptions && decoration.options.overviewRulerOptions.position === 'full') {
this._renderDecoration(decoration, updateAnchor); this._renderDecoration(decoration);
} }
} }
this._shouldUpdateDimensions = false;
this._shouldUpdateAnchor = false;
} }
private _renderDecoration(decoration: IInternalDecoration, updateAnchor?: boolean): void { private _renderDecoration(decoration: IInternalDecoration): void {
const element = this._decorationElements.get(decoration); const element = this._decorationElements.get(decoration);
if (!element) { if (!element) {
this._decorationElements.set(decoration, this._canvas); this._decorationElements.set(decoration, this._canvas);
decoration.onDispose(() => this._queueRefresh()); decoration.onDispose(() => this._queueRefresh());
} }
this._refreshStyle(decoration, updateAnchor); this._refreshStyle(decoration);
} }
private _queueRefresh(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void { private _queueRefresh(updateCanvasDimensions?: boolean, updateAnchor?: boolean): void {
this._shouldUpdateDimensions = updateCanvasDimensions || this._shouldUpdateDimensions;
this._shouldUpdateAnchor = updateAnchor || this._shouldUpdateAnchor;
if (this._animationFrame !== undefined) { if (this._animationFrame !== undefined) {
return; return;
} }
this._animationFrame = window.requestAnimationFrame(() => { this._animationFrame = window.requestAnimationFrame(() => {
this._refreshDecorations(updateCanvasDimensions, updateAnchor); this._refreshDecorations();
this._animationFrame = undefined; this._animationFrame = undefined;
}); });
} }
+2 -1
View File
@@ -613,7 +613,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.optionsService.onOptionChange(() => { this.optionsService.onOptionChange(() => {
if (!this._overviewRulerRenderer && this.options.overviewRulerWidth && this._viewportElement && this.screenElement) { if (!this._overviewRulerRenderer && this.options.overviewRulerWidth && this._viewportElement && this.screenElement) {
this._overviewRulerRenderer = this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement); this._overviewRulerRenderer = this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement);
}}); }
});
// Measure the character size // Measure the character size
this._charSizeService.measure(); this._charSizeService.measure();
+1
View File
@@ -371,6 +371,7 @@ export class MockRenderService implements IRenderService {
public serviceBrand: undefined; public serviceBrand: undefined;
public onDimensionsChange: IEvent<IRenderDimensions> = new EventEmitter<IRenderDimensions>().event; public onDimensionsChange: IEvent<IRenderDimensions> = new EventEmitter<IRenderDimensions>().event;
public onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; public onRenderedBufferChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event;
public onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event;
public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event;
public dimensions: IRenderDimensions = { public dimensions: IRenderDimensions = {
scaledCharWidth: 0, scaledCharWidth: 0,
+5 -2
View File
@@ -39,8 +39,10 @@ export class RenderService extends Disposable implements IRenderService {
private _onDimensionsChange = new EventEmitter<IRenderDimensions>(); private _onDimensionsChange = new EventEmitter<IRenderDimensions>();
public get onDimensionsChange(): IEvent<IRenderDimensions> { return this._onDimensionsChange.event; } public get onDimensionsChange(): IEvent<IRenderDimensions> { return this._onDimensionsChange.event; }
private _onRenderedBufferChange = new EventEmitter<{ start: number, end: number }>();
public get onRenderedBufferChange(): IEvent<{ start: number, end: number }> { return this._onRenderedBufferChange.event; }
private _onRender = new EventEmitter<{ start: number, end: number }>(); private _onRender = new EventEmitter<{ start: number, end: number }>();
public get onRenderedBufferChange(): IEvent<{ start: number, end: number }> { return this._onRender.event; } public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; }
private _onRefreshRequest = new EventEmitter<{ start: number, end: number }>(); private _onRefreshRequest = new EventEmitter<{ start: number, end: number }>();
public get onRefreshRequest(): IEvent<{ start: number, end: number }> { return this._onRefreshRequest.event; } public get onRefreshRequest(): IEvent<{ start: number, end: number }> { return this._onRefreshRequest.event; }
@@ -122,8 +124,9 @@ export class RenderService extends Disposable implements IRenderService {
// Fire render event only if it was not a redraw // Fire render event only if it was not a redraw
if (!this._isNextRenderRedrawOnly) { if (!this._isNextRenderRedrawOnly) {
this._onRender.fire({ start, end }); this._onRenderedBufferChange.fire({ start, end });
} }
this._onRender.fire({ start, end });
this._isNextRenderRedrawOnly = true; this._isNextRenderRedrawOnly = true;
} }
+4
View File
@@ -50,6 +50,10 @@ export interface IRenderService extends IDisposable {
* or selections are rendered. * or selections are rendered.
*/ */
onRenderedBufferChange: IEvent<{ start: number, end: number }>; onRenderedBufferChange: IEvent<{ start: number, end: number }>;
/**
* Fires on render
*/
onRender: IEvent<{ start: number, end: number }>;
onRefreshRequest: IEvent<{ start: number, end: number }>; onRefreshRequest: IEvent<{ start: number, end: number }>;
dimensions: IRenderDimensions; dimensions: IRenderDimensions;