improve focus behavior.

This commit is contained in:
Christopher Jeffrey
2013-08-08 09:06:16 -05:00
parent 9127316158
commit 6cc8b3cd8a
5 changed files with 274 additions and 11 deletions
+11
View File
@@ -0,0 +1,11 @@
.git*
build/
.lock-wscript
out/
Makefile.gyp
*.Makefile
*.target.gyp.mk
node_modules/
img/
test/
*.node
+53
View File
@@ -0,0 +1,53 @@
<!doctype html>
<title>tty.js</title>
<!--
tty.js
Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
-->
<style>
h1 {
margin-bottom: 20px;
font: 20px/1.5 sans-serif;
}
.terminal {
float: left;
border: #000 solid 5px;
font-family: "DejaVu Sans Mono", "Liberation Mono", monospace;
font-size: 11px;
color: #f0f0f0;
background: #000;
}
.reverse-video {
color: #000;
background: #f0f0f0;
}
</style>
<h1>tty.js</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="term.js"></script>
<script>
;(function() {
return setTimeout(function() {
var term = new Terminal(80, 24)
, socket = io.connect();
socket.on('connect', function() {
term.on('data', function(data) {
socket.emit('data', data);
});
term.on('title', function(title) {
document.title = title;
});
term.open();
socket.on('data', function(data) {
term.write(data);
});
});
}, 1000);
}).call(this);
</script>
+93
View File
@@ -0,0 +1,93 @@
/**
* tty.js
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
*/
var http = require('http')
, express = require('express')
, io = require('socket.io')
, pty = require('pty.js');
/**
* tty.js
*/
process.title = 'tty.js';
/**
* Open Terminal
*/
var buff = []
, socket
, term;
var term = pty.fork(process.env.SHELL || 'sh', [], {
name: 'xterm',
cols: 80,
rows: 24,
cwd: process.env.HOME
});
term.on('data', function(data) {
return !socket
? buff.push(data)
: socket.emit('data', data);
});
console.log(''
+ 'Created shell with pty master/slave'
+ ' pair (master: %d, pid: %d)',
term.fd, term.pid);
/**
* App & Server
*/
var app = express()
, server = http.createServer(app);
app.use(function(req, res, next) {
var setHeader = res.setHeader;
res.setHeader = function(name) {
switch (name) {
case 'Cache-Control':
case 'Last-Modified':
case 'ETag':
return;
}
return setHeader.apply(res, arguments);
};
next();
});
app.use(express.static(__dirname));
app.use(express.static(__dirname + '/../lib'));
server.listen(8080);
/**
* Sockets
*/
io = io.listen(server);
io.configure(function() {
io.disable('log');
});
io.sockets.on('connection', function(sock) {
socket = sock;
socket.on('data', function(data) {
term.write(data);
});
socket.on('disconnect', function() {
socket = null;
});
while (buff.length) {
socket.emit('data', buff.shift());
}
});
+2 -1
View File
@@ -1,6 +1,7 @@
/**
* term.js - an xterm emulator
* Copyright (c) 2013, Christopher Jeffrey (https://github.com/chjj/term.js)
* Copyright (c) 2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
*/
function term(options) {
+115 -10
View File
@@ -1,7 +1,7 @@
/**
* term.js - an xterm emulator
*
* Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/term.js)
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
* https://github.com/chjj/term.js
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -262,6 +262,25 @@ Terminal.colors = [
'#eeeeec'
];
Terminal.xtermColors = [
'#000000', // black
'#cd0000', // red3
'#00cd00', // green3
'#cdcd00', // yellow3
'#0000ee', // blue2
'#cd00cd', // magenta3
'#00cdcd', // cyan3
'#e5e5e5', // gray90
'#7f7f7f', // gray50
'#ff0000', // red
'#00ff00', // green
'#ffff00', // yellow
'#5c5cff', // rgb:5c/5c/ff
'#ff00ff', // magenta
'#00ffff', // cyan
'#ffffff' // white
];
// Colors 16-255
// Much thanks to TooTallNate for writing this.
Terminal.colors = (function() {
@@ -326,14 +345,41 @@ Terminal.focus = null;
Terminal.prototype.focus = function() {
if (Terminal.focus === this) return;
if (Terminal.focus) {
Terminal.focus.cursorState = 0;
Terminal.focus.refresh(Terminal.focus.y, Terminal.focus.y);
if (Terminal.focus.sendFocus) Terminal.focus.send('\x1b[O');
Terminal.focus.blur();
}
Terminal.focus = this;
if (this.sendFocus) this.send('\x1b[I');
this.showCursor();
// try {
// this.element.focus();
// } catch (e) {
// ;
// }
// this.emit('focus');
Terminal.focus = this;
};
Terminal.prototype.blur = function() {
if (Terminal.focus !== this) return;
this.cursorState = 0;
this.refresh(this.y, this.y);
if (this.sendFocus) this.send('\x1b[O');
// try {
// this.element.blur();
// } catch (e) {
// ;
// }
// this.emit('blur');
Terminal.focus = null;
};
/**
@@ -341,17 +387,57 @@ Terminal.prototype.focus = function() {
*/
Terminal.bindKeys = function(document) {
if (Terminal.focus) return;
Terminal._boundDocs = Terminal._boundDocs || [];
if (~indexOf(Terminal._boundDocs, document)) {
return;
}
Terminal._boundDocs.push(document);
// We could put an "if (Terminal.focus)" check
// here, but it shouldn't be necessary.
on(document, 'keydown', function(ev) {
return Terminal.focus.keyDown(ev);
if (!Terminal.focus) return;
var target = ev.target || ev.srcElement;
// Should just be body, but we can
// check everything for good measure.
if (target === Terminal.focus.element
|| target === Terminal.focus.context
|| target === Terminal.focus.document
|| target === Terminal.focus.document.body
|| target === Terminal.focus.parent) {
return Terminal.focus.keyDown(ev);
}
}, true);
on(document, 'keypress', function(ev) {
return Terminal.focus.keyPress(ev);
if (!Terminal.focus) return;
var target = ev.target || ev.srcElement;
// Should just be body, but we can
// check everything for good measure.
if (target === Terminal.focus.element
|| target === Terminal.focus.context
|| target === Terminal.focus.document
|| target === Terminal.focus.document.body
|| target === Terminal.focus.parent) {
return Terminal.focus.keyPress(ev);
}
}, true);
// If we click somewhere other than a
// terminal, unfocus the terminal.
on(document, 'mousedown', function(ev) {
if (!Terminal.focus) return;
var el = ev.target || ev.srcElement;
do {
if (el === Terminal.focus.element) return;
} while (el = el.parentNode);
Terminal.focus.blur();
});
};
/**
@@ -367,6 +453,9 @@ Terminal.prototype.open = function(parent) {
this.element = this.document.createElement('div');
this.element.className = 'terminal';
this.element.style.outline = 'none';
this.element.setAttribute('tabindex', 0);
this.children = [];
for (; i < this.rows; i++) {
@@ -385,6 +474,14 @@ Terminal.prototype.open = function(parent) {
this.startBlink();
on(this.element, 'focus', function() {
self.focus();
});
// on(this.element, 'blur', function() {
// self.blur();
// });
on(this.element, 'mousedown', function() {
self.focus();
});
@@ -434,7 +531,7 @@ Terminal.prototype.open = function(parent) {
this.element.style.backgroundColor = Terminal.defaultColors.bg;
this.element.style.color = Terminal.defaultColors.fg;
//this.emit('open');
this.emit('open');
};
// XTerm mouse events
@@ -4231,6 +4328,14 @@ var String = this.String;
var setTimeout = this.setTimeout;
var setInterval = this.setInterval;
function indexOf(obj, el) {
var i = obj.length;
while (i--) {
if (obj[i] === el) return i;
}
return -1;
}
/**
* Expose
*/