Remove RenderService dep in InputHandler

This commit is contained in:
Daniel Imms
2020-04-26 07:03:11 -07:00
parent ba40fe4ff4
commit 81d289b266
4 changed files with 65 additions and 48 deletions
+9 -9
View File
@@ -43,7 +43,7 @@ describe('InputHandler', () => {
bufferService.buffer.x = 1;
bufferService.buffer.y = 2;
bufferService.buffer.ybase = 0;
const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
inputHandler.curAttrData.fg = 3;
// Save cursor position
inputHandler.saveCursor();
@@ -63,7 +63,7 @@ describe('InputHandler', () => {
describe('setCursorStyle', () => {
it('should call Terminal.setOption with correct params', () => {
const optionsService = new MockOptionsService();
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), optionsService, new MockCoreMouseService(), new MockUnicodeService());
inputHandler.setCursorStyle(Params.fromArray([0]));
assert.equal(optionsService.options['cursorStyle'], 'block');
@@ -103,7 +103,7 @@ describe('InputHandler', () => {
describe('setMode', () => {
it('should toggle bracketedPasteMode', () => {
const coreService = new MockCoreService();
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
// Set bracketed paste mode
inputHandler.setModePrivate(Params.fromArray([2004]));
assert.equal(coreService.decPrivateModes.bracketedPasteMode, true);
@@ -121,7 +121,7 @@ describe('InputHandler', () => {
it('insertChars', function(): void {
const bufferService = new MockBufferService(80, 30);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
// insert some data in first and second line
inputHandler.parse(Array(bufferService.cols - 9).join('a'));
@@ -158,7 +158,7 @@ describe('InputHandler', () => {
});
it('deleteChars', function(): void {
const bufferService = new MockBufferService(80, 30);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
// insert some data in first and second line
inputHandler.parse(Array(bufferService.cols - 9).join('a'));
@@ -198,7 +198,7 @@ describe('InputHandler', () => {
});
it('eraseInLine', function(): void {
const bufferService = new MockBufferService(80, 30);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
// fill 6 lines to test 3 different states
inputHandler.parse(Array(bufferService.cols + 1).join('a'));
@@ -226,7 +226,7 @@ describe('InputHandler', () => {
});
it('eraseInDisplay', function(): void {
const bufferService = new MockBufferService(80, 7);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
// fill display with a's
for (let i = 0; i < bufferService.rows; ++i) inputHandler.parse(Array(bufferService.cols + 1).join('a'));
@@ -360,7 +360,7 @@ describe('InputHandler', () => {
});
describe('print', () => {
it('should not cause an infinite loop (regression test)', () => {
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
const inputHandler = new InputHandler(new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
const container = new Uint32Array(10);
container[0] = 0x200B;
inputHandler.print(container, 0, 1);
@@ -373,7 +373,7 @@ describe('InputHandler', () => {
beforeEach(() => {
bufferService = new MockBufferService(80, 30);
handler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService(), {} as any);
handler = new InputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockCoreMouseService(), new MockUnicodeService());
});
it('should handle DECSET/DECRST 47 (alt screen buffer)', () => {
handler.parse('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST');
+31 -34
View File
@@ -18,10 +18,9 @@ import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content
import { CellData } from 'common/buffer/CellData';
import { AttributeData } from 'common/buffer/AttributeData';
import { IAttributeData, IDisposable, IWindowOptions } from 'common/Types';
import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IInstantiationService } from 'common/services/Services';
import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService } from 'common/services/Services';
import { OscHandler } from 'common/parser/OscParser';
import { DcsHandler } from 'common/parser/DcsParser';
import { IRenderService } from 'browser/services/Services';
/**
* Map collect to glevel. Used in `selectCharset`.
@@ -94,7 +93,10 @@ function paramToWindowOption(n: number, opts: IWindowOptions): boolean {
return false;
}
export enum WindowsOptionsReportType {
GET_WIN_SIZE_PIXELS = 0,
GET_CELL_SIZE_PIXELS = 1
}
/**
* DCS subparser implementations
@@ -224,28 +226,31 @@ export class InputHandler extends Disposable implements IInputHandler {
private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone();
private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone();
private _onRequestBell = new EventEmitter<void>();
public get onRequestBell(): IEvent<void> { return this._onRequestBell.event; }
private _onRequestRefreshRows = new EventEmitter<number, number>();
public get onRequestRefreshRows(): IEvent<number, number> { return this._onRequestRefreshRows.event; }
private _onRequestReset = new EventEmitter<void>();
public get onRequestReset(): IEvent<void> { return this._onRequestReset.event; }
private _onRequestBell = new EventEmitter<void>();
public get onRequestBell(): IEvent<void> { return this._onRequestBell.event; }
private _onRequestScroll = new EventEmitter<IAttributeData, boolean | void>();
public get onRequestScroll(): IEvent<IAttributeData, boolean | void> { return this._onRequestScroll.event; }
private _onRequestSyncScrollBar = new EventEmitter<void>();
public get onRequestSyncScrollBar(): IEvent<void> { return this._onRequestSyncScrollBar.event; }
private _onRequestWindowsOptionsReport = new EventEmitter<WindowsOptionsReportType>();
public get onRequestWindowsOptionsReport(): IEvent<WindowsOptionsReportType> { return this._onRequestWindowsOptionsReport.event; }
private _onA11yChar = new EventEmitter<string>();
public get onA11yChar(): IEvent<string> { return this._onA11yChar.event; }
private _onA11yTab = new EventEmitter<number>();
public get onA11yTab(): IEvent<number> { return this._onA11yTab.event; }
private _onCursorMove = new EventEmitter<void>();
public get onCursorMove(): IEvent<void> { return this._onCursorMove.event; }
private _onLineFeed = new EventEmitter<void>();
public get onLineFeed(): IEvent<void> { return this._onLineFeed.event; }
private _onScroll = new EventEmitter<number>();
public get onScroll(): IEvent<number> { return this._onScroll.event; }
private _onScrollRequest = new EventEmitter<IAttributeData, boolean | void>();
public get onScrollRequest(): IEvent<IAttributeData, boolean | void> { return this._onScrollRequest.event; }
private _onSyncScrollBarRequest = new EventEmitter<void>();
public get onSyncScrollBarRequest(): IEvent<void> { return this._onSyncScrollBarRequest.event; }
private _onTitleChange = new EventEmitter<string>();
public get onTitleChange(): IEvent<string> { return this._onTitleChange.event; }
private _onA11yChar = new EventEmitter<string>();
public get onA11yChar(): IEvent<string> { return this._onA11yChar.event; }
private _onA11yTab = new EventEmitter<number>();
public get onA11yTab(): IEvent<number> { return this._onA11yTab.event; }
constructor(
private readonly _bufferService: IBufferService,
@@ -256,7 +261,6 @@ export class InputHandler extends Disposable implements IInputHandler {
private readonly _optionsService: IOptionsService,
private readonly _coreMouseService: ICoreMouseService,
private readonly _unicodeService: IUnicodeService,
private readonly _instantiationService: IInstantiationService,
private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
) {
super();
@@ -557,7 +561,7 @@ export class InputHandler extends Disposable implements IInputHandler {
buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onScrollRequest.fire(this._eraseAttrData(), true);
this._onRequestScroll.fire(this._eraseAttrData(), true);
} else {
if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
@@ -696,7 +700,7 @@ export class InputHandler extends Disposable implements IInputHandler {
buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onScrollRequest.fire(this._eraseAttrData());
this._onRequestScroll.fire(this._eraseAttrData());
} else if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
}
@@ -1767,7 +1771,7 @@ export class InputHandler extends Disposable implements IInputHandler {
case 66:
this._logService.debug('Serial port requested application keypad.');
this._coreService.decPrivateModes.applicationKeypad = true;
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
break;
case 9: // X10 Mouse
// no release, no motion, no wheel, no modifiers.
@@ -1813,7 +1817,7 @@ export class InputHandler extends Disposable implements IInputHandler {
this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
this._coreService.isCursorInitialized = true;
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
break;
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
this._coreService.decPrivateModes.bracketedPasteMode = true;
@@ -1994,7 +1998,7 @@ export class InputHandler extends Disposable implements IInputHandler {
case 66:
this._logService.debug('Switching back to normal keypad.');
this._coreService.decPrivateModes.applicationKeypad = false;
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
break;
case 9: // X10 Mouse
case 1000: // vt200 mouse
@@ -2031,7 +2035,7 @@ export class InputHandler extends Disposable implements IInputHandler {
}
this._coreService.isCursorInitialized = true;
this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
break;
case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
this._coreService.decPrivateModes.bracketedPasteMode = false;
@@ -2370,7 +2374,7 @@ export class InputHandler extends Disposable implements IInputHandler {
*/
public softReset(params: IParams): void {
this._coreService.isCursorHidden = false;
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
this._bufferService.buffer.scrollTop = 0;
this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1;
this._curAttrData = DEFAULT_ATTR_DATA.clone();
@@ -2484,21 +2488,14 @@ export class InputHandler extends Disposable implements IInputHandler {
return;
}
const second = (params.length > 1) ? params.params[1] : 0;
const rs = this._instantiationService.getService(IRenderService);
switch (params.params[0]) {
case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t
if (rs && second !== 2) {
const w = rs.dimensions.scaledCanvasWidth.toFixed(0);
const h = rs.dimensions.scaledCanvasHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[4;${h};${w}t`);
if (second !== 2) {
this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_WIN_SIZE_PIXELS);
}
break;
case 16: // GetCellSizePixels, returns CSI 6 ; height ; width t
if (rs) {
const w = rs.dimensions.scaledCellWidth.toFixed(0);
const h = rs.dimensions.scaledCellHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[6;${h};${w}t`);
}
this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_CELL_SIZE_PIXELS);
break;
case 18: // GetWinSizeChars, returns CSI 8 ; height ; width t
if (this._bufferService) {
@@ -2618,7 +2615,7 @@ export class InputHandler extends Disposable implements IInputHandler {
public keypadApplicationMode(): void {
this._logService.debug('Serial port requested application keypad.');
this._coreService.decPrivateModes.applicationKeypad = true;
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
}
/**
@@ -2629,7 +2626,7 @@ export class InputHandler extends Disposable implements IInputHandler {
public keypadNumericMode(): void {
this._logService.debug('Switching back to normal keypad.');
this._coreService.decPrivateModes.applicationKeypad = false;
this._onSyncScrollBarRequest.fire();
this._onRequestSyncScrollBar.fire();
}
/**
@@ -2686,7 +2683,7 @@ export class InputHandler extends Disposable implements IInputHandler {
this._bufferService.buffer.y++;
if (buffer.y === buffer.scrollBottom + 1) {
buffer.y--;
this._onScrollRequest.fire(this._eraseAttrData());
this._onRequestScroll.fire(this._eraseAttrData());
} else if (buffer.y >= this._bufferService.rows) {
buffer.y = this._bufferService.rows - 1;
}
+24 -4
View File
@@ -27,7 +27,7 @@ import { CompositionHelper } from 'browser/input/CompositionHelper';
import { Viewport } from 'browser/Viewport';
import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard';
import { C0 } from 'common/data/EscapeSequences';
import { InputHandler } from './InputHandler';
import { InputHandler, WindowsOptionsReportType } from './InputHandler';
import { Renderer } from 'browser/renderer/Renderer';
import { Linkifier } from 'browser/Linkifier';
import { SelectionService } from 'browser/services/SelectionService';
@@ -176,11 +176,12 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._inputHandler.reset();
} else {
// Register input handler and refire/handle events
this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService);
this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService);
this.register(this._inputHandler.onRequestBell(() => this.bell()));
this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
this.register(this._inputHandler.onRequestReset(() => this.reset()));
this.register(this._inputHandler.onScrollRequest((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)));
this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)));
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
@@ -462,7 +463,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._viewportScrollArea
);
this.viewport.onThemeChange(this._colorManager.colors);
this.register(this._inputHandler.onSyncScrollBarRequest(() => this.viewport.syncScrollArea()));
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport.syncScrollArea()));
this.register(this.viewport);
this.register(this.onCursorMove(() => this._renderService.onCursorMove()));
@@ -1351,6 +1352,25 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.viewport?.syncScrollArea();
}
private _reportWindowsOptions(type: WindowsOptionsReportType): void {
if (!this._renderService) {
return;
}
switch (type) {
case WindowsOptionsReportType.GET_WIN_SIZE_PIXELS:
const canvasWidth = this._renderService.dimensions.scaledCanvasWidth.toFixed(0);
const canvasHeight = this._renderService.dimensions.scaledCanvasHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[4;${canvasHeight};${canvasWidth}t`);
break;
case WindowsOptionsReportType.GET_CELL_SIZE_PIXELS:
const cellWidth = this._renderService.dimensions.scaledCellWidth.toFixed(0);
const cellHeight = this._renderService.dimensions.scaledCellHeight.toFixed(0);
this._coreService.triggerDataEvent(`${C0.ESC}[6;${cellHeight};${cellWidth}t`);
break;
}
}
// TODO: Remove cancel function and cancelEvents option
public cancel(ev: Event, force?: boolean): boolean {
if (!this.options.cancelEvents && !force) {
+1 -1
View File
@@ -28,7 +28,7 @@ export interface ICompositionHelper {
*/
export interface IInputHandler {
onTitleChange: IEvent<string>;
onScrollRequest: IEvent<IAttributeData, boolean | void>;
onRequestScroll: IEvent<IAttributeData, boolean | void>;
parse(data: string | Uint8Array): void;
print(data: Uint32Array, start: number, end: number): void;