diff --git a/addons/xterm-addon-search/package.json b/addons/xterm-addon-search/package.json index 1913f177..445f70c9 100644 --- a/addons/xterm-addon-search/package.json +++ b/addons/xterm-addon-search/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-search", - "version": "0.5.0", + "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-serialize/package.json b/addons/xterm-addon-serialize/package.json index fbf1614e..4b52e814 100644 --- a/addons/xterm-addon-serialize/package.json +++ b/addons/xterm-addon-serialize/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-serialize", - "version": "0.1.2", + "version": "0.2.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-web-links/package.json b/addons/xterm-addon-web-links/package.json index 6167de74..febcfab4 100644 --- a/addons/xterm-addon-web-links/package.json +++ b/addons/xterm-addon-web-links/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-web-links", - "version": "0.2.1", + "version": "0.3.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-web-links/src/WebLinkProvider.ts b/addons/xterm-addon-web-links/src/WebLinkProvider.ts index 23dc8560..5f6460bf 100644 --- a/addons/xterm-addon-web-links/src/WebLinkProvider.ts +++ b/addons/xterm-addon-web-links/src/WebLinkProvider.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ILinkProvider, IBufferCellPosition, ILink, Terminal, IBuffer } from 'xterm'; +import { ILinkProvider, IBufferCellPosition, ILink, Terminal } from 'xterm'; export class WebLinkProvider implements ILinkProvider { diff --git a/addons/xterm-addon-web-links/src/WebLinksAddon.ts b/addons/xterm-addon-web-links/src/WebLinksAddon.ts index dbc664a8..4e700b57 100644 --- a/addons/xterm-addon-web-links/src/WebLinksAddon.ts +++ b/addons/xterm-addon-web-links/src/WebLinksAddon.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal, ILinkMatcherOptions, ITerminalAddon, ILinkProvider, IDisposable } from 'xterm'; +import { Terminal, ILinkMatcherOptions, ITerminalAddon, IDisposable } from 'xterm'; import { WebLinkProvider } from './WebLinkProvider'; const protocolClause = '(https?:\\/\\/)'; diff --git a/addons/xterm-addon-webgl/package.json b/addons/xterm-addon-webgl/package.json index ca49e795..7a1a9ee5 100644 --- a/addons/xterm-addon-webgl/package.json +++ b/addons/xterm-addon-webgl/package.json @@ -1,6 +1,6 @@ { "name": "xterm-addon-webgl", - "version": "0.5.1", + "version": "0.6.0", "author": { "name": "The xterm.js authors", "url": "https://xtermjs.org/" diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts index 591d7fff..daf7f6fc 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.api.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.api.ts @@ -341,10 +341,6 @@ describe('WebGL Renderer Integration Tests', async () => { await writeSync(page, data); for (let y = 0; y < 240 / 16; y++) { for (let x = 0; x < 16; x++) { - const cssColor = COLORS_16_TO_255[y * 16 + x]; - const r = parseInt(cssColor.substr(1, 2), 16); - const g = parseInt(cssColor.substr(3, 2), 16); - const b = parseInt(cssColor.substr(5, 2), 16); await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]); } } @@ -670,7 +666,6 @@ describe('WebGL Renderer Integration Tests', async () => { await writeSync(page, data); for (let y = 0; y < 16; y++) { for (let x = 0; x < 16; x++) { - const i = y * 16 + x; await pollFor(page, () => getCellColor(x + 1, y + 1), [0, 0, 0, 255]); } } diff --git a/bin/extract_vtfeatures.js b/bin/extract_vtfeatures.js index e575aeab..63d09684 100644 --- a/bin/extract_vtfeatures.js +++ b/bin/extract_vtfeatures.js @@ -1,7 +1,7 @@ /** * Copyright (c) 2019 The xterm.js authors. All rights reserved. * @license MIT - * + * * Script to extract vt features documented in docstrings. */ const fs = require('fs'); @@ -265,7 +265,7 @@ To denote the sequences the tables use the same abbreviations as xterm does: function hideDetailSections() { for (let section of document.getElementsByClassName('sequence-details')) section.style.display = 'none'; } - + function decorateDetailLinks() { for (let link of document.getElementsByClassName('link-details')) { link.addEventListener("click", toggleDetails, false); @@ -344,11 +344,11 @@ function applyMacros(s) { return s; } -function replaceStatus(s) { - if (s === 'supported') return ''; - if (s === 'unsupported') return ''; - return s; -} +// function replaceStatus(s) { +// if (s === 'supported') return ''; +// if (s === 'unsupported') return ''; +// return s; +// } function createAnchorSlug(s) { return s.toLowerCase().split(' ').join('-'); diff --git a/package.json b/package.json index b177851a..df6208c8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xterm", "description": "Full xterm terminal, in your browser", - "version": "4.4.0", + "version": "4.5.0", "main": "lib/xterm.js", "style": "css/xterm.css", "types": "typings/xterm.d.ts", diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 60861112..3e304bcf 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -4,7 +4,9 @@ */ import { IEvent, EventEmitter } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService } from 'browser/services/Services'; +import { ICharSizeService, IMouseService, IRenderService } from 'browser/services/Services'; +import { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types'; +import { IColorSet } from 'browser/Types'; export class MockCharSizeService implements ICharSizeService { serviceBrand: any; @@ -24,3 +26,72 @@ export class MockMouseService implements IMouseService { throw new Error('Not implemented'); } } + +export class MockRenderService implements IRenderService { + serviceBrand: any; + onDimensionsChange: IEvent = new EventEmitter().event; + onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; + onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; + dimensions: IRenderDimensions = { + scaledCharWidth: 0, + scaledCharHeight: 0, + scaledCellWidth: 0, + scaledCellHeight: 0, + scaledCharLeft: 0, + scaledCharTop: 0, + scaledCanvasWidth: 0, + scaledCanvasHeight: 0, + canvasWidth: 0, + canvasHeight: 0, + actualCellWidth: 0, + actualCellHeight: 0 + }; + refreshRows(start: number, end: number): void { + throw new Error('Method not implemented.'); + } + resize(cols: number, rows: number): void { + throw new Error('Method not implemented.'); + } + changeOptions(): void { + throw new Error('Method not implemented.'); + } + setRenderer(renderer: IRenderer): void { + throw new Error('Method not implemented.'); + } + setColors(colors: IColorSet): void { + throw new Error('Method not implemented.'); + } + onDevicePixelRatioChange(): void { + throw new Error('Method not implemented.'); + } + onResize(cols: number, rows: number): void { + throw new Error('Method not implemented.'); + } + onCharSizeChanged(): void { + throw new Error('Method not implemented.'); + } + onBlur(): void { + throw new Error('Method not implemented.'); + } + onFocus(): void { + throw new Error('Method not implemented.'); + } + onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void { + throw new Error('Method not implemented.'); + } + onCursorMove(): void { + throw new Error('Method not implemented.'); + } + clear(): void { + throw new Error('Method not implemented.'); + } + registerCharacterJoiner(handler: CharacterJoinerHandler): number { + throw new Error('Method not implemented.'); + } + deregisterCharacterJoiner(joinerId: number): boolean { + throw new Error('Method not implemented.'); + } + dispose(): void { + throw new Error('Method not implemented.'); + } +} diff --git a/src/browser/input/MoveToCell.ts b/src/browser/input/MoveToCell.ts index d8f5a498..25e1844d 100644 --- a/src/browser/input/MoveToCell.ts +++ b/src/browser/input/MoveToCell.ts @@ -105,11 +105,6 @@ function moveToRequestedCol(startX: number, startY: number, targetX: number, tar ).length, sequence(direction, applicationCursor)); } -function moveHorizontallyOnly(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string { - const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor); - return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor)); -} - /** * Utility functions */ diff --git a/src/browser/services/SelectionService.test.ts b/src/browser/services/SelectionService.test.ts index 62ca3819..cd787531 100644 --- a/src/browser/services/SelectionService.test.ts +++ b/src/browser/services/SelectionService.test.ts @@ -10,16 +10,18 @@ import { IBufferLine } from 'common/Types'; import { MockBufferService, MockOptionsService, MockCoreService } from 'common/TestUtils.test'; import { BufferLine } from 'common/buffer/BufferLine'; import { IBufferService, IOptionsService } from 'common/services/Services'; -import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test'; +import { MockMouseService, MockRenderService } from 'browser/TestUtils.test'; import { CellData } from 'common/buffer/CellData'; import { IBuffer } from 'common/buffer/Types'; +import { IRenderService } from 'browser/services/Services'; class TestSelectionService extends SelectionService { constructor( bufferService: IBufferService, - optionsService: IOptionsService + optionsService: IOptionsService, + renderService: IRenderService ) { - super(() => {}, null!, null!, new MockCharSizeService(10, 10), bufferService, new MockCoreService(), new MockMouseService(), optionsService); + super(() => {}, null!, null!, bufferService, new MockCoreService(), new MockMouseService(), optionsService, renderService); } public get model(): SelectionModel { return this._model; } @@ -46,7 +48,10 @@ describe('SelectionService', () => { optionsService = new MockOptionsService(); bufferService = new MockBufferService(20, 20, optionsService); buffer = bufferService.buffer; - selectionService = new TestSelectionService(bufferService, optionsService); + const renderService = new MockRenderService(); + renderService.dimensions.canvasHeight = 10 * 20; + renderService.dimensions.canvasWidth = 10 * 20; + selectionService = new TestSelectionService(bufferService, optionsService, renderService); }); function stringToRow(text: string): IBufferLine { diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index f2f46a94..45424d16 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -10,7 +10,7 @@ import * as Browser from 'common/Platform'; import { SelectionModel } from 'browser/selection/SelectionModel'; import { CellData } from 'common/buffer/CellData'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { ICharSizeService, IMouseService, ISelectionService } from 'browser/services/Services'; +import { ICharSizeService, IMouseService, ISelectionService, IRenderService } from 'browser/services/Services'; import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services'; import { getCoordsRelativeToElement } from 'browser/input/Mouse'; import { moveToCellSequence } from 'browser/input/MoveToCell'; @@ -116,11 +116,11 @@ export class SelectionService implements ISelectionService { private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void, private readonly _element: HTMLElement, private readonly _screenElement: HTMLElement, - @ICharSizeService private readonly _charSizeService: ICharSizeService, @IBufferService private readonly _bufferService: IBufferService, @ICoreService private readonly _coreService: ICoreService, @IMouseService private readonly _mouseService: IMouseService, - @IOptionsService private readonly _optionsService: IOptionsService + @IOptionsService private readonly _optionsService: IOptionsService, + @IRenderService private readonly _renderService: IRenderService ) { // Init listeners this._mouseMoveListener = event => this._onMouseMove(event); @@ -374,7 +374,7 @@ export class SelectionService implements ISelectionService { */ private _getMouseEventScrollAmount(event: MouseEvent): number { let offset = getCoordsRelativeToElement(event, this._screenElement)[1]; - const terminalHeight = this._bufferService.rows * Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight); + const terminalHeight = this._renderService.dimensions.canvasHeight; if (offset >= 0 && offset <= terminalHeight) { return 0; } diff --git a/src/common/input/Keyboard.test.ts b/src/common/input/Keyboard.test.ts index a304923e..0bb0e24c 100644 --- a/src/common/input/Keyboard.test.ts +++ b/src/common/input/Keyboard.test.ts @@ -86,6 +86,12 @@ describe('Keyboard', () => { it('should return \\x1b[3;3~ for alt+delete', () => { assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~'); }); + it('should return \\x1b\\r for alt+enter', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 13 }).key, '\x1b\r'); + }); + it('should return \\x1b\\x1b for alt+esc', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 27 }).key, '\x1b\x1b'); + }); it('should return \\x1b[5D for ctrl+left', () => { assert.equal(testEvaluateKeyboardEvent({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D }); @@ -141,6 +147,10 @@ describe('Keyboard', () => { it('should return \\x1ba for alt+a', () => { assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 65 }, { isMac: true, macOptionIsMeta: true }).key, '\x1ba'); }); + + it('should return \\x1b\\x1b for alt+enter', () => { + assert.equal(testEvaluateKeyboardEvent({ altKey: true, keyCode: 13 }, { isMac: true, macOptionIsMeta: true }).key, '\x1b\r'); + }); }); it('should return \\x1b[5A for alt+up', () => { diff --git a/src/common/input/Keyboard.ts b/src/common/input/Keyboard.ts index 1bf378c1..fdb777b4 100644 --- a/src/common/input/Keyboard.ts +++ b/src/common/input/Keyboard.ts @@ -103,12 +103,15 @@ export function evaluateKeyboardEvent( break; case 13: // return/enter - result.key = C0.CR; + result.key = ev.altKey ? C0.ESC + C0.CR : C0.CR; result.cancel = true; break; case 27: // escape result.key = C0.ESC; + if (ev.altKey) { + result.key = C0.ESC + C0.ESC; + } result.cancel = true; break; case 37: diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index bc58a688..cc35d5b5 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -5,7 +5,7 @@ import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { IDecPrivateModes, ICharset } from 'common/Types'; +import { IDecPrivateModes } from 'common/Types'; import { clone } from 'common/Clone'; const DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({