From 18871f0d3cf3fd41b641ec5dcfb809c3ddd82657 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Mon, 1 Oct 2018 13:30:13 -0700 Subject: [PATCH 01/16] Cleared terminal lines should have isWrapped reset Fixes #1710 --- src/InputHandler.ts | 21 ++++++++++++++++++--- src/addons/search/SearchHelper.ts | 2 +- src/addons/search/search.test.ts | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index ad5aad39..9a0aae08 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -730,6 +730,21 @@ export class InputHandler extends Disposable implements IInputHandler { ); } + /** + * Helper method to reset cells in a terminal row. + * The cell gets replaced with the eraseChar of the terminal and the isWrapped property is set to false. + * @param y row index + */ + private _resetBufferLine(y: number): void { + const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y); + line.replaceCells( + 0, + this._terminal.cols, + [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE] + ); + line.isWrapped = false; + } + /** * CSI Ps J Erase in Display (ED). * Ps = 0 -> Erase Below (default). @@ -750,7 +765,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.updateRange(j); this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols); for (; j < this._terminal.rows; j++) { - this._eraseInBufferLine(j, 0, this._terminal.cols); + this._resetBufferLine(j); } this._terminal.updateRange(j); break; @@ -759,7 +774,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._terminal.updateRange(j); this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1); while (j--) { - this._eraseInBufferLine(j, 0, this._terminal.cols); + this._resetBufferLine(j); } this._terminal.updateRange(0); break; @@ -767,7 +782,7 @@ export class InputHandler extends Disposable implements IInputHandler { j = this._terminal.rows; this._terminal.updateRange(j - 1); while (j--) { - this._eraseInBufferLine(j, 0, this._terminal.cols); + this._resetBufferLine(j); } this._terminal.updateRange(0); break; diff --git a/src/addons/search/SearchHelper.ts b/src/addons/search/SearchHelper.ts index d07c6b2c..da09f83f 100644 --- a/src/addons/search/SearchHelper.ts +++ b/src/addons/search/SearchHelper.ts @@ -191,7 +191,7 @@ export class SearchHelper implements ISearchHelper { do { const nextLine = this._terminal._core.buffer.lines.get(lineIndex + 1); lineWrapsToNext = nextLine ? nextLine.isWrapped : false; - lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight); + lineString += this._terminal._core.buffer.translateBufferLineToString(lineIndex, !lineWrapsToNext && trimRight).substring(0, this._terminal.cols); lineIndex++; } while (lineWrapsToNext); diff --git a/src/addons/search/search.test.ts b/src/addons/search/search.test.ts index ccdebaf3..b22c22a5 100644 --- a/src/addons/search/search.test.ts +++ b/src/addons/search/search.test.ts @@ -82,6 +82,9 @@ describe('search addon', () => { expect(hello3).eql(undefined); expect(llo).eql(undefined); expect(goodbye).eql({col: 0, row: 5, term: 'goodbye'}); + term.core.resize(9, 5); + const hello0Resize = term.searchHelper.findInLine('Hello', 0); + expect(hello0Resize).eql({col: 8, row: 0, term: 'Hello'}); }); it('should respect search regex', () => { search.apply(MockTerminal); From 6e350219aaac512c23493252dc556e27cee87518 Mon Sep 17 00:00:00 2001 From: leomoty Date: Mon, 8 Oct 2018 23:17:45 -0300 Subject: [PATCH 02/16] Support for lineHeight in DOM Renderer --- src/renderer/dom/DomRenderer.ts | 27 ++++++++++++++------------- typings/xterm.d.ts | 1 - 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index 8f51c4ef..bd0a6b02 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) { @@ -290,10 +291,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/typings/xterm.d.ts b/typings/xterm.d.ts index b5a8a109..f809c2ed 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -161,7 +161,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 */ From f2ecd06e64dcbfdc3cbfdc24bac59f52d1255569 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 10 Oct 2018 15:31:49 +0200 Subject: [PATCH 03/16] Additional isWrapped clearing --- src/InputHandler.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 9a0aae08..97001d0a 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -722,12 +722,16 @@ export class InputHandler extends Disposable implements IInputHandler { * @param start first cell index to be erased * @param end end - 1 is last erased cell */ - private _eraseInBufferLine(y: number, start: number, end: number): void { - this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y).replaceCells( + private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void { + const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y); + line.replaceCells( start, end, [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE] ); + if (clearWrap) { + line.isWrapped = false; + } } /** @@ -736,13 +740,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @param y row index */ private _resetBufferLine(y: number): void { - const line = this._terminal.buffer.lines.get(this._terminal.buffer.ybase + y); - line.replaceCells( - 0, - this._terminal.cols, - [this._terminal.eraseAttr(), NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE] - ); - line.isWrapped = false; + this._eraseInBufferLine(y, 0, this._terminal.cols, true); } /** @@ -763,7 +761,11 @@ export class InputHandler extends Disposable implements IInputHandler { case 0: j = this._terminal.buffer.y; this._terminal.updateRange(j); - this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols); + if (this._terminal.buffer.x !== 0) { + this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols); + } else { + this._resetBufferLine(j++); + } for (; j < this._terminal.rows; j++) { this._resetBufferLine(j); } From 64d6354983600b7323b49d875405ff38f2379f18 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 11 Oct 2018 11:18:56 +0200 Subject: [PATCH 04/16] Added testing and better erase left and above handling --- src/InputHandler.test.ts | 30 ++++++++++++++++++++++++++++++ src/InputHandler.ts | 13 +++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 722cc287..0e610fc0 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -444,6 +444,36 @@ describe('InputHandler', () => { termNew.buffer.x = 40; inputHandlerNew.eraseInDisplay([2]); expect(termContent(termNew)).eql(termContent(termOld)); + + // reset and add a wrapped line + termNew.buffer.y = 0; + termNew.buffer.x = 0; + inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); // line 0 + inputHandlerNew.parse(Array(termNew.cols + 10).join('a')); // line 1 and 2 + for (let i = 3; i < termOld.rows; ++i) inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); + + // params[1] left and above with wrap + // confirm precondition that line 2 is wrapped + expect(termNew.buffer.lines.get(2).isWrapped).true; + termNew.buffer.y = 2; + termNew.buffer.x = 40; + inputHandlerNew.eraseInDisplay([1]); + expect(termNew.buffer.lines.get(2).isWrapped).false; + + // reset and add a wrapped line + termNew.buffer.y = 0; + termNew.buffer.x = 0; + inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); // line 0 + inputHandlerNew.parse(Array(termNew.cols + 10).join('a')); // line 1 and 2 + for (let i = 3; i < termOld.rows; ++i) inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); + + // params[1] left and above with wrap + // confirm precondition that line 2 is wrapped + expect(termNew.buffer.lines.get(2).isWrapped).true; + termNew.buffer.y = 1; + termNew.buffer.x = 90; // Cursor is beyond last column + inputHandlerNew.eraseInDisplay([1]); + expect(termNew.buffer.lines.get(2).isWrapped).false; }); }); it('convertEol setting', function(): void { diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 97001d0a..2fcfac27 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -761,11 +761,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 0: j = this._terminal.buffer.y; this._terminal.updateRange(j); - if (this._terminal.buffer.x !== 0) { - this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols); - } else { - this._resetBufferLine(j++); - } + this._eraseInBufferLine(j++, this._terminal.buffer.x, this._terminal.cols, this._terminal.buffer.x === 0); for (; j < this._terminal.rows; j++) { this._resetBufferLine(j); } @@ -774,7 +770,12 @@ export class InputHandler extends Disposable implements IInputHandler { case 1: j = this._terminal.buffer.y; this._terminal.updateRange(j); - this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1); + // Deleted front part of line and everything before. This line will no longer be wrapped. + this._eraseInBufferLine(j, 0, this._terminal.buffer.x + 1, true); + if (this._terminal.buffer.x + 1 >= this._terminal.cols) { + // Deleted entire previous line. This next line can no longer be wrapped. + this._terminal.buffer.lines.get(j + 1).isWrapped = false; + } while (j--) { this._resetBufferLine(j); } From 375b5c5b4f1334ea06ad64d2a22af2c00d031e33 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 11 Oct 2018 09:02:36 -0700 Subject: [PATCH 05/16] Fix indent --- src/InputHandler.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index 0e610fc0..04b7a173 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -461,7 +461,7 @@ describe('InputHandler', () => { expect(termNew.buffer.lines.get(2).isWrapped).false; // reset and add a wrapped line - termNew.buffer.y = 0; + termNew.buffer.y = 0; termNew.buffer.x = 0; inputHandlerNew.parse(Array(termNew.cols + 1).join('a')); // line 0 inputHandlerNew.parse(Array(termNew.cols + 10).join('a')); // line 1 and 2 From 9e1551e2f14f76d098b2b8d293dd6c3ef57d7255 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 11 Oct 2018 09:37:19 -0700 Subject: [PATCH 06/16] Fix NPE in DOM renderer underline Fixes #1747 --- src/renderer/dom/DomRenderer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index 8f51c4ef..adce57bc 100644 --- a/src/renderer/dom/DomRenderer.ts +++ b/src/renderer/dom/DomRenderer.ts @@ -352,7 +352,11 @@ export class DomRenderer extends EventEmitter implements IRenderer { private _setCellUnderline(x: number, x2: number, y: number, y2: number, cols: number, enabled: boolean): void { while (x !== x2 || y !== y2) { - const span = this._rowElements[y].children[x]; + const row = this._rowElements[y]; + if (!row) { + return; + } + const span = row.children[x]; span.style.textDecoration = enabled ? 'underline' : 'none'; x = (x + 1) % cols; if (x === 0) { From a0250c5cea4c8c310c9f5b3dca7a630786465c6a Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 12 Oct 2018 08:33:59 -0700 Subject: [PATCH 07/16] Improve types for listener args in .d.ts Without this consumers need an undefined check with strictNullChecks turned on. --- typings/xterm.d.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b5a8a109..8676a458 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -388,37 +388,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. From 19f6c0a940e1d3e43e66ced78089ec1d976a72d2 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 12 Oct 2018 09:01:56 -0700 Subject: [PATCH 08/16] Fix tests --- src/utils/TestUtils.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From 8bd49cba35617699f6c69bf7b648b66b6cb17057 Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Fri, 21 Sep 2018 23:20:38 -0500 Subject: [PATCH 09/16] Fill inserted lines with background color When scrolling occurs due to a LF or scroll code, fill the new line with the currently-set background color. --- src/Terminal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index c995af62..55e212e0 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1174,7 +1174,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II * @param isWrapped Whether the new line is wrapped from the previous line. */ public scroll(isWrapped?: boolean): void { - const newLine = this.buffer.getBlankLine(DEFAULT_ATTR, isWrapped); + const newLine = this.buffer.getBlankLine(this.eraseAttr(), isWrapped); const topRow = this.buffer.ybase + this.buffer.scrollTop; const bottomRow = this.buffer.ybase + this.buffer.scrollBottom; From 4d556fcaf0b6158d5327ef6df61b908bb01893db Mon Sep 17 00:00:00 2001 From: Jeff Smith Date: Tue, 23 Oct 2018 11:57:20 -0500 Subject: [PATCH 10/16] Check for focus on document as well as on textarea When clicking outside of the browser document area, the cursor does not appear to get 'blurred'. This can be confusing as it implies that the cursor is still active. This is caused by Terminal's isFocused getter only checking if the textarea is the active element of the document. Expand isFocused to also check that the document itself has focus. --- src/Terminal.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index c995af62..a7b87027 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -342,7 +342,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II } public get isFocused(): boolean { - return document.activeElement === this.textarea; + return document.activeElement === this.textarea && document.hasFocus(); } /** From c2994b0ae1b72fffe95312ef74c5d32897ac82a7 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 23 Oct 2018 15:45:52 -0700 Subject: [PATCH 11/16] Remove request term info handler We're not supporting it anyway, no point having it. --- src/InputHandler.ts | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index ddb20527..a282031b 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -24,26 +24,6 @@ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, * DCS subparser implementations */ - /** - * DCS + q Pt ST (xterm) - * Request Terminfo String - * not supported - */ -class RequestTerminfo implements IDcsHandler { - private _data: string; - constructor(private _terminal: any) { } - hook(collect: string, params: number[], flag: number): void { - this._data = ''; - } - put(data: string, start: number, end: number): void { - this._data += data.substring(start, end); - } - unhook(): void { - // invalid: DCS 0 + r Pt ST - this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`); - } -} - /** * DCS $ q Pt ST * DECRQSS (https://vt100.net/docs/vt510-rm/DECRQSS.html) @@ -86,7 +66,7 @@ class DECRQSS implements IDcsHandler { default: // invalid: DCS 0 $ r Pt ST (xterm) this._terminal.error('Unknown DCS $q %s', this._data); - this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`); + this._terminal.handler(`${C0.ESC}P0$r${C0.ESC}\\`); } } } @@ -287,7 +267,6 @@ export class InputHandler extends Disposable implements IInputHandler { * DCS handler */ this._parser.setDcsHandler('$q', new DECRQSS(this._terminal)); - this._parser.setDcsHandler('+q', new RequestTerminfo(this._terminal)); } public dispose(): void { From 213dadf1bd12a5ca796214a796f4c6443b5b75b5 Mon Sep 17 00:00:00 2001 From: Shengdun Hua Date: Thu, 25 Oct 2018 23:01:03 +0800 Subject: [PATCH 12/16] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 17833598..551a94f4 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,7 @@ computational environment for Jupyter, supporting interactive data science and s - [**SSH Web Client**](https://github.com/roke22/PHP-SSH2-Web-Client): SSH Web Client with PHP. - [**Shellvault**](https://www.shellvault.io): The cloud-based SSH terminal you can access from anywhere. - [**Juno**](http://junolab.org/): A flexible Julia IDE, based on Atom. +- [**webssh**](https://github.com/huashengdun/webssh): Web based ssh client. [And much more...](https://github.com/xtermjs/xterm.js/network/dependents) From 793516060fe95dc305c16799dd73d243e8b75e74 Mon Sep 17 00:00:00 2001 From: leomoty Date: Sun, 28 Oct 2018 14:24:08 -0300 Subject: [PATCH 13/16] Recreate mouseHelper after renderer is disposed --- src/Terminal.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Terminal.ts b/src/Terminal.ts index 63315008..8a837337 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -473,6 +473,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (this._theme) { this.renderer.setTheme(this._theme); } + this.mouseHelper = new MouseHelper(this.renderer); break; case 'scrollback': this.buffers.resize(this.cols, this.rows); From 41b1c929e0d860100c9dca2f39aa0c08ac04a361 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 28 Oct 2018 10:50:16 -0700 Subject: [PATCH 14/16] Fix screen element remaining large if originally using canvas --- src/renderer/dom/DomRenderer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/renderer/dom/DomRenderer.ts b/src/renderer/dom/DomRenderer.ts index d55d2416..22ecd0cd 100644 --- a/src/renderer/dom/DomRenderer.ts +++ b/src/renderer/dom/DomRenderer.ts @@ -131,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 { From 108438dbebd053df4cc01e3a74174534a3a291d9 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sun, 28 Oct 2018 10:51:57 -0700 Subject: [PATCH 15/16] Use setRenderer instead of ctor Just in case something hangs onto MouseHelper --- src/Terminal.ts | 2 +- src/utils/MouseHelper.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index 8a837337..e8871462 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -473,7 +473,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II if (this._theme) { this.renderer.setTheme(this._theme); } - this.mouseHelper = new MouseHelper(this.renderer); + this.mouseHelper.setRenderer(this.renderer); break; case 'scrollback': this.buffers.resize(this.cols, this.rows); 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) { From 160b4a7d669b6c527fec1bc40a18ae79db7d19de Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 30 Oct 2018 11:04:32 -0700 Subject: [PATCH 16/16] Revert "Remove request term info handler" This reverts commit c2994b0ae1b72fffe95312ef74c5d32897ac82a7. --- src/InputHandler.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 091f41cf..a34590ef 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -24,6 +24,26 @@ const GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, * DCS subparser implementations */ + /** + * DCS + q Pt ST (xterm) + * Request Terminfo String + * not supported + */ +class RequestTerminfo implements IDcsHandler { + private _data: string; + constructor(private _terminal: any) { } + hook(collect: string, params: number[], flag: number): void { + this._data = ''; + } + put(data: string, start: number, end: number): void { + this._data += data.substring(start, end); + } + unhook(): void { + // invalid: DCS 0 + r Pt ST + this._terminal.handler(`${C0.ESC}P0+r${this._data}${C0.ESC}\\`); + } +} + /** * DCS $ q Pt ST * DECRQSS (https://vt100.net/docs/vt510-rm/DECRQSS.html) @@ -66,7 +86,7 @@ class DECRQSS implements IDcsHandler { default: // invalid: DCS 0 $ r Pt ST (xterm) this._terminal.error('Unknown DCS $q %s', this._data); - this._terminal.handler(`${C0.ESC}P0$r${C0.ESC}\\`); + this._terminal.handler(`${C0.ESC}P0$r${this._data}${C0.ESC}\\`); } } } @@ -267,6 +287,7 @@ export class InputHandler extends Disposable implements IInputHandler { * DCS handler */ this._parser.setDcsHandler('$q', new DECRQSS(this._terminal)); + this._parser.setDcsHandler('+q', new RequestTerminfo(this._terminal)); } public dispose(): void {