mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Fix third level shifts for Mac OS and windows
ISO third level keys were not working. That prevented some inputting important characters (like pipe `|` and caret `^`) on some keyboard layouts. Instead of parsing the user-agent string to find the users os, we now look into the `platform` attribute of the `navigator` object. Removed the hijacking of the command key `⌘` on Mac OS as the `Alt` key on other systems.
This commit is contained in:
+47
-7
@@ -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
@@ -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 })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user