diff --git a/README.md b/README.md
index d01a0f33..2853696f 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,7 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Bastillion**](https://www.bastillion.io): Bastillion is an open-source web-based SSH console that centrally manages administrative access to systems.
- [**PHP App Server**](https://github.com/cubiclesoft/php-app-server/): Create lightweight, installable almost-native applications for desktop OSes. ExecTerminal (nicely wraps the xterm.js Terminal), TerminalManager, and RunProcessSDK are self-contained, reusable ES5+ compliant Javascript components.
- [**NgTerminal**](https://github.com/qwefgh90/ng-terminal): NgTerminal is a web terminal that leverages xterm.js on Angular 7+. You can easily add it into your application by adding `` into your component.
+- [**tty-share**](https://tty-share.com): Extremely simple terminal sharing over the Internet.
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
diff --git a/bin/test.js b/bin/test.js
index 89f0d61e..775ec004 100644
--- a/bin/test.js
+++ b/bin/test.js
@@ -21,7 +21,7 @@ if (process.argv.length > 2) {
testFiles = process.argv.slice(2);
}
-cp.spawnSync(
+const run = cp.spawnSync(
path.resolve(__dirname, '../node_modules/.bin/mocha'),
testFiles,
{
@@ -30,3 +30,5 @@ cp.spawnSync(
stdio: 'inherit'
}
);
+
+process.exit(run.status);
\ No newline at end of file
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