summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2022-10-19 14:16:29 +0200
committerPierre Ossman <ossman@cendio.se>2022-10-19 14:16:29 +0200
commitcd94c2aed2582fd85ec5ecc444967fc7ec60a649 (patch)
treeb45681771b8330cc08690c564b910d26dc3f9072
parent8715ed9e7010c83cb96a519e5569a5d0cad51bca (diff)
parent1971823a4fb77866d392ce0d673e777d4f468439 (diff)
downloadnovnc-cd94c2aed2582fd85ec5ecc444967fc7ec60a649.tar.gz
Merge branch 'fix-1695' of https://github.com/m1k1o/noVNC
-rw-r--r--core/input/keyboard.js10
-rw-r--r--tests/test.keyboard.js61
2 files changed, 71 insertions, 0 deletions
diff --git a/core/input/keyboard.js b/core/input/keyboard.js
index 48f65cf..ddb5ce0 100644
--- a/core/input/keyboard.js
+++ b/core/input/keyboard.js
@@ -153,6 +153,16 @@ export default class Keyboard {
keysym = this._keyDownList[code];
}
+ // macOS doesn't send proper key releases if a key is pressed
+ // while meta is held down
+ if ((browser.isMac() || browser.isIOS()) &&
+ (e.metaKey && code !== 'MetaLeft' && code !== 'MetaRight')) {
+ this._sendKeyEvent(keysym, code, true);
+ this._sendKeyEvent(keysym, code, false);
+ stopEvent(e);
+ return;
+ }
+
// macOS doesn't send proper key events for modifiers, only
// state change events. That gets extra confusing for CapsLock
// which toggles on each press, but not on release. So pretend
diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js
index 381cd30..6b59cde 100644
--- a/tests/test.keyboard.js
+++ b/tests/test.keyboard.js
@@ -197,6 +197,67 @@ describe('Key Event Handling', function () {
});
});
+ describe('Meta key combination on iOS and macOS', 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();
+ }
+ });
+
+ afterEach(function () {
+ if (origNavigator !== undefined) {
+ Object.defineProperty(window, "navigator", origNavigator);
+ }
+ });
+
+ it('should send keyup when meta key is pressed on iOS', function () {
+ window.navigator.platform = "iPad";
+ const kbd = new Keyboard(document);
+ kbd.onkeyevent = sinon.spy();
+
+ kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledOnce;
+ kbd.onkeyevent.resetHistory();
+
+ kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a', metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledTwice;
+ expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", true);
+ expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", false);
+ kbd.onkeyevent.resetHistory();
+
+ kbd._handleKeyUp(keyevent('keyup', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledOnce;
+ });
+
+ it('should send keyup when meta key is pressed on macOS', function () {
+ window.navigator.platform = "Mac";
+ const kbd = new Keyboard(document);
+ kbd.onkeyevent = sinon.spy();
+
+ kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledOnce;
+ kbd.onkeyevent.resetHistory();
+
+ kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a', metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledTwice;
+ expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", true);
+ expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", false);
+ kbd.onkeyevent.resetHistory();
+
+ kbd._handleKeyUp(keyevent('keyup', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
+ expect(kbd.onkeyevent).to.have.been.calledOnce;
+ });
+ });
+
describe('Caps Lock on iOS and macOS', function () {
let origNavigator;
beforeEach(function () {