From 3a7c0c67c174d880a1df11b6c2f6c020dd492451 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 9 Mar 2018 16:51:23 +0100 Subject: [PATCH] Work around broken Alt keyup in Firefox Firefox no longer sends keyup events properly for the Alt keys. Try to sniff out the state of the Alt key by monitoring other events that include its state. --- core/input/keyboard.js | 46 +++++++++++++++++++++++++++++++++++++++++- core/util/browser.js | 4 ++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/core/input/keyboard.js b/core/input/keyboard.js index 4e8dc0d5..081a00ab 100644 --- a/core/input/keyboard.js +++ b/core/input/keyboard.js @@ -27,7 +27,8 @@ export default function Keyboard(target) { 'keyup': this._handleKeyUp.bind(this), 'keydown': this._handleKeyDown.bind(this), 'keypress': this._handleKeyPress.bind(this), - 'blur': this._allKeysUp.bind(this) + 'blur': this._allKeysUp.bind(this), + 'checkalt': this._checkAlt.bind(this), }; }; @@ -281,6 +282,26 @@ Keyboard.prototype = { Log.Debug("<< Keyboard.allKeysUp"); }, + // Firefox Alt workaround, see below + _checkAlt: function (e) { + if (e.altKey) { + return; + } + + let target = this._target; + let downList = this._keyDownList; + ['AltLeft', 'AltRight'].forEach(function (code) { + if (!(code in downList)) { + return; + } + + let event = new KeyboardEvent('keyup', + { key: downList[code], + code: code }); + target.dispatchEvent(event); + }); + }, + // ===== PUBLIC METHODS ===== grab: function () { @@ -294,6 +315,20 @@ Keyboard.prototype = { // Release (key up) if window loses focus window.addEventListener('blur', this._eventHandlers.blur); + // Firefox has broken handling of Alt, so we need to poll as + // best we can for releases (still doesn't prevent the menu + // from popping up though as we can't call preventDefault()) + if (browser.isWindows() && browser.isFirefox()) { + let handler = this._eventHandlers.checkalt; + ['mousedown', 'mouseup', 'mousemove', 'wheel', + 'touchstart', 'touchend', 'touchmove', + 'keydown', 'keyup'].forEach(function (type) { + document.addEventListener(type, handler, + { capture: true, + passive: true }); + }); + } + //Log.Debug("<< Keyboard.grab"); }, @@ -301,6 +336,15 @@ Keyboard.prototype = { //Log.Debug(">> Keyboard.ungrab"); var c = this._target; + if (browser.isWindows() && browser.isFirefox()) { + let handler = this._eventHandlers.checkalt; + ['mousedown', 'mouseup', 'mousemove', 'wheel', + 'touchstart', 'touchend', 'touchmove', + 'keydown', 'keyup'].forEach(function (type) { + document.removeEventListener(type, handler); + }); + } + c.removeEventListener('keydown', this._eventHandlers.keydown); c.removeEventListener('keyup', this._eventHandlers.keyup); c.removeEventListener('keypress', this._eventHandlers.keypress); diff --git a/core/util/browser.js b/core/util/browser.js index ab0e7ee3..7a78eee0 100644 --- a/core/util/browser.js +++ b/core/util/browser.js @@ -56,6 +56,10 @@ export function isEdge() { return navigator && !!(/edge/i).exec(navigator.userAgent); } +export function isFirefox() { + return navigator && !!(/firefox/i).exec(navigator.userAgent); +} + export function isWindows() { return navigator && !!(/win/i).exec(navigator.platform); }