diff options
author | Pierre Ossman <ossman@cendio.se> | 2019-11-04 10:17:45 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2019-11-04 10:17:45 +0100 |
commit | ccb511a527a693d0de0ad58b430f73aa2fb74344 (patch) | |
tree | 9c2e0eeb457e40ba4e6aa49fd86f278aece8c03f | |
parent | 3388c92c7f55b4e77527d1481a52c27459345f46 (diff) | |
download | novnc-ccb511a527a693d0de0ad58b430f73aa2fb74344.tar.gz |
Handle missing Shift events on Windows
This is a bug in the OS that leaks through to the browsers. We need
to fake a Shift release here to avoid Shift getting stuck in the remote
session.
-rw-r--r-- | core/input/keyboard.js | 15 | ||||
-rw-r--r-- | tests/test.keyboard.js | 70 |
2 files changed, 85 insertions, 0 deletions
diff --git a/core/input/keyboard.js b/core/input/keyboard.js index 764288a..ab62378 100644 --- a/core/input/keyboard.js +++ b/core/input/keyboard.js @@ -281,6 +281,21 @@ export default class Keyboard { } this._sendKeyEvent(this._keyDownList[code], code, false); + + // Windows has a rather nasty bug where it won't send key + // release events for a Shift button if the other Shift is still + // pressed + if (browser.isWindows() && ((code === 'ShiftLeft') || + (code === 'ShiftRight'))) { + if ('ShiftRight' in this._keyDownList) { + this._sendKeyEvent(this._keyDownList['ShiftRight'], + 'ShiftRight', false); + } + if ('ShiftLeft' in this._keyDownList) { + this._sendKeyEvent(this._keyDownList['ShiftLeft'], + 'ShiftLeft', false); + } + } } _handleAltGrTimeout() { diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index 170149f..f5807e9 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -459,4 +459,74 @@ describe('Key Event Handling', function () { expect(kbd.onkeyevent).to.have.been.calledWith(0xfe03, 'AltRight', true); }); }); + + describe('Missing Shift keyup 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"); + if (origNavigator === undefined) { + // Object.getOwnPropertyDescriptor() doesn't work + // properly in any version of IE + this.skip(); + } + + 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 x86_64"; + + this.clock = sinon.useFakeTimers(); + }); + afterEach(function () { + Object.defineProperty(window, "navigator", origNavigator); + this.clock.restore(); + }); + + it('should fake a left Shift keyup', function () { + const kbd = new Keyboard(document); + kbd.onkeyevent = sinon.spy(); + + kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftLeft', key: 'Shift', location: 1})); + expect(kbd.onkeyevent).to.have.been.calledOnce; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', true); + kbd.onkeyevent.resetHistory(); + + kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftRight', key: 'Shift', location: 2})); + expect(kbd.onkeyevent).to.have.been.calledOnce; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', true); + kbd.onkeyevent.resetHistory(); + + kbd._handleKeyUp(keyevent('keyup', {code: 'ShiftLeft', key: 'Shift', location: 1})); + expect(kbd.onkeyevent).to.have.been.calledTwice; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', false); + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', false); + }); + + it('should fake a right Shift keyup', function () { + const kbd = new Keyboard(document); + kbd.onkeyevent = sinon.spy(); + + kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftLeft', key: 'Shift', location: 1})); + expect(kbd.onkeyevent).to.have.been.calledOnce; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', true); + kbd.onkeyevent.resetHistory(); + + kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftRight', key: 'Shift', location: 2})); + expect(kbd.onkeyevent).to.have.been.calledOnce; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', true); + kbd.onkeyevent.resetHistory(); + + kbd._handleKeyUp(keyevent('keyup', {code: 'ShiftRight', key: 'Shift', location: 2})); + expect(kbd.onkeyevent).to.have.been.calledTwice; + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', false); + expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', false); + }); + }); }); |