improve mouse support
This commit is contained in:
parent
e8a20fdb77
commit
ab02708306
158
lib/program.js
158
lib/program.js
|
@ -28,11 +28,17 @@ function Program(input, output) {
|
||||||
this.cols = this.output.columns || 1;
|
this.cols = this.output.columns || 1;
|
||||||
this.rows = this.output.rows || 1;
|
this.rows = this.output.rows || 1;
|
||||||
|
|
||||||
|
this.terminal = process.env.TERM || 'xterm';
|
||||||
|
|
||||||
this.listen();
|
this.listen();
|
||||||
}
|
}
|
||||||
|
|
||||||
Program.prototype.__proto__ = EventEmitter.prototype;
|
Program.prototype.__proto__ = EventEmitter.prototype;
|
||||||
|
|
||||||
|
Program.prototype.term = function(is) {
|
||||||
|
return this.terminal.indexOf(is) === 0;
|
||||||
|
};
|
||||||
|
|
||||||
Program.prototype.listen = function() {
|
Program.prototype.listen = function() {
|
||||||
if (!this.input.isTTY || !this.output.isTTY) return;
|
if (!this.input.isTTY || !this.output.isTTY) return;
|
||||||
|
|
||||||
|
@ -143,24 +149,64 @@ Program.prototype._bindMouse = function(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XTerm / X10
|
// XTerm / X10
|
||||||
if (parts = /^\x1b\[M([\x20-\x7f\x00]{3})/.exec(s)) {
|
//if (parts = /^\x1b\[M([\x20-\x7f\x00]{3})/.exec(s)) {
|
||||||
|
if (parts = /^\x1b\[M([\x00\u0020-\xffff]{3,4})/.exec(s)) {
|
||||||
var b = parts[1].charCodeAt(0)
|
var b = parts[1].charCodeAt(0)
|
||||||
, x = parts[1].charCodeAt(1)
|
, x = parts[1].charCodeAt(1)
|
||||||
, y = parts[1].charCodeAt(2);
|
, y = parts[1].charCodeAt(2)
|
||||||
|
, mod;
|
||||||
|
|
||||||
key.name = 'mouse';
|
key.name = 'mouse';
|
||||||
key.type = 'X10';
|
key.type = 'X10';
|
||||||
key.button = b;
|
|
||||||
|
key.raw = [b, x, y, parts[0]];
|
||||||
key.x = x - 32;
|
key.x = x - 32;
|
||||||
key.y = y - 32;
|
key.y = y - 32;
|
||||||
|
|
||||||
|
if (key.x === 0) key.x = 255;
|
||||||
|
if (key.y === 0) key.y = 255;
|
||||||
|
|
||||||
|
mod = b >> 3;
|
||||||
|
key.shift = mod & 4;
|
||||||
|
key.meta = mod & 8;
|
||||||
|
key.ctrl = mod & 16;
|
||||||
|
|
||||||
|
b -= 32;
|
||||||
|
|
||||||
|
if (b === 64) {
|
||||||
|
key.action = 'wheelup';
|
||||||
|
key.button = 'middle';
|
||||||
|
} else if (b === 65) {
|
||||||
|
key.action = 'wheeldown';
|
||||||
|
key.button = 'middle';
|
||||||
|
} else if (b === 3) {
|
||||||
|
// Could also be a movement.
|
||||||
|
key.action = 'mouseup';
|
||||||
|
key.button = 'unknown';
|
||||||
|
} else {
|
||||||
|
key.action = 'mousedown';
|
||||||
|
key.button =
|
||||||
|
b === 0 ? 'left'
|
||||||
|
: b === 1 ? 'middle'
|
||||||
|
: b === 2 ? 'right'
|
||||||
|
: 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's a movement
|
||||||
|
// Wrong
|
||||||
|
//if (b > 32 && b < 64) {
|
||||||
|
// delete key.button;
|
||||||
|
// key.action = 'movement';
|
||||||
|
//}
|
||||||
|
|
||||||
self.emit('keypress', null, key);
|
self.emit('keypress', null, key);
|
||||||
self.emit('mouse', key);
|
self.emit('mouse', key);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// URxvt
|
// URxvt
|
||||||
if (parts = /^\x1b\[((?:\d+;){3})M/.exec(s)) {
|
if (parts = /^\x1b\[(\d+;\d+;\d+)M/.exec(s)) {
|
||||||
var parts = parts[1].split(';')
|
var parts = parts[1].split(';')
|
||||||
, b = +parts[0]
|
, b = +parts[0]
|
||||||
, x = +parts[1]
|
, x = +parts[1]
|
||||||
|
@ -168,17 +214,21 @@ Program.prototype._bindMouse = function(s) {
|
||||||
|
|
||||||
key.name = 'mouse';
|
key.name = 'mouse';
|
||||||
key.type = 'urxvt';
|
key.type = 'urxvt';
|
||||||
|
|
||||||
key.button = b;
|
key.button = b;
|
||||||
key.x = x;
|
key.x = x;
|
||||||
key.y = y;
|
key.y = y;
|
||||||
|
|
||||||
|
// NOTE: Duplicate of the above.
|
||||||
|
|
||||||
self.emit('keypress', null, key);
|
self.emit('keypress', null, key);
|
||||||
self.emit('mouse', key);
|
self.emit('mouse', key);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SGR
|
// SGR
|
||||||
if (parts = /^\x1b\[<((?:\d+;){3})([mM])/.exec(s)) {
|
if (parts = /^\x1b\[<(\d+;\d+;\d+)([mM])/.exec(s)) {
|
||||||
var down = parts[2] === 'm'
|
var down = parts[2] === 'm'
|
||||||
, parts = parts[1].split(';')
|
, parts = parts[1].split(';')
|
||||||
, b = +parts[0]
|
, b = +parts[0]
|
||||||
|
@ -187,18 +237,32 @@ Program.prototype._bindMouse = function(s) {
|
||||||
|
|
||||||
key.name = 'mouse';
|
key.name = 'mouse';
|
||||||
key.type = 'sgr';
|
key.type = 'sgr';
|
||||||
key.button = b;
|
|
||||||
key.x = x;
|
key.x = x;
|
||||||
key.y = y;
|
key.y = y;
|
||||||
key.down = down;
|
|
||||||
|
b &= 3;
|
||||||
|
|
||||||
|
// NOTE: Get mod. And wheel.
|
||||||
|
|
||||||
|
key.action = down
|
||||||
|
? 'mousedown'
|
||||||
|
: 'mouseup';
|
||||||
|
|
||||||
|
key.button =
|
||||||
|
b === 0 ? 'left'
|
||||||
|
: b === 1 ? 'middle'
|
||||||
|
: b === 2 ? 'right'
|
||||||
|
: 'unknown';
|
||||||
|
|
||||||
self.emit('keypress', null, key);
|
self.emit('keypress', null, key);
|
||||||
self.emit('mouse', key);
|
self.emit('mouse', key);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEC
|
// DEC
|
||||||
if (parts = /^\x1b\[<((?:\d+;){4})&w/.exec(s)) {
|
if (parts = /^\x1b\[<(\d+;\d+;\d+;\d+)&w/.exec(s)) {
|
||||||
var parts = parts[1].split(';')
|
var parts = parts[1].split(';')
|
||||||
, b = +parts[0]
|
, b = +parts[0]
|
||||||
, x = +parts[1]
|
, x = +parts[1]
|
||||||
|
@ -207,12 +271,24 @@ Program.prototype._bindMouse = function(s) {
|
||||||
|
|
||||||
key.name = 'mouse';
|
key.name = 'mouse';
|
||||||
key.type = 'dec';
|
key.type = 'dec';
|
||||||
|
|
||||||
key.button = b;
|
key.button = b;
|
||||||
key.x = x;
|
key.x = x;
|
||||||
key.y = y;
|
key.y = y;
|
||||||
|
|
||||||
|
key.action = b === 3
|
||||||
|
? 'mouseup'
|
||||||
|
: 'mousedown';
|
||||||
|
|
||||||
|
key.button =
|
||||||
|
b === 2 ? 'left'
|
||||||
|
: b === 4 ? 'middle'
|
||||||
|
: b === 6 ? 'right'
|
||||||
|
: 'unknown';
|
||||||
|
|
||||||
self.emit('keypress', null, key);
|
self.emit('keypress', null, key);
|
||||||
self.emit('mouse', key);
|
self.emit('mouse', key);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,12 +300,31 @@ Program.prototype._bindMouse = function(s) {
|
||||||
|
|
||||||
key.name = 'mouse';
|
key.name = 'mouse';
|
||||||
key.type = 'vt300';
|
key.type = 'vt300';
|
||||||
key.button = b;
|
|
||||||
key.x = x;
|
key.x = x;
|
||||||
key.y = y;
|
key.y = y;
|
||||||
|
|
||||||
|
key.action = 'mousedown';
|
||||||
|
key.button =
|
||||||
|
b === 1 ? 'left'
|
||||||
|
: b === 2 ? 'middle'
|
||||||
|
: b === 5 ? 'right'
|
||||||
|
: 'unknown';
|
||||||
|
|
||||||
self.emit('keypress', null, key);
|
self.emit('keypress', null, key);
|
||||||
self.emit('mouse', key);
|
self.emit('mouse', key);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parts = /^\x1b\[(O|I)/.exec(s)) {
|
||||||
|
key.action = parts[1] === 'I'
|
||||||
|
? 'focus'
|
||||||
|
: 'blur';
|
||||||
|
|
||||||
|
self.emit('mouse', key);
|
||||||
|
self.emit(key.action);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1249,8 +1344,45 @@ Program.prototype.normalBuffer = function() {
|
||||||
return this.resetMode('?1049');
|
return this.resetMode('?1049');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Program.prototype.enableMouse = function() {
|
||||||
|
if (this.term('urxvt')) {
|
||||||
|
return this.setMouse({ urxvtMouse: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.term('xterm') || this.term('screen')) {
|
||||||
|
return this.setMouse({
|
||||||
|
allMotion: true,
|
||||||
|
utfMouse: true,
|
||||||
|
sendFocus: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.term('vt')) {
|
||||||
|
return this.setMouse({ vt200Mouse: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Program.prototype.disableMouse = function() {
|
||||||
|
return this.setMouse({
|
||||||
|
x10Mouse: false,
|
||||||
|
vt200Mouse: false,
|
||||||
|
hiliteTracking: false,
|
||||||
|
cellMotion: false,
|
||||||
|
allMotion: false,
|
||||||
|
sendFocus: false,
|
||||||
|
utfMouse: false,
|
||||||
|
sgrMouse: false,
|
||||||
|
urxvtMouse: false
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Set Mouse
|
// Set Mouse
|
||||||
Program.prototype.setMouse = function(opt) {
|
Program.prototype.setMouse = function(opt) {
|
||||||
|
if (opt.normalMouse != null) {
|
||||||
|
opt.cellMotion = opt.normalMouse;
|
||||||
|
opt.allMotion = opt.normalMouse;
|
||||||
|
}
|
||||||
|
|
||||||
// Ps = 9 -> Send Mouse X & Y on button press. See the sec-
|
// Ps = 9 -> Send Mouse X & Y on button press. See the sec-
|
||||||
// tion Mouse Tracking.
|
// tion Mouse Tracking.
|
||||||
// Ps = 9 -> Don't send Mouse X & Y on button press.
|
// Ps = 9 -> Don't send Mouse X & Y on button press.
|
||||||
|
@ -1280,16 +1412,16 @@ Program.prototype.setMouse = function(opt) {
|
||||||
// Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking.
|
// Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking.
|
||||||
// Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.
|
// Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.
|
||||||
// button event mouse
|
// button event mouse
|
||||||
if (opt.normalMouse != null) {
|
if (opt.cellMotion != null) {
|
||||||
if (opt.normalMouse) this.setMode('?1002');
|
if (opt.cellMotion) this.setMode('?1002');
|
||||||
else this.resetMode('?1002');
|
else this.resetMode('?1002');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ps = 1 0 0 3 -> Use All Motion Mouse Tracking.
|
// Ps = 1 0 0 3 -> Use All Motion Mouse Tracking.
|
||||||
// Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.
|
// Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.
|
||||||
// any event mouse
|
// any event mouse
|
||||||
if (opt.normalMouse != null) {
|
if (opt.allMotion != null) {
|
||||||
if (opt.normalMouse) this.setMode('?1003');
|
if (opt.allMotion) this.setMode('?1003');
|
||||||
else this.resetMode('?1003');
|
else this.resetMode('?1003');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue