This commit is contained in:
Pierre Ossman 2022-10-19 14:16:29 +02:00
commit cd94c2aed2
2 changed files with 71 additions and 0 deletions

View File

@ -153,6 +153,16 @@ export default class Keyboard {
keysym = this._keyDownList[code]; 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 // macOS doesn't send proper key events for modifiers, only
// state change events. That gets extra confusing for CapsLock // state change events. That gets extra confusing for CapsLock
// which toggles on each press, but not on release. So pretend // which toggles on each press, but not on release. So pretend

View File

@ -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 () { describe('Caps Lock on iOS and macOS', function () {
let origNavigator; let origNavigator;
beforeEach(function () { beforeEach(function () {