Make terminal rendering work in popout windows

Add support for the parent element (what is passed to Terminal.open)
being in a different (same origin) window. Accesses to DOM APIs such
as requestAnimationFrame and devicePixelRatio thus need to be scoped
to the corrent window, instead of assuming that it's the same as the
window/global scope where the code is running.

This is done by inferring a parent window at the creation time, and
then storing it in CoreBrowserService, which is already passed to most
places that need it.

To catch future regressions, an ESLint rule that checks for global
accesses is added (it uses AST selectors via the no-restricted-syntax
rule).

This should also be applicable when the parent element is an iframe.

Fixes #3758
This commit is contained in:
Mihai Parparita
2022-09-08 16:59:31 -07:00
parent 2935d9feb7
commit a39a468f19
31 changed files with 255 additions and 176 deletions
@@ -5,7 +5,7 @@
import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
import { addDisposableDomListener } from 'browser/Lifecycle';
import { IRenderService } from 'browser/services/Services';
import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
import { Disposable } from 'common/Lifecycle';
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
@@ -51,7 +51,8 @@ export class OverviewRulerRenderer extends Disposable {
@IBufferService private readonly _bufferService: IBufferService,
@IDecorationService private readonly _decorationService: IDecorationService,
@IRenderService private readonly _renderService: IRenderService,
@IOptionsService private readonly _optionsService: IOptionsService
@IOptionsService private readonly _optionsService: IOptionsService,
@ICoreBrowserService private readonly _coreBrowseService: ICoreBrowserService
) {
super();
this._canvas = document.createElement('canvas');
@@ -112,7 +113,7 @@ export class OverviewRulerRenderer extends Disposable {
}
}));
// device pixel ratio changed
this.register(addDisposableDomListener(window, 'resize', () => {
this.register(addDisposableDomListener(this._coreBrowseService.window, 'resize', () => {
this._queueRefresh(true);
}));
// set the canvas dimensions
@@ -142,11 +143,11 @@ export class OverviewRulerRenderer extends Disposable {
}
private _refreshDrawHeightConstants(): void {
drawHeight.full = Math.round(2 * window.devicePixelRatio);
drawHeight.full = Math.round(2 * this._coreBrowseService.dpr);
// Calculate actual pixels per line
const pixelsPerLine = this._canvas.height / this._bufferService.buffer.lines.length;
// Clamp actual pixels within a range
const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * window.devicePixelRatio);
const nonFullHeight = Math.round(Math.max(Math.min(pixelsPerLine, 12), 6) * this._coreBrowseService.dpr);
drawHeight.left = nonFullHeight;
drawHeight.center = nonFullHeight;
drawHeight.right = nonFullHeight;
@@ -164,9 +165,9 @@ export class OverviewRulerRenderer extends Disposable {
private _refreshCanvasDimensions(): void {
this._canvas.style.width = `${this._width}px`;
this._canvas.width = Math.round(this._width * window.devicePixelRatio);
this._canvas.width = Math.round(this._width * this._coreBrowseService.dpr);
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 * this._coreBrowseService.dpr);
this._refreshDrawConstants();
this._refreshColorZonePadding();
}
@@ -220,7 +221,7 @@ export class OverviewRulerRenderer extends Disposable {
if (this._animationFrame !== undefined) {
return;
}
this._animationFrame = window.requestAnimationFrame(() => {
this._animationFrame = this._coreBrowseService.window.requestAnimationFrame(() => {
this._refreshDecorations();
this._animationFrame = undefined;
});