diff --git a/src/Terminal.ts b/src/Terminal.ts index 5b79750c..df73ca58 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -477,6 +477,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (this._theme) { this.renderer.setTheme(this._theme); } + this.mouseHelper.setRenderer(this.renderer); break; case 'scrollback': this.buffers.resize(this.cols, this.rows); diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index adce57bc..22ecd0cd 100644 --- a/src/renderer/dom/DomRenderer.ts +++ b/src/renderer/dom/DomRenderer.ts @@ -94,22 +94,23 @@ export class DomRenderer extends EventEmitter implements IRenderer { } private _updateDimensions(): void { - this.dimensions.scaledCharWidth = this._terminal.charMeasure.width * window.devicePixelRatio; - this.dimensions.scaledCharHeight = this._terminal.charMeasure.height * window.devicePixelRatio; - this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth; - this.dimensions.scaledCellHeight = this.dimensions.scaledCharHeight; + this.dimensions.scaledCharWidth = Math.floor(this._terminal.charMeasure.width * window.devicePixelRatio); + this.dimensions.scaledCharHeight = Math.ceil(this._terminal.charMeasure.height * window.devicePixelRatio); + this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._terminal.options.letterSpacing); + this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._terminal.options.lineHeight); this.dimensions.scaledCharLeft = 0; this.dimensions.scaledCharTop = 0; this.dimensions.scaledCanvasWidth = this.dimensions.scaledCellWidth * this._terminal.cols; this.dimensions.scaledCanvasHeight = this.dimensions.scaledCellHeight * this._terminal.rows; - this.dimensions.canvasWidth = this._terminal.charMeasure.width * this._terminal.cols; - this.dimensions.canvasHeight = this._terminal.charMeasure.height * this._terminal.rows; - this.dimensions.actualCellWidth = this._terminal.charMeasure.width; - this.dimensions.actualCellHeight = this._terminal.charMeasure.height; + this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio); + this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio); + this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._terminal.cols; + this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._terminal.rows; this._rowElements.forEach(element => { element.style.width = `${this.dimensions.canvasWidth}px`; - element.style.height = `${this._terminal.charMeasure.height}px`; + element.style.height = `${this.dimensions.actualCellHeight}px`; + element.style.lineHeight = `${this.dimensions.actualCellHeight}px`; }); if (!this._dimensionsStyleElement) { @@ -130,6 +131,8 @@ export class DomRenderer extends EventEmitter implements IRenderer { this._selectionContainer.style.height = (this._terminal)._viewportElement.style.height; this._rowContainer.style.width = `${this.dimensions.canvasWidth}px`; this._rowContainer.style.height = `${this.dimensions.canvasHeight}px`; + this._terminal.screenElement.style.width = ''; + this._terminal.screenElement.style.height = ''; } public setTheme(theme: ITheme | undefined): IColorSet { @@ -290,10 +293,10 @@ export class DomRenderer extends EventEmitter implements IRenderer { */ private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement { const element = document.createElement('div'); - element.style.height = `${rowCount * this._terminal.charMeasure.height}px`; - element.style.top = `${row * this._terminal.charMeasure.height}px`; - element.style.left = `${colStart * this._terminal.charMeasure.width}px`; - element.style.width = `${this._terminal.charMeasure.width * (colEnd - colStart)}px`; + element.style.height = `${rowCount * this.dimensions.actualCellHeight}px`; + element.style.top = `${row * this.dimensions.actualCellHeight}px`; + element.style.left = `${colStart * this.dimensions.actualCellWidth}px`; + element.style.width = `${this.dimensions.actualCellWidth * (colEnd - colStart)}px`; return element; } diff --git a/src/utils/MouseHelper.ts b/src/utils/MouseHelper.ts index 15f05742..ca1bb27e 100644 --- a/src/utils/MouseHelper.ts +++ b/src/utils/MouseHelper.ts @@ -9,6 +9,10 @@ import { IRenderer } from '../renderer/Types'; export class MouseHelper { constructor(private _renderer: IRenderer) {} + public setRenderer(renderer: IRenderer): void { + this._renderer = renderer; + } + public static getCoordsRelativeToElement(event: {pageX: number, pageY: number}, element: HTMLElement): [number, number] { // Ignore browsers that don't support MouseEvent.pageX if (event.pageX === null || event.pageX === undefined) { diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index f575855a..353e615f 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -121,7 +121,7 @@ export class MockTerminal implements ITerminal { handler(data: string): void { throw new Error('Method not implemented.'); } - on(event: string, callback: () => void): void { + on(event: string, callback: (...args: any[]) => void): void { throw new Error('Method not implemented.'); } off(type: string, listener: XtermListener): void { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 7fb33a9b..68e1e188 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -163,7 +163,6 @@ declare module 'xterm' { * when canvas is too slow for the environment. The following features do * not work when the DOM renderer is used: * - * - Line height * - Letter spacing * - Cursor blink */ @@ -390,37 +389,37 @@ declare module 'xterm' { * @param type The type of the event. * @param listener The listener. */ - on(type: 'key', listener: (key?: string, event?: KeyboardEvent) => void): void; + on(type: 'key', listener: (key: string, event: KeyboardEvent) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'keypress' | 'keydown', listener: (event?: KeyboardEvent) => void): void; + on(type: 'keypress' | 'keydown', listener: (event: KeyboardEvent) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'refresh', listener: (data?: {start: number, end: number}) => void): void; + on(type: 'refresh', listener: (data: {start: number, end: number}) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'resize', listener: (data?: {cols: number, rows: number}) => void): void; + on(type: 'resize', listener: (data: {cols: number, rows: number}) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'scroll', listener: (ydisp?: number) => void): void; + on(type: 'scroll', listener: (ydisp: number) => void): void; /** * Registers an event listener. * @param type The type of the event. * @param listener The listener. */ - on(type: 'title', listener: (title?: string) => void): void; + on(type: 'title', listener: (title: string) => void): void; /** * Registers an event listener. * @param type The type of the event.