diff --git a/bin/test_mousemodes.js b/bin/test_mousemodes.js new file mode 100644 index 00000000..12ee8a0c --- /dev/null +++ b/bin/test_mousemodes.js @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + * + * 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). + * + * VT200 Highlight mode (DECSET 1001) is not implemented. + * + * The test basically applies the report data to the cursor, thus + * a mouse report should move the cursor to the cell under the mouse. + * Furthermore the reports are printed in the left lower corner as + * raw data and their meaning. + * + * A failing test might show: + * - wrong coords: the cursor will jump to some other place + * - wrong buttons: see meaning output and check whether it makes sense + * - faulty reports: inspect the raw data and compare with other emulators + * - missing events: compare with spec / other emulators + */ + +let activeProtocol = 0; +let activeEnc = 0; + +const stdin = process.openStdin(); +process.stdin.setRawMode(true); + +// close handler - reset terminal on exit +stdin.addListener('data', function(data) { + if (data[0] === 0x03) { + process.stdin.setRawMode(false); + process.stdout.write('\x1bc'); + process.exit(); + } + if (data[0] === 0x01) { + switchActiveProtocol(); + printMenu(); + } + if (data[0] === 0x02) { + switchActiveEnc(); + printMenu(); + } + console.log('\x1b[100;H\x1b[2A\x1b[2KReport:', data, [data.toString('binary')]); + // filter mouse reports + if (data[0] === 0x1b && data[1] === '['.charCodeAt(0)) { + applyReportData(data); + } +}); + +// basic button codes (modifier keys are added on top) +const BUTTONS = { + 0: ['left', 'press'], + 1: ['middle', 'press'], + 2: ['right', 'press'], + 3: ['', 'release'], + 32: ['left', 'move'], + 33: ['middle', 'move'], + 34: ['right', 'move'], + 35: ['', 'move'], + 64: ['wheel', 'up'], + 65: ['wheel', 'down'] +}; + +function evalButtonCode(code) { + // 2 bits: 0 - left, 1 - middle, 2 - right, 3 - release + // higher bits: 4 - shift, 8 - meta, 16 - control + const modifier = {shift: !!(code & 4), meta: !!(code & 8), control: !!(code & 16)}; + 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' : ''; + } + return {button, action, modifier}; +} + +// protocols +const PROTOCOLS = { + '9 (X10: press only)': '\x1b[?9h', + '1000 (VT200: press, release, wheel)': '\x1b[?1000h', + // '1001 (VT200 highlight)': '\x1b[?1001h', // handle of backreport not implemented + '1002 (press, release, move on pressed, wheel)': '\x1b[?1002h', + '1003 (press, relase, move, wheel)': '\x1b[?1003h' +} + +// encodings: ENCODING_NAME => [sequence, parse_report] +const ENC = { + 'DEFAULT' : [ + '', + // format: CSI M