Merge branch 'jp' of https://github.com/CendioOssman/noVNC
This commit is contained in:
commit
67ac9f9c0d
|
@ -119,7 +119,7 @@ addStandard("WakeUp", KeyTable.XF86XK_WakeUp);
|
||||||
// 2.8. IME and Composition Keys
|
// 2.8. IME and Composition Keys
|
||||||
|
|
||||||
addStandard("AllCandidates", KeyTable.XK_MultipleCandidate);
|
addStandard("AllCandidates", KeyTable.XK_MultipleCandidate);
|
||||||
addStandard("Alphanumeric", KeyTable.XK_Eisu_Shift); // could also be _Eisu_Toggle
|
addStandard("Alphanumeric", KeyTable.XK_Eisu_toggle);
|
||||||
addStandard("CodeInput", KeyTable.XK_Codeinput);
|
addStandard("CodeInput", KeyTable.XK_Codeinput);
|
||||||
addStandard("Compose", KeyTable.XK_Multi_key);
|
addStandard("Compose", KeyTable.XK_Multi_key);
|
||||||
addStandard("Convert", KeyTable.XK_Henkan);
|
addStandard("Convert", KeyTable.XK_Henkan);
|
||||||
|
@ -147,7 +147,7 @@ addStandard("KanjiMode", KeyTable.XK_Kanji);
|
||||||
addStandard("Katakana", KeyTable.XK_Katakana);
|
addStandard("Katakana", KeyTable.XK_Katakana);
|
||||||
addStandard("Romaji", KeyTable.XK_Romaji);
|
addStandard("Romaji", KeyTable.XK_Romaji);
|
||||||
addStandard("Zenkaku", KeyTable.XK_Zenkaku);
|
addStandard("Zenkaku", KeyTable.XK_Zenkaku);
|
||||||
addStandard("ZenkakuHanaku", KeyTable.XK_Zenkaku_Hankaku);
|
addStandard("ZenkakuHankaku", KeyTable.XK_Zenkaku_Hankaku);
|
||||||
|
|
||||||
// 2.9. General-Purpose Function Keys
|
// 2.9. General-Purpose Function Keys
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,20 @@ export default class Keyboard {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Windows doesn't send proper key releases for a bunch of
|
||||||
|
// Japanese IM keys so we have to fake the release right away
|
||||||
|
const jpBadKeys = [ KeyTable.XK_Zenkaku_Hankaku,
|
||||||
|
KeyTable.XK_Eisu_toggle,
|
||||||
|
KeyTable.XK_Katakana,
|
||||||
|
KeyTable.XK_Hiragana,
|
||||||
|
KeyTable.XK_Romaji ];
|
||||||
|
if (browser.isWindows() && jpBadKeys.includes(keysym)) {
|
||||||
|
this._sendKeyEvent(keysym, code, true);
|
||||||
|
this._sendKeyEvent(keysym, code, false);
|
||||||
|
stopEvent(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stopEvent(e);
|
stopEvent(e);
|
||||||
|
|
||||||
// Possible start of AltGr sequence? (see above)
|
// Possible start of AltGr sequence? (see above)
|
||||||
|
|
|
@ -157,6 +157,21 @@ export function getKeysym(evt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Windows sends alternating symbols for some keys when using a
|
||||||
|
// Japanese layout. We have no way of synchronising with the IM
|
||||||
|
// running on the remote system, so we send some combined keysym
|
||||||
|
// instead and hope for the best.
|
||||||
|
if (browser.isWindows()) {
|
||||||
|
switch (key) {
|
||||||
|
case 'Zenkaku':
|
||||||
|
case 'Hankaku':
|
||||||
|
return KeyTable.XK_Zenkaku_Hankaku;
|
||||||
|
case 'Romaji':
|
||||||
|
case 'KanaMode':
|
||||||
|
return KeyTable.XK_Romaji;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return DOMKeyTable[key][location];
|
return DOMKeyTable[key][location];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,5 +186,38 @@ describe('Helpers', function () {
|
||||||
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: ',', location: 3})).to.be.equal(0xFFAC);
|
expect(KeyboardUtil.getKeysym({code: 'NumpadDecimal', key: ',', location: 3})).to.be.equal(0xFFAC);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Japanese IM keys on Windows', function () {
|
||||||
|
let origNavigator;
|
||||||
|
beforeEach(function () {
|
||||||
|
// window.navigator is a protected read-only property in many
|
||||||
|
// environments, so we need to redefine it whilst running these
|
||||||
|
// tests.
|
||||||
|
origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
|
||||||
|
|
||||||
|
Object.defineProperty(window, "navigator", {value: {}});
|
||||||
|
if (window.navigator.platform !== undefined) {
|
||||||
|
// Object.defineProperty() doesn't work properly in old
|
||||||
|
// versions of Chrome
|
||||||
|
this.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.navigator.platform = "Windows";
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
if (origNavigator !== undefined) {
|
||||||
|
Object.defineProperty(window, "navigator", origNavigator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const keys = { 'Zenkaku': 0xff2a, 'Hankaku': 0xff2a,
|
||||||
|
'Romaji': 0xff24, 'KanaMode': 0xff24 };
|
||||||
|
for (let [key, keysym] of Object.entries(keys)) {
|
||||||
|
it(`should fake combined key for ${key} on Windows`, function () {
|
||||||
|
expect(KeyboardUtil.getKeysym({code: 'FakeIM', key: key})).to.be.equal(keysym);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -219,7 +219,7 @@ describe('Key Event Handling', function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle caps lock on key press on iOS', function (done) {
|
it('should toggle caps lock on key press on iOS', function () {
|
||||||
window.navigator.platform = "iPad";
|
window.navigator.platform = "iPad";
|
||||||
const kbd = new Keyboard(document);
|
const kbd = new Keyboard(document);
|
||||||
kbd.onkeyevent = sinon.spy();
|
kbd.onkeyevent = sinon.spy();
|
||||||
|
@ -228,10 +228,9 @@ describe('Key Event Handling', function () {
|
||||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle caps lock on key press on mac', function (done) {
|
it('should toggle caps lock on key press on mac', function () {
|
||||||
window.navigator.platform = "Mac";
|
window.navigator.platform = "Mac";
|
||||||
const kbd = new Keyboard(document);
|
const kbd = new Keyboard(document);
|
||||||
kbd.onkeyevent = sinon.spy();
|
kbd.onkeyevent = sinon.spy();
|
||||||
|
@ -240,10 +239,9 @@ describe('Key Event Handling', function () {
|
||||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle caps lock on key release on iOS', function (done) {
|
it('should toggle caps lock on key release on iOS', function () {
|
||||||
window.navigator.platform = "iPad";
|
window.navigator.platform = "iPad";
|
||||||
const kbd = new Keyboard(document);
|
const kbd = new Keyboard(document);
|
||||||
kbd.onkeyevent = sinon.spy();
|
kbd.onkeyevent = sinon.spy();
|
||||||
|
@ -252,10 +250,9 @@ describe('Key Event Handling', function () {
|
||||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle caps lock on key release on mac', function (done) {
|
it('should toggle caps lock on key release on mac', function () {
|
||||||
window.navigator.platform = "Mac";
|
window.navigator.platform = "Mac";
|
||||||
const kbd = new Keyboard(document);
|
const kbd = new Keyboard(document);
|
||||||
kbd.onkeyevent = sinon.spy();
|
kbd.onkeyevent = sinon.spy();
|
||||||
|
@ -264,10 +261,50 @@ describe('Key Event Handling', function () {
|
||||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Japanese IM keys on Windows', function () {
|
||||||
|
let origNavigator;
|
||||||
|
beforeEach(function () {
|
||||||
|
// window.navigator is a protected read-only property in many
|
||||||
|
// environments, so we need to redefine it whilst running these
|
||||||
|
// tests.
|
||||||
|
origNavigator = Object.getOwnPropertyDescriptor(window, "navigator");
|
||||||
|
|
||||||
|
Object.defineProperty(window, "navigator", {value: {}});
|
||||||
|
if (window.navigator.platform !== undefined) {
|
||||||
|
// Object.defineProperty() doesn't work properly in old
|
||||||
|
// versions of Chrome
|
||||||
|
this.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.navigator.platform = "Windows";
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
if (origNavigator !== undefined) {
|
||||||
|
Object.defineProperty(window, "navigator", origNavigator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const keys = { 'Zenkaku': 0xff2a, 'Hankaku': 0xff2a,
|
||||||
|
'Alphanumeric': 0xff30, 'Katakana': 0xff26,
|
||||||
|
'Hiragana': 0xff25, 'Romaji': 0xff24,
|
||||||
|
'KanaMode': 0xff24 };
|
||||||
|
for (let [key, keysym] of Object.entries(keys)) {
|
||||||
|
it(`should fake key release for ${key} on Windows`, function () {
|
||||||
|
let kbd = new Keyboard(document);
|
||||||
|
kbd.onkeyevent = sinon.spy();
|
||||||
|
kbd._handleKeyDown(keyevent('keydown', {code: 'FakeIM', key: key}));
|
||||||
|
|
||||||
|
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||||
|
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(keysym, "FakeIM", true);
|
||||||
|
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(keysym, "FakeIM", false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe('Escape AltGraph on Windows', function () {
|
describe('Escape AltGraph on Windows', function () {
|
||||||
let origNavigator;
|
let origNavigator;
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
|
Loading…
Reference in New Issue