deactivate wheel left/right, docs
This commit is contained in:
+57
-34
@@ -48,43 +48,66 @@ stdin.addListener('data', function(data) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// basic button codes (modifier keys are added on top)
|
// button definitions
|
||||||
const BUTTONS = {
|
const buttons = {
|
||||||
0: ['left', 'press'],
|
'<none>': -1,
|
||||||
1: ['middle', 'press'],
|
left: 0,
|
||||||
2: ['right', 'press'],
|
middle: 1,
|
||||||
3: ['', 'release'],
|
right: 2,
|
||||||
32: ['left', 'move'],
|
released: 3,
|
||||||
33: ['middle', 'move'],
|
wheelUp: 4,
|
||||||
34: ['right', 'move'],
|
wheelDown: 5,
|
||||||
35: ['', 'move'],
|
wheelLeft: 6,
|
||||||
64: ['wheel', 'up'],
|
wheelRight: 7,
|
||||||
65: ['wheel', 'down']
|
aux1: 8,
|
||||||
|
aux2: 9,
|
||||||
|
aux3: 10,
|
||||||
|
aux4: 11,
|
||||||
|
aux5: 12,
|
||||||
|
aux6: 13,
|
||||||
|
aux7: 14,
|
||||||
|
aux8: 15
|
||||||
};
|
};
|
||||||
|
const reverseButtons = {};
|
||||||
|
for (const el in buttons) {
|
||||||
|
reverseButtons[buttons[el]] = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract button data from buttonCode
|
||||||
function evalButtonCode(code) {
|
function evalButtonCode(code) {
|
||||||
// 2 bits: 0 - left, 1 - middle, 2 - right, 3 - release
|
// more than 15 buttons are not supported
|
||||||
// higher bits: 4 - shift, 8 - meta, 16 - control
|
if (code > 255) {
|
||||||
const modifier = {shift: !!(code & 4), meta: !!(code & 8), control: !!(code & 16)};
|
return {button: 'invalid', action: 'invalid', modifier: {}};
|
||||||
const wheel = code & 64;
|
|
||||||
let action;
|
|
||||||
let button;
|
|
||||||
if (wheel) {
|
|
||||||
action = (code & 1) ? 'down' : 'up';
|
|
||||||
button = 'wheel';
|
|
||||||
} else {
|
|
||||||
action = code & 32 ? 'move' : code === 3 ? 'release' : 'press';
|
|
||||||
code &= 3; // TODO: more than 3 buttons + wheel
|
|
||||||
button = code === 0 ? 'left' : code === 1 ? 'middle' : code === 2 ? 'right' : '<none>';
|
|
||||||
}
|
}
|
||||||
return {button, action, modifier};
|
const modifier = {shift: !!(code & 4), meta: !!(code & 8), control: !!(code & 16)};
|
||||||
|
const move = code & 32;
|
||||||
|
let button = code & 3;
|
||||||
|
if (code & 128) {
|
||||||
|
button |= 8;
|
||||||
|
}
|
||||||
|
if (code & 64) {
|
||||||
|
button |= 4
|
||||||
|
}
|
||||||
|
let actionS = 'press';
|
||||||
|
let buttonS = reverseButtons[button];
|
||||||
|
if (button === 3) {
|
||||||
|
buttonS = '<none>';
|
||||||
|
actionS = 'release';
|
||||||
|
}
|
||||||
|
if (move) {
|
||||||
|
actionS = 'move';
|
||||||
|
} else if (4 <= button && button <= 7) {
|
||||||
|
buttonS = 'wheel';
|
||||||
|
actionS = button === 4 ? 'up' : button === 5 ? 'down' : button === 6 ? 'left' : 'right';
|
||||||
|
}
|
||||||
|
return {button: buttonS, action: actionS, modifier};
|
||||||
}
|
}
|
||||||
|
|
||||||
// protocols
|
// protocols
|
||||||
const PROTOCOLS = {
|
const PROTOCOLS = {
|
||||||
'9 (X10: press only)': '\x1b[?9h',
|
'9 (X10: press only)': '\x1b[?9h',
|
||||||
'1000 (VT200: press, release, wheel)': '\x1b[?1000h',
|
'1000 (VT200: press, release, wheel)': '\x1b[?1000h',
|
||||||
// '1001 (VT200 highlight)': '\x1b[?1001h', // handle of backreport not implemented
|
// '1001 (VT200 highlight)': '\x1b[?1001h', // handle of backreport - not implemented
|
||||||
'1002 (press, release, move on pressed, wheel)': '\x1b[?1002h',
|
'1002 (press, release, move on pressed, wheel)': '\x1b[?1002h',
|
||||||
'1003 (press, relase, move, wheel)': '\x1b[?1003h'
|
'1003 (press, relase, move, wheel)': '\x1b[?1003h'
|
||||||
}
|
}
|
||||||
@@ -96,8 +119,8 @@ const ENC = {
|
|||||||
// format: CSI M <button + 32> <row + 32> <col + 32>
|
// format: CSI M <button + 32> <row + 32> <col + 32>
|
||||||
report => ({
|
report => ({
|
||||||
state: evalButtonCode(report[3] - 32),
|
state: evalButtonCode(report[3] - 32),
|
||||||
row: report[4] - 32,
|
col: report[4] - 32,
|
||||||
col: report[5] - 32
|
row: report[5] - 32
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
'UTF8' : [
|
'UTF8' : [
|
||||||
@@ -108,8 +131,8 @@ const ENC = {
|
|||||||
const sReport = report.toString(); // decode with utf8
|
const sReport = report.toString(); // decode with utf8
|
||||||
return {
|
return {
|
||||||
state: evalButtonCode(sReport.charCodeAt(3) - 32),
|
state: evalButtonCode(sReport.charCodeAt(3) - 32),
|
||||||
row: sReport.charCodeAt(4) - 32,
|
col: sReport.charCodeAt(4) - 32,
|
||||||
col: sReport.charCodeAt(5) - 32
|
row: sReport.charCodeAt(5) - 32
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -119,7 +142,7 @@ const ENC = {
|
|||||||
report => {
|
report => {
|
||||||
// strip off introducer + M
|
// strip off introducer + M
|
||||||
const sReport = report.toString().slice(3, -1);
|
const sReport = report.toString().slice(3, -1);
|
||||||
const [buttonCode, row, col] = sReport.split(';');
|
const [buttonCode, col, row] = sReport.split(';');
|
||||||
const state = evalButtonCode(buttonCode);
|
const state = evalButtonCode(buttonCode);
|
||||||
if (report[report.length - 1] === 'm'.charCodeAt(0)) {
|
if (report[report.length - 1] === 'm'.charCodeAt(0)) {
|
||||||
state.action = 'release';
|
state.action = 'release';
|
||||||
@@ -133,7 +156,7 @@ const ENC = {
|
|||||||
report => {
|
report => {
|
||||||
// strip off introducer + M
|
// strip off introducer + M
|
||||||
const sReport = report.toString().slice(2, -1);
|
const sReport = report.toString().slice(2, -1);
|
||||||
const [button, row, col] = sReport.split(';');
|
const [button, col, row] = sReport.split(';');
|
||||||
return {state: evalButtonCode(button - 32), row, col};
|
return {state: evalButtonCode(button - 32), row, col};
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -182,7 +205,7 @@ function applyReportData(data) {
|
|||||||
let {state, row, col} = ENC[Object.keys(ENC)[activeEnc]][1](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);
|
console.log('\x1b[2KButton:', state.button, 'Action:', state.action, 'Modifier:', state.modifier, 'row:', row, 'col:', col);
|
||||||
// apply to cursor position
|
// apply to cursor position
|
||||||
process.stdout.write(`\x1b[${col};${row}H`);
|
process.stdout.write(`\x1b[${row};${col}H`);
|
||||||
}
|
}
|
||||||
|
|
||||||
printMenu();
|
printMenu();
|
||||||
|
|||||||
+23
-11
@@ -710,7 +710,21 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move mouse event code into its own file.
|
/**
|
||||||
|
* Bind certain mouse events to the terminal.
|
||||||
|
* By default only 3 button + wheel up/down is ativated. For higher buttons
|
||||||
|
* no mouse report will be created. Typically the standard actions will be active.
|
||||||
|
*
|
||||||
|
* There are several reasons not to enable support for higher buttons/wheel:
|
||||||
|
* - Button 4 and 5 are typically used for history back and forward navigation,
|
||||||
|
* there is no straight forward way to supress/intercept those standard actions.
|
||||||
|
* - Support for higher buttons does not work in some platform/browser combinations.
|
||||||
|
* - Left/right wheel was not tested.
|
||||||
|
* - Emulators vary in mouse button support, typically only 3 buttons and
|
||||||
|
* wheel up/down work reliable.
|
||||||
|
*
|
||||||
|
* TODO: Move mouse event code into its own file.
|
||||||
|
*/
|
||||||
public bindMouse(): void {
|
public bindMouse(): void {
|
||||||
const self = this;
|
const self = this;
|
||||||
const el = this.element;
|
const el = this.element;
|
||||||
@@ -734,9 +748,10 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
|||||||
// buttons is not supported on macOS, try to get a value from button instead
|
// buttons is not supported on macOS, try to get a value from button instead
|
||||||
but = CoreMouseButton.NONE;
|
but = CoreMouseButton.NONE;
|
||||||
if (ev.button !== undefined) {
|
if (ev.button !== undefined) {
|
||||||
but = ev.button < 3 ? ev.button : undefined;
|
but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// according to MDN buttons only reports up to button 5 (AUX2)
|
||||||
but = ev.buttons & 1 ? CoreMouseButton.LEFT :
|
but = ev.buttons & 1 ? CoreMouseButton.LEFT :
|
||||||
ev.buttons & 4 ? CoreMouseButton.MIDDLE :
|
ev.buttons & 4 ? CoreMouseButton.MIDDLE :
|
||||||
ev.buttons & 2 ? CoreMouseButton.RIGHT :
|
ev.buttons & 2 ? CoreMouseButton.RIGHT :
|
||||||
@@ -745,20 +760,16 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
|||||||
break;
|
break;
|
||||||
case 'mouseup':
|
case 'mouseup':
|
||||||
action = CoreMouseAction.UP;
|
action = CoreMouseAction.UP;
|
||||||
// AUX buttons are currently not supported
|
but = ev.button < 3 ? ev.button : ev.button + 5;
|
||||||
but = ev.button < 3 ? ev.button : undefined;
|
|
||||||
break;
|
break;
|
||||||
case 'mousedown':
|
case 'mousedown':
|
||||||
action = CoreMouseAction.DOWN;
|
action = CoreMouseAction.DOWN;
|
||||||
but = ev.button < 3 ? ev.button : undefined;
|
but = ev.button < 3 ? ev.button : ev.button + 5;
|
||||||
break;
|
break;
|
||||||
case 'wheel':
|
case 'wheel':
|
||||||
// precedence: up/down over left/right
|
// only UP/DOWN wheel events are respected
|
||||||
// FIXME: Can we have both in one event? Need to send another wheel event?
|
|
||||||
if ((ev as WheelEvent).deltaY !== 0) {
|
if ((ev as WheelEvent).deltaY !== 0) {
|
||||||
action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
|
action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;
|
||||||
} else if ((ev as WheelEvent).deltaX !== 0) {
|
|
||||||
action = (ev as WheelEvent).deltaX < 0 ? CoreMouseAction.LEFT : CoreMouseAction.RIGHT;
|
|
||||||
}
|
}
|
||||||
but = CoreMouseButton.WHEEL;
|
but = CoreMouseButton.WHEEL;
|
||||||
break;
|
break;
|
||||||
@@ -767,8 +778,9 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exit if we cannot determine button/action values
|
// exit if we cannot determine valid button/action values
|
||||||
if (action === undefined || but === undefined) {
|
// do nothing for higher buttons than wheel
|
||||||
|
if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user