Merge pull request #60 from runarberg/master

Fix cross platform input problems
This commit is contained in:
Paris Kasidiaris
2016-06-10 19:32:45 +03:00
committed by GitHub
2 changed files with 169 additions and 7 deletions
+47 -7
View File
@@ -659,12 +659,27 @@
* Parse User-Agent
*/
if (this.context.navigator && this.context.navigator.userAgent) {
this.isMac = !!~this.context.navigator.userAgent.indexOf('Mac');
this.isIpad = !!~this.context.navigator.userAgent.indexOf('iPad');
this.isIphone = !!~this.context.navigator.userAgent.indexOf('iPhone');
this.isMSIE = !!~this.context.navigator.userAgent.indexOf('MSIE');
}
/*
* Find the users platform. We use this to interpret the meta key
* and ISO third level shifts.
* http://stackoverflow.com/questions/19877924/what-is-the-list-of-possible-values-for-navigator-platform-as-of-today
*/
if (this.context.navigator && this.context.navigator.platform) {
this.isMac = contains(
this.context.navigator.platform,
['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K']
);
this.isIpad = this.context.navigator.platform === 'iPad';
this.isIphone = this.context.navigator.platform === 'iPhone';
this.isMSWindows = contains(
this.context.navigator.platform,
['Windows', 'Win16', 'Win32', 'WinCE']
);
}
/*
* Create main element container
*/
@@ -2337,12 +2352,16 @@
return this.cancel(ev);
}
if (result.cancel) {
if (isThirdLevelShift(this, ev)) {
return true;
}
if (result.cancel ) {
// The event is canceled at the end already, is this necessary?
this.cancel(ev, true);
}
if (!result.key || (this.isMac && ev.metaKey)) {
if (!result.key) {
return true;
}
@@ -2532,7 +2551,8 @@
// ^] - group sep
result.key = String.fromCharCode(29);
}
} else if ((!this.isMac && ev.altKey) || (this.isMac && ev.metaKey)) {
} else if (!this.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) {
// On Mac this is a third level shift. Use <Esc> instead.
if (ev.keyCode >= 65 && ev.keyCode <= 90) {
result.key = '\x1b' + String.fromCharCode(ev.keyCode + 32);
} else if (ev.keyCode === 192) {
@@ -2571,7 +2591,9 @@
return false;
}
if (!key || ev.ctrlKey || ev.altKey || ev.metaKey) {
if (!key || (
(ev.altKey || ev.ctrlKey || ev.metaKey) && !isThirdLevelShift(this, ev)
)) {
return false;
}
@@ -4398,6 +4420,15 @@
* Helpers
*/
function contains(el, arr) {
for (var i = 0; i < arr.length; i += 1) {
if (el === arr[i]) {
return true;
}
}
return false;
}
function on(el, type, handler, capture) {
if (!Array.isArray(el)) {
el = [el];
@@ -4454,6 +4485,15 @@
return -1;
}
function isThirdLevelShift(term, ev) {
var thirdLevelKey =
(term.isMac && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||
(term.isMSWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);
// Don't invoke for arrows, pageDown, home, backspace, etc.
return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);
}
function isWide(ch) {
if (ch <= '\uff00') return false;
return (ch >= '\uff01' && ch <= '\uffbe')
+122
View File
@@ -68,4 +68,126 @@ describe('xterm.js', function() {
assert.equal(processedText.indexOf(nonBreakingSpace), -1);
});
});
describe('Third level shift', function() {
var ev = {
preventDefault: function() {},
stopPropagation: function() {}
};
beforeEach(function() {
xterm.handler = function() {};
xterm.showCursor = function() {};
xterm.clearSelection = function() {};
})
describe('On Mac OS', function() {
beforeEach(function() {
xterm.isMac = true;
});
it('should not interfere with the alt key on keyDown', function() {
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, keyCode: 81 })),
true
);
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, keyCode: 192 })),
true
);
});
it('should interefere with the alt + arrow keys', function() {
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, keyCode: 37 })),
false
);
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, keyCode: 39 })),
false
);
});
it('should emit key with alt + key on keyPress', function(done) {
var keys = ['@', '@', '\\', '\\', '|', '|'];
xterm.on('keypress', function(key) {
if (key) {
var index = keys.indexOf(key);
assert(index !== -1, "Emitted wrong key: " + key);
keys.splice(index, 1);
}
if (keys.length === 0) done();
});
xterm.keyPress(Object.assign({}, ev, { altKey: true, keyCode: 64 })); // @
// Firefox
xterm.keyPress(Object.assign({}, ev, { altKey: true, charCode: 64, keyCode: 0 }));
xterm.keyPress(Object.assign({}, ev, { altKey: true, keyCode: 92 })); // \
xterm.keyPress(Object.assign({}, ev, { altKey: true, charCode: 92, keyCode: 0 }));
xterm.keyPress(Object.assign({}, ev, { altKey: true, keyCode: 124 })); // |
xterm.keyPress(Object.assign({}, ev, { altKey: true, charCode: 124, keyCode: 0 }));
});
});
describe('On MS Windows', function() {
beforeEach(function() {
xterm.isMSWindows = true;
});
it('should not interfere with the alt + ctrl key on keyDown', function() {
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 81 })),
true
);
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 192 })),
true
);
});
it('should interefere with the alt + ctrl + arrow keys', function() {
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 37 })),
false
);
assert.equal(
xterm.keyDown(Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 39 })),
false
);
});
it('should emit key with alt + ctrl + key on keyPress', function(done) {
var keys = ['@', '@', '\\', '\\', '|', '|'];
xterm.on('keypress', function(key) {
if (key) {
var index = keys.indexOf(key);
assert(index !== -1, "Emitted wrong key: " + key);
keys.splice(index, 1);
}
if (keys.length === 0) done();
});
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 64 })
); // @
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, charCode: 64, keyCode: 0 })
);
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 92 })
); // \
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, charCode: 92, keyCode: 0 })
);
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, keyCode: 124 })
); // |
xterm.keyPress(
Object.assign({}, ev, { altKey: true, ctrlKey: true, charCode: 124, keyCode: 0 })
);
});
});
});
});