mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
+22
-5
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* Script to test different mouse modes in terminal emulators.
|
||||
* Tests for protocols DECSET 9, 1000, 1002, 1003 with different
|
||||
* report encodings (default, UTF8, SGR, URXVT).
|
||||
* report encodings (default, UTF8, SGR, URXVT, SGR-pixels).
|
||||
*
|
||||
* VT200 Highlight mode (DECSET 1001) is not implemented.
|
||||
*
|
||||
@@ -152,13 +152,27 @@ const ENC = {
|
||||
],
|
||||
'URXVT': [
|
||||
'\x1b[?1015h',
|
||||
// format: CSI <button + 32> ; Prow ; Pcol M
|
||||
// format: CSI <button + 32> ; Prow ; Pcol M
|
||||
report => {
|
||||
// strip off introducer + M
|
||||
const sReport = report.toString().slice(2, -1);
|
||||
const [button, col, row] = sReport.split(';');
|
||||
return {state: evalButtonCode(button - 32), row, col};
|
||||
}
|
||||
],
|
||||
'SGR_PIXELS' : [
|
||||
'\x1b[?1016h',
|
||||
// format: CSI < Pbutton ; Prow ; Pcol M
|
||||
report => {
|
||||
// strip off introducer + M
|
||||
const sReport = report.toString().slice(3, -1);
|
||||
const [buttonCode, col, row] = sReport.split(';');
|
||||
const state = evalButtonCode(buttonCode);
|
||||
if (report[report.length - 1] === 'm'.charCodeAt(0)) {
|
||||
state.action = 'release';
|
||||
}
|
||||
return {state, row, col};
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -203,9 +217,12 @@ function activate() {
|
||||
|
||||
function applyReportData(data) {
|
||||
let {state, row, col} = ENC[Object.keys(ENC)[activeEnc]][1](data);
|
||||
console.log('\x1b[2KButton:', state.button, 'Action:', state.action, 'Modifier:', state.modifier, 'row:', row, 'col:', col);
|
||||
// apply to cursor position
|
||||
process.stdout.write(`\x1b[${row};${col}H`);
|
||||
if (Object.keys(ENC)[activeEnc] !== 'SGR_PIXELS') {
|
||||
console.log('\x1b[2KButton:', state.button, 'Action:', state.action, 'Modifier:', state.modifier, 'row:', row, 'col:', col);
|
||||
process.stdout.write(`\x1b[${row};${col}H`);
|
||||
} else {
|
||||
console.log('\x1b[2KButton:', state.button, 'Action:', state.action, 'Modifier:', state.modifier, 'x:', row, 'y:', col);
|
||||
}
|
||||
}
|
||||
|
||||
printMenu();
|
||||
|
||||
@@ -645,7 +645,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
// send event to CoreMouseService
|
||||
function sendEvent(ev: MouseEvent | WheelEvent): boolean {
|
||||
// get mouse coordinates
|
||||
const pos = self._mouseService!.getRawByteCoords(ev, self.screenElement!, self.cols, self.rows);
|
||||
const pos = self._mouseService!.getMouseReportCoords(ev, self.screenElement!);
|
||||
if (!pos) {
|
||||
return false;
|
||||
}
|
||||
@@ -699,8 +699,10 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
}
|
||||
|
||||
return self.coreMouseService.triggerMouseEvent({
|
||||
col: pos.x - 33, // FIXME: why -33 here?
|
||||
row: pos.y - 33,
|
||||
col: pos.col,
|
||||
row: pos.row,
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
button: but,
|
||||
action,
|
||||
ctrl: ev.ctrlKey,
|
||||
@@ -1320,13 +1322,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
|
||||
switch (type) {
|
||||
case WindowsOptionsReportType.GET_WIN_SIZE_PIXELS:
|
||||
const canvasWidth = this._renderService.dimensions.scaledCanvasWidth.toFixed(0);
|
||||
const canvasHeight = this._renderService.dimensions.scaledCanvasHeight.toFixed(0);
|
||||
const canvasWidth = this._renderService.dimensions.canvasWidth.toFixed(0);
|
||||
const canvasHeight = this._renderService.dimensions.canvasHeight.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);
|
||||
const cellWidth = this._renderService.dimensions.actualCellWidth.toFixed(0);
|
||||
const cellHeight = this._renderService.dimensions.actualCellHeight.toFixed(0);
|
||||
this.coreService.triggerDataEvent(`${C0.ESC}[6;${cellHeight};${cellWidth}t`);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ export class MockMouseService implements IMouseService {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined {
|
||||
public getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,17 +48,3 @@ export function getCoords(window: Pick<Window, 'getComputedStyle'>, event: {clie
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets coordinates within the terminal for a particular mouse event, wrapping
|
||||
* them to the bounds of the terminal and adding 32 to both the x and y values
|
||||
* as expected by xterm.
|
||||
*/
|
||||
export function getRawByteCoords(coords: [number, number] | undefined): { x: number, y: number } | undefined {
|
||||
if (!coords) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// xterm sends raw bytes and starts at 32 (SP) for each.
|
||||
return { x: coords[0] + 32, y: coords[1] + 32 };
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { ICharSizeService, IRenderService, IMouseService } from './Services';
|
||||
import { getCoords, getRawByteCoords } from 'browser/input/Mouse';
|
||||
import { getCoords, getCoordsRelativeToElement } from 'browser/input/Mouse';
|
||||
|
||||
export class MouseService implements IMouseService {
|
||||
public serviceBrand: undefined;
|
||||
@@ -29,8 +29,24 @@ export class MouseService implements IMouseService {
|
||||
);
|
||||
}
|
||||
|
||||
public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined {
|
||||
const coords = this.getCoords(event, element, colCount, rowCount);
|
||||
return getRawByteCoords(coords);
|
||||
public getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined {
|
||||
const coords = getCoordsRelativeToElement(window, event, element);
|
||||
|
||||
// due to rounding issues in zoom states pixel values might be negative or overflow actual canvas
|
||||
// ignore those events effectively narrowing mouse area a tiny bit at the edges
|
||||
if (!this._charSizeService.hasValidSize
|
||||
|| coords[0] < 0
|
||||
|| coords[1] < 0
|
||||
|| coords[0] >= this._renderService.dimensions.canvasWidth
|
||||
|| coords[1] >= this._renderService.dimensions.canvasHeight) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
col: Math.floor(coords[0] / this._renderService.dimensions.actualCellWidth),
|
||||
row: Math.floor(coords[1] / this._renderService.dimensions.actualCellHeight),
|
||||
x: Math.floor(coords[0]),
|
||||
y: Math.floor(coords[1])
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export interface IMouseService {
|
||||
serviceBrand: undefined;
|
||||
|
||||
getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined;
|
||||
getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined;
|
||||
getMouseReportCoords(event: MouseEvent, element: HTMLElement): { col: number, row: number, x: number, y: number } | undefined;
|
||||
}
|
||||
|
||||
export const IRenderService = createDecorator<IRenderService>('RenderService');
|
||||
|
||||
@@ -1908,6 +1908,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* | 1005 | Enable UTF-8 Mouse Mode. | #N |
|
||||
* | 1006 | Enable SGR Mouse Mode. | #Y |
|
||||
* | 1015 | Enable urxvt Mouse Mode. | #N |
|
||||
* | 1016 | Enable SGR-Pixels Mouse Mode. | #Y |
|
||||
* | 1047 | Use Alternate Screen Buffer. | #Y |
|
||||
* | 1048 | Save cursor as in DECSC. | #Y |
|
||||
* | 1049 | Save cursor and switch to alternate buffer clearing it. | #P[Does not clear the alternate buffer.] |
|
||||
@@ -1989,6 +1990,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 1015: // urxvt ext mode mouse - removed in #2507
|
||||
this._logService.debug('DECSET 1015 not supported (see #2507)');
|
||||
break;
|
||||
case 1016: // sgr pixels mode mouse
|
||||
this._coreMouseService.activeEncoding = 'SGR_PIXELS';
|
||||
break;
|
||||
case 25: // show cursor
|
||||
this._coreService.isCursorHidden = false;
|
||||
break;
|
||||
@@ -2149,6 +2153,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
* | 1005 | Disable UTF-8 Mouse Mode. | #N |
|
||||
* | 1006 | Disable SGR Mouse Mode. | #Y |
|
||||
* | 1015 | Disable urxvt Mouse Mode. | #N |
|
||||
* | 1006 | Disable SGR-Pixels Mouse Mode. | #Y |
|
||||
* | 1047 | Use Normal Screen Buffer (clearing screen if in alt). | #Y |
|
||||
* | 1048 | Restore cursor as in DECRC. | #Y |
|
||||
* | 1049 | Use Normal Screen Buffer and restore cursor. | #Y |
|
||||
@@ -2210,6 +2215,9 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
case 1015: // urxvt ext mode mouse - removed in #2507
|
||||
this._logService.debug('DECRST 1015 not supported (see #2507)');
|
||||
break;
|
||||
case 1006: // sgr pixels mode mouse
|
||||
this._coreMouseService.activeEncoding = 'DEFAULT';
|
||||
break;
|
||||
case 25: // hide cursor
|
||||
this._coreService.isCursorHidden = true;
|
||||
break;
|
||||
|
||||
Vendored
+3
@@ -281,6 +281,9 @@ export interface ICoreMouseEvent {
|
||||
col: number;
|
||||
/** row (zero based). */
|
||||
row: number;
|
||||
/** xy pixel positions. */
|
||||
x: number;
|
||||
y: number;
|
||||
/**
|
||||
* Button the action occured. Due to restrictions of the tracking protocols
|
||||
* it is not possible to report multiple buttons at once.
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('CoreMouseService', () => {
|
||||
});
|
||||
it('default encodings - DEFAULT, SGR', () => {
|
||||
const cms = new CoreMouseService(bufferService, coreService);
|
||||
assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'SGR']);
|
||||
assert.deepEqual(Object.keys((cms as any)._encodings), ['DEFAULT', 'SGR', 'SGR_PIXELS']);
|
||||
});
|
||||
it('protocol/encoding setter, reset', () => {
|
||||
const cms = new CoreMouseService(bufferService, coreService);
|
||||
@@ -82,68 +82,68 @@ describe('CoreMouseService', () => {
|
||||
coreService.triggerBinaryEvent = (data: string) => reports.push(data);
|
||||
});
|
||||
it('NONE', () => {
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
});
|
||||
it('X10', () => {
|
||||
cms.activeProtocol = 'X10';
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
});
|
||||
it('VT200', () => {
|
||||
cms.activeProtocol = 'VT200';
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), false);
|
||||
});
|
||||
it('DRAG', () => {
|
||||
cms.activeProtocol = 'DRAG';
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
});
|
||||
it('ANY', () => {
|
||||
cms.activeProtocol = 'ANY';
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE }), true);
|
||||
// should not report in any case
|
||||
// invalid button + action combinations
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.UP }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.MOVE }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.UP }), false);
|
||||
// invalid coords
|
||||
assert.equal(cms.triggerMouseEvent({ col: -1, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 500, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: -1, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 500, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: -1, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 500, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: -1, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 500, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), false);
|
||||
});
|
||||
describe('coords', () => {
|
||||
it('DEFAULT encoding', () => {
|
||||
cms.activeProtocol = 'ANY';
|
||||
for (let i = 0; i < bufferService.cols; ++i) {
|
||||
assert.equal(cms.triggerMouseEvent({ col: i, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: i, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
if (i > 222) {
|
||||
// supress mouse reports if we are out of addressible range (max. 222)
|
||||
assert.deepEqual(toBytes(reports.pop()), []);
|
||||
@@ -156,46 +156,54 @@ describe('CoreMouseService', () => {
|
||||
cms.activeProtocol = 'ANY';
|
||||
cms.activeEncoding = 'SGR';
|
||||
for (let i = 0; i < bufferService.cols; ++i) {
|
||||
assert.equal(cms.triggerMouseEvent({ col: i, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: i, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.deepEqual(reports.pop(), `\x1b[<0;${i + 1};1M`);
|
||||
}
|
||||
});
|
||||
it('SGR_PIXELS encoding', () => {
|
||||
cms.activeProtocol = 'ANY';
|
||||
cms.activeEncoding = 'SGR_PIXELS';
|
||||
for (let i = 0; i < 500; ++i) {
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: i, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN }), true);
|
||||
assert.deepEqual(reports.pop(), `\x1b[<0;${i};0M`);
|
||||
}
|
||||
});
|
||||
});
|
||||
it('eventCodes with modifiers (DEFAULT encoding)', () => {
|
||||
// TODO: implement AUX button tests
|
||||
cms.activeProtocol = 'ANY';
|
||||
cms.activeEncoding = 'DEFAULT';
|
||||
// all buttons + down + no modifer
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.DOWN, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.deepEqual(reports, ['\x1b[M !!', '\x1b[M!!!', '\x1b[M"!!', '\x1b[Ma!!']);
|
||||
reports = [];
|
||||
|
||||
// all buttons + up + no modifier
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.WHEEL, action: CoreMouseAction.UP, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.deepEqual(reports, ['\x1b[M#!!', '\x1b[M#!!', '\x1b[M#!!', '\x1b[M`!!']);
|
||||
reports = [];
|
||||
|
||||
// all buttons + move + no modifier
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.LEFT, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.MIDDLE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.RIGHT, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: false }), true);
|
||||
assert.deepEqual(reports, ['\x1b[M@!!', '\x1b[MA!!', '\x1b[MB!!', '\x1b[MC!!']);
|
||||
reports = [];
|
||||
|
||||
// button none + move + modifiers
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: true, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: true }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: true, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: true, shift: true }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: true, shift: true }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: false, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: true, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: false, shift: true }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: true, shift: false }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: false, alt: true, shift: true }), true);
|
||||
assert.equal(cms.triggerMouseEvent({ col: 0, row: 0, x: 0, y: 0, button: CoreMouseButton.NONE, action: CoreMouseAction.MOVE, ctrl: true, alt: true, shift: true }), true);
|
||||
assert.deepEqual(reports, ['\x1b[MS!!', '\x1b[MK!!', '\x1b[MG!!', '\x1b[M[!!', '\x1b[MO!!', '\x1b[M_!!']);
|
||||
reports = [];
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventT
|
||||
/**
|
||||
* Supported default protocols.
|
||||
*/
|
||||
const DEFAULT_PROTOCOLS: {[key: string]: ICoreMouseProtocol} = {
|
||||
const DEFAULT_PROTOCOLS: { [key: string]: ICoreMouseProtocol } = {
|
||||
/**
|
||||
* NONE
|
||||
* Events: none
|
||||
@@ -117,7 +117,7 @@ const S = String.fromCharCode;
|
||||
/**
|
||||
* Supported default encodings.
|
||||
*/
|
||||
const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = {
|
||||
const DEFAULT_ENCODINGS: { [key: string]: CoreMouseEncoding } = {
|
||||
/**
|
||||
* DEFAULT - CSI M Pb Px Py
|
||||
* Single byte encoding for coords and event code.
|
||||
@@ -142,6 +142,10 @@ const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = {
|
||||
SGR: (e: ICoreMouseEvent) => {
|
||||
const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';
|
||||
return `\x1b[<${eventCode(e, true)};${e.col};${e.row}${final}`;
|
||||
},
|
||||
SGR_PIXELS: (e: ICoreMouseEvent) => {
|
||||
const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';
|
||||
return `\x1b[<${eventCode(e, true)};${e.x};${e.y}${final}`;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -162,8 +166,8 @@ const DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = {
|
||||
* To send a mouse event call `triggerMouseEvent`.
|
||||
*/
|
||||
export class CoreMouseService implements ICoreMouseService {
|
||||
private _protocols: {[name: string]: ICoreMouseProtocol} = {};
|
||||
private _encodings: {[name: string]: CoreMouseEncoding} = {};
|
||||
private _protocols: { [name: string]: ICoreMouseProtocol } = {};
|
||||
private _encodings: { [name: string]: CoreMouseEncoding } = {};
|
||||
private _activeProtocol: string = '';
|
||||
private _activeEncoding: string = '';
|
||||
private _onProtocolChange = new EventEmitter<CoreMouseEventType>();
|
||||
@@ -241,7 +245,7 @@ export class CoreMouseService implements ICoreMouseService {
|
||||
public triggerMouseEvent(e: ICoreMouseEvent): boolean {
|
||||
// range check for col/row
|
||||
if (e.col < 0 || e.col >= this._bufferService.cols
|
||||
|| e.row < 0 || e.row >= this._bufferService.rows) {
|
||||
|| e.row < 0 || e.row >= this._bufferService.rows) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -260,8 +264,11 @@ export class CoreMouseService implements ICoreMouseService {
|
||||
e.col++;
|
||||
e.row++;
|
||||
|
||||
// debounce move at grid level
|
||||
if (e.action === CoreMouseAction.MOVE && this._lastEvent && this._compareEvents(this._lastEvent, e)) {
|
||||
// debounce move events at grid or pixel level
|
||||
if (e.action === CoreMouseAction.MOVE
|
||||
&& this._lastEvent
|
||||
&& this._equalEvents(this._lastEvent, e, this._activeEncoding === 'SGR_PIXELS')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,7 +293,7 @@ export class CoreMouseService implements ICoreMouseService {
|
||||
return true;
|
||||
}
|
||||
|
||||
public explainEvents(events: CoreMouseEventType): {[event: string]: boolean} {
|
||||
public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } {
|
||||
return {
|
||||
down: !!(events & CoreMouseEventType.DOWN),
|
||||
up: !!(events & CoreMouseEventType.UP),
|
||||
@@ -296,9 +303,14 @@ export class CoreMouseService implements ICoreMouseService {
|
||||
};
|
||||
}
|
||||
|
||||
private _compareEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent): boolean {
|
||||
if (e1.col !== e2.col) return false;
|
||||
if (e1.row !== e2.row) return false;
|
||||
private _equalEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent, pixels: boolean): boolean {
|
||||
if (pixels) {
|
||||
if (e1.x !== e2.x) return false;
|
||||
if (e1.y !== e2.y) return false;
|
||||
} else {
|
||||
if (e1.col !== e2.col) return false;
|
||||
if (e1.row !== e2.row) return false;
|
||||
}
|
||||
if (e1.button !== e2.button) return false;
|
||||
if (e1.action !== e2.action) return false;
|
||||
if (e1.ctrl !== e2.ctrl) return false;
|
||||
|
||||
+223
-236
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user