remove listeners property on screen.destroy and program.destroy. fix ignoreLocked.

This commit is contained in:
Christopher Jeffrey 2015-07-29 19:56:54 -07:00
parent debbc864e4
commit f8fd4253f2
4 changed files with 118 additions and 75 deletions

View File

@ -309,8 +309,8 @@ The screen on which every other node renders.
debug console which will display when pressing F12. It will display all log
and debug messages.
- __ignoreLocked__ - Array of keys in their full format (e.g. `C-c`) to ignore
when keys are locked. Useful for creating a key that will _always_ exit no
matter whether the keys are locked.
when keys are locked or grabbed. Useful for creating a key that will _always_
exit no matter whether the keys are locked.
- __dockBorders__ - Automatically "dock" borders with other elements instead of
overlapping, depending on position (__experimental__). For example:
These border-overlapped elements:

View File

@ -132,8 +132,12 @@ Program.bind = function(program) {
if (Program._bound) return;
Program._bound = true;
unshiftEvent(process, 'exit', function() {
unshiftEvent(process, 'exit', Program._exitHandler = function() {
Program.instances.forEach(function(program) {
// Potentially reset window title on exit:
// if (program._originalTitle) {
// program.setTitle(program._originalTitle);
// }
// Ensure the buffer is flushed (it should
// always be at this point, but who knows).
program.flush();
@ -142,15 +146,6 @@ Program.bind = function(program) {
program._exiting = true;
});
});
// Potentially reset window title on exit:
// unshiftEvent(process, 'exit', function() {
// Program.instances.forEach(function(program) {
// if (program._originalTitle) {
// program.setTitle(program._originalTitle);
// }
// });
// });
};
Program.prototype.__proto__ = EventEmitter.prototype;
@ -307,8 +302,9 @@ Program.prototype.term = function(is) {
};
Program.prototype.listen = function() {
var self = this;
// Potentially reset window title on exit:
// var self = this;
// if (!this.isRxvt) {
// if (!this.isVTE) this.setTitleModeFeature(3);
// this.manipulateWindow(21, function(err, data) {
@ -319,14 +315,35 @@ Program.prototype.listen = function() {
// Listen for keys/mouse on input
if (!this.input._blessedListened) {
this.input._blessedListened = true;
this.input._blessedListened = 1;
this._listenInput();
} else {
this.input._blessedListened++;
}
this.on('newListener', this._newHandler = function fn(type) {
if (type === 'keypress' || type === 'mouse') {
self.removeListener('newListener', fn);
if (self.input.setRawMode && !self.input.isRaw) {
self.input.setRawMode(true);
self.input.resume();
}
}
});
this.on('newListener', function fn(type) {
if (type === 'mouse') {
self.removeListener('newListener', fn);
self.bindMouse();
}
});
// Listen for resize on output
if (!this.output._blessedListened) {
this.output._blessedListened = true;
this.output._blessedListened = 1;
this._listenOutput();
} else {
this.output._blessedListened++;
}
};
@ -335,7 +352,7 @@ Program.prototype._listenInput = function() {
, self = this;
// Input
this.input.on('keypress', function(ch, key) {
this.input.on('keypress', this.input._keypressHandler = function(ch, key) {
key = key || { ch: ch };
if (key.name === 'undefined'
@ -371,7 +388,7 @@ Program.prototype._listenInput = function() {
});
});
this.input.on('data', function(data) {
this.input.on('data', this.input._dataHandler = function(data) {
Program.instances.forEach(function(program) {
if (program.input !== self.input) return;
program.emit('data', data);
@ -379,29 +396,6 @@ Program.prototype._listenInput = function() {
});
keys.emitKeypressEvents(this.input);
this.on('newListener', function fn(type) {
if (type === 'keypress' || type === 'mouse') {
Program.instances.forEach(function(program) {
if (program.input !== self.input) return;
program.removeListener('newListener', fn);
if (program.input.setRawMode && !program.input.isRaw) {
program.input.setRawMode(true);
program.input.resume();
}
});
}
});
this.on('newListener', function fn(type) {
if (type === 'mouse') {
Program.instances.forEach(function(program) {
if (program.input !== self.input) return;
program.removeListener('newListener', fn);
program.bindMouse();
});
}
});
};
Program.prototype._listenOutput = function() {
@ -423,7 +417,7 @@ Program.prototype._listenOutput = function() {
});
}
this.output.on('resize', function() {
this.output.on('resize', this.output._resizeHandler = function() {
Program.instances.forEach(function(program) {
if (program.output !== self.output) return;
if (!program.options.resizeTimeout) {
@ -454,12 +448,20 @@ Program.prototype.destroy = function() {
if (Program.total === 0) {
Program.global = null;
process.removeAllListeners('exit');
process.removeListener('exit', Program._exitHandler);
delete Program._exitHandler;
this.input.removeAllListeners('keypress');
this.input.removeAllListeners('data');
this.input.removeAllListeners('newListener');
this.output.removeAllListeners('resize');
delete Program._bound;
}
this.input._blessedListened--;
this.output._blessedListened--;
if (this.input._blessedListened === 0) {
this.input.removeListener('keypress', this.input._keypressHandler);
this.input.removeListener('data', this.input._dataHandler);
delete this.input._keypressHandler;
delete this.input._dataHandler;
if (this.input.setRawMode) {
if (this.input.isRaw) {
@ -471,6 +473,14 @@ Program.prototype.destroy = function() {
}
}
if (this.output._blessedListened === 0) {
this.output.removeListener('resize', this.output._resizeHandler);
delete this.output._resizeHandler;
}
this.removeListener('newListener', this._newHandler);
delete this._newHandler;
this.destroyed = true;
this.emit('destroy');
}

View File

@ -35,7 +35,7 @@ function Screen(options) {
return new Screen(options);
}
Screen.bind(this, options || {});
Screen.bind(this);
options = options || {};
if (options.rsety && options.listen) {
@ -193,14 +193,9 @@ Screen.total = 0;
Screen.instances = [];
Screen.signals = true;
Screen.bind = function(screen, options) {
Screen.bind = function(screen) {
if (!Screen.global) {
Screen.global = screen;
if (options.signals === false) {
Screen.signals = false;
}
}
if (!~Screen.instances.indexOf(screen)) {
@ -211,7 +206,7 @@ Screen.bind = function(screen, options) {
if (Screen._bound) return;
Screen._bound = true;
process.on('uncaughtException', function(err) {
process.on('uncaughtException', Screen._exceptionHandler = function(err) {
if (process.listeners('uncaughtException').length > 1) {
return;
}
@ -220,33 +215,24 @@ Screen.bind = function(screen, options) {
});
err = err || new Error('Uncaught Exception.');
console.error(err.stack ? err.stack + '' : err + '');
if (Screen.total === 0) {
return process.exit(1);
}
nextTick(function() {
process.exit(1);
});
});
// XXX Multiple signal handlers and removal of signal
// handlers does not work, so we have this option instead.
if (Screen.signals) {
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach(function(signal) {
process.on(signal, function() {
if (process.listeners(signal).length > 1) {
return;
}
if (Screen.total === 0) {
return process.exit(0);
}
nextTick(function() {
process.exit(0);
});
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach(function(signal) {
var name = '_' + signal.toLowerCase() + 'Handler';
process.on(signal, Screen[name] = function() {
if (process.listeners(signal).length > 1) {
return;
}
nextTick(function() {
process.exit(0);
});
});
}
});
process.on('exit', function() {
process.on('exit', Screen._exitHandler = function() {
Screen.instances.slice().forEach(function(screen) {
screen.destroy();
});
@ -404,7 +390,18 @@ Screen.prototype.destroy = function() {
if (Screen.total === 0) {
Screen.global = null;
process.removeAllListeners('uncaughtException');
process.removeListener('uncaughtException', Screen._exceptionHandler);
process.removeListener('SIGTERM', Screen._sigtermHandler);
process.removeListener('SIGINT', Screen._sigintHandler);
process.removeListener('SIGQUIT', Screen._sigquitHandler);
process.removeListener('exit', Screen._exitHandler);
delete Screen._exceptionHandler;
delete Screen._sigtermHandler;
delete Screen._sigintHandler;
delete Screen._sigquitHandler;
delete Screen._exitHandler;
delete Screen._bound;
}
this.destroyed = true;
@ -564,7 +561,7 @@ Screen.prototype._listenKeys = function(el) {
var focused = self.focused
, grabKeys = self.grabKeys;
if (!grabKeys) {
if (!grabKeys || ~self.ignoreLocked.indexOf(key.full)) {
self.emit('keypress', ch, key);
self.emit('key ' + key.full, ch, key);
}

36
test/widget-exit.js Normal file
View File

@ -0,0 +1,36 @@
var blessed = require('../');
var screen = blessed.screen({
dump: __dirname + '/logs/exit.log',
smartCSR: true,
autoPadding: true,
warnings: true,
ignoreLocked: ['C-q']
});
var box = blessed.prompt({
parent: screen,
left: 'center',
top: 'center',
width: '70%',
height: 'shrink',
border: 'line'
});
screen.render();
box.input('Input: ', '', function(err, data) {
screen.destroy();
if (process.argv[2] === 'resume') {
process.stdin.resume();
} else if (process.argv[2] === 'end') {
process.stdin.setRawMode(false);
process.stdin.end();
}
if (err) throw err;
console.log('Input: ' + data);
});
screen.key('C-q', function(ch, key) {
return process.exit(0);
});