From 45d1139ab0d65da874d9d99b37026e859270a5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 14 Nov 2019 12:20:59 +0100 Subject: [PATCH] windowOptions on ctor options --- src/InputHandler.test.ts | 28 +++++++++------------------ src/InputHandler.ts | 8 ++++---- src/common/TestUtils.test.ts | 1 + src/common/Types.d.ts | 1 - src/common/services/OptionsService.ts | 12 ++++++++---- src/common/services/Services.ts | 7 ++++--- typings/xterm.d.ts | 6 ++++++ 7 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/InputHandler.test.ts b/src/InputHandler.test.ts index afbef168..873998a6 100644 --- a/src/InputHandler.test.ts +++ b/src/InputHandler.test.ts @@ -17,7 +17,6 @@ import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsSer import { IBufferService } from 'common/services/Services'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { clone } from 'common/Clone'; -import { WindowOptions } from 'common/WindowOptions'; function getCursor(term: TestTerminal): number[] { return [ @@ -1270,7 +1269,6 @@ describe('InputHandler', () => { describe('windowOptions', () => { it('all should be disabled by default and not report', () => { const term = new TestTerminal({cols: 10, rows: 10}); - assert.deepEqual(term.options.windowOptions, 0); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b[14t'); @@ -1281,8 +1279,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, []); }); it('14 - GetWinSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.getWinSizePixels}); - assert.deepEqual(term.options.windowOptions, 1 << 14); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizePixels: true}}); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b[14t'); @@ -1290,8 +1287,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, []); }); it('16 - GetCellSizePixels', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.getCellSizePixels}); - assert.deepEqual(term.options.windowOptions, 1 << 16); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getCellSizePixels: true}}); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b[16t'); @@ -1299,8 +1295,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, []); }); it('18 - GetWinSizeChars', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.getWinSizeChars}); - assert.deepEqual(term.options.windowOptions, 1 << 18); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinSizeChars: true}}); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b[18t'); @@ -1310,8 +1305,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, ['\x1b[8;10;10t', '\x1b[8;20;50t']); }); it('20 - GetIconTitle', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.getIconTitle}); - assert.deepEqual(term.options.windowOptions, 1 << 20); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getIconTitle: true}}); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b]1;hello world!\x07'); @@ -1322,8 +1316,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, ['\x1b]Lhello world!\x1b\\', '\x1b]Lsome other\x1b\\']); }); it('21 - GetWinTitle', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.getWinTitle}); - assert.deepEqual(term.options.windowOptions, 1 << 21); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {getWinTitle: true}}); const stack: string[] = []; term.onData(data => stack.push(data)); term.writeSync('\x1b]2;hello world!\x07'); @@ -1334,8 +1327,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, ['\x1b]lhello world!\x1b\\', '\x1b]lsome other\x1b\\']); }); it('22/23 - PushTitle/PopTitle', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.pushTitle | WindowOptions.popTitle}); - assert.deepEqual(term.options.windowOptions, (1 << 22) | (1 << 23)); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); const stack: string[] = []; term.onTitleChange(data => stack.push(data)); term.writeSync('\x1b]0;1\x07'); @@ -1356,8 +1348,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, ['1', '2', '3', '3', '2', '1']); }); it('22/23 - PushTitle/PopTitle with ;1', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.pushTitle | WindowOptions.popTitle}); - assert.deepEqual(term.options.windowOptions, (1 << 22) | (1 << 23)); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); const stack: string[] = []; term.onTitleChange(data => stack.push(data)); term.writeSync('\x1b]0;1\x07'); @@ -1378,8 +1369,7 @@ describe('InputHandler', () => { assert.deepEqual(stack, ['1', '2', '3']); }); it('22/23 - PushTitle/PopTitle with ;2', () => { - const term = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.pushTitle | WindowOptions.popTitle}); - assert.deepEqual(term.options.windowOptions, (1 << 22) | (1 << 23)); + const term = new TestTerminal({cols: 10, rows: 10, windowOptions: {pushTitle: true, popTitle: true}}); const stack: string[] = []; term.onTitleChange(data => stack.push(data)); term.writeSync('\x1b]0;1\x07'); @@ -1407,7 +1397,7 @@ describe('InputHandler', () => { term.writeSync('\x1b[?3h'); assert.equal((term as any)._bufferService.cols, 10); // enabled - const term2 = new TestTerminal({cols: 10, rows: 10, windowOptions: WindowOptions.setWinLines}); + const term2 = new TestTerminal({cols: 10, rows: 10, windowOptions: {setWinLines: true}}); term2.writeSync('\x1b[?3l'); assert.equal((term2 as any)._bufferService.cols, 80); term2.writeSync('\x1b[?3h'); diff --git a/src/InputHandler.ts b/src/InputHandler.ts index 21bab83b..a2bb9be9 100644 --- a/src/InputHandler.ts +++ b/src/InputHandler.ts @@ -521,7 +521,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (id.final === 't' && !id.prefix && !id.intermediates) { // security: always check whether window option is allowed return this._parser.addCsiHandler(id, params => { - if (!hasWindowOption(params.params[0], this._optionsService.options.windowOptions)) { + if (!hasWindowOption(params.params[0], this._optionsService.windowOptions)) { return true; } return callback(params); @@ -1422,7 +1422,7 @@ export class InputHandler extends Disposable implements IInputHandler { * This is only active if 'SetWinLines' (24) is listed * in `options.windowsOptions`. */ - if (this._optionsService.options.windowOptions & WindowOptions.setWinLines) { + if (this._optionsService.windowOptions & WindowOptions.setWinLines) { this._terminal.resize(132, this._bufferService.rows); this._terminal.reset(); } @@ -1609,7 +1609,7 @@ export class InputHandler extends Disposable implements IInputHandler { * This is only active if 'SetWinLines' (24) is listed * in `options.windowsOptions`. */ - if (this._optionsService.options.windowOptions & WindowOptions.setWinLines) { + if (this._optionsService.windowOptions & WindowOptions.setWinLines) { this._terminal.resize(80, this._bufferService.rows); this._terminal.reset(); } @@ -2083,7 +2083,7 @@ export class InputHandler extends Disposable implements IInputHandler { * Ps >= 24 not implemented */ public windowOptions(params: IParams): void { - if (!hasWindowOption(params.params[0], this._optionsService.options.windowOptions)) { + if (!hasWindowOption(params.params[0], this._optionsService.windowOptions)) { return; } const second = (params.length > 1) ? params.params[1] : 0; diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 7d9c3aa6..42152fac 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -75,6 +75,7 @@ export class MockLogService implements ILogService { export class MockOptionsService implements IOptionsService { serviceBrand: any; options: ITerminalOptions = clone(DEFAULT_OPTIONS); + windowOptions = 0; onOptionChange: IEvent = new EventEmitter().event; constructor(testOptions?: IPartialTerminalOptions) { if (testOptions) { diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 9b38aa3c..2587820a 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -256,7 +256,6 @@ export type CoreMouseEncoding = (event: ICoreMouseEvent) => string; * WindowOption settings. */ export interface IWindowOptions { - [key: string]: boolean | undefined; restoreWin?: boolean; minimizeWin?: boolean; setWinPosition?: boolean; diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 099c4501..9ded45e9 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -7,7 +7,7 @@ import { IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'comm import { EventEmitter, IEvent } from 'common/EventEmitter'; import { isMac } from 'common/Platform'; import { clone } from 'common/Clone'; -import { setWindowOptions, getWindowOptions } from 'common/WindowOptions'; +import { setWindowOptions, getWindowOptions, WindowOptions } from 'common/WindowOptions'; // Source: https://freesound.org/people/altemark/sounds/45759/ // This sound is released under the Creative Commons Attribution 3.0 Unported @@ -53,7 +53,7 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ cancelEvents: false, useFlowControl: false, wordSeparator: ' ()[]{}\',:;"', - windowOptions: 0 + windowOptions: {} }); /** @@ -65,6 +65,7 @@ export class OptionsService implements IOptionsService { serviceBrand: any; public options: ITerminalOptions; + public windowOptions: WindowOptions = 0; private _onOptionChange = new EventEmitter(); public get onOptionChange(): IEvent { return this._onOptionChange.event; } @@ -77,6 +78,9 @@ export class OptionsService implements IOptionsService { this.options[k] = newValue; } }); + if (options.windowOptions) { + this.windowOptions = setWindowOptions(options.windowOptions as any, 0); + } } public setOption(key: string, value: any): void { @@ -132,7 +136,7 @@ export class OptionsService implements IOptionsService { } break; case 'windowOptions': - value = setWindowOptions(value, this.options.windowOptions); + this.windowOptions = setWindowOptions(value, this.windowOptions); } return value; } @@ -142,7 +146,7 @@ export class OptionsService implements IOptionsService { throw new Error(`No option with key "${key}"`); } if (key === 'windowOptions') { - return getWindowOptions(this.options.windowOptions); + return getWindowOptions(this.windowOptions); } return this.options[key]; } diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 30650957..7a045fc7 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -5,7 +5,7 @@ import { IEvent } from 'common/EventEmitter'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; -import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType } from 'common/Types'; +import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, IWindowOptions } from 'common/Types'; import { createDecorator } from 'common/services/ServiceRegistry'; import { WindowOptions } from 'common/WindowOptions'; @@ -167,6 +167,7 @@ export interface IOptionsService { serviceBrand: any; readonly options: ITerminalOptions; + readonly windowOptions: WindowOptions; readonly onOptionChange: IEvent; @@ -208,7 +209,7 @@ export interface IPartialTerminalOptions { theme?: ITheme; windowsMode?: boolean; wordSeparator?: string; - windowOptions?: WindowOptions; + windowOptions?: IWindowOptions; } export interface ITerminalOptions { @@ -248,7 +249,7 @@ export interface ITerminalOptions { screenKeys: boolean; termName: string; useFlowControl: boolean; - windowOptions: WindowOptions; + windowOptions: IWindowOptions; } export interface ITheme { diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 0530bee7..e984bd44 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -215,6 +215,12 @@ declare module 'xterm' { * double click to select work logic. */ wordSeparator?: string; + + /** + * Enable various window manipulation and report features. + * All features are disabled by default for security reasons. + */ + windowOptions?: IWindowOptions; } /**