diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js
index da4d3e61..0338d452 100644
--- a/ext/js/dom/document-util.js
+++ b/ext/js/dom/document-util.js
@@ -311,6 +311,22 @@ class DocumentUtil {
return !(browser === 'firefox' || browser === 'firefox-mobile') || os === 'mac';
}
+ static isInputElementFocused() {
+ const element = document.activeElement;
+ if (element === null) { return false; }
+ const type = element.nodeName.toUpperCase();
+ switch (type) {
+ case 'INPUT':
+ case 'TEXTAREA':
+ case 'SELECT':
+ return true;
+ default:
+ return element.isContentEditable;
+ }
+ }
+
+ // Private
+
static _getActiveButtons(event, array) {
let {buttons} = event;
if (typeof buttons === 'number' && buttons > 0) {
@@ -325,8 +341,6 @@ class DocumentUtil {
}
}
- // Private
-
_setImposterStyle(style, propertyName, value) {
style.setProperty(propertyName, value, 'important');
}
diff --git a/ext/js/input/hotkey-handler.js b/ext/js/input/hotkey-handler.js
index 8388302d..6c63aebb 100644
--- a/ext/js/input/hotkey-handler.js
+++ b/ext/js/input/hotkey-handler.js
@@ -153,11 +153,10 @@ class HotkeyHandler extends EventDispatcher {
// Private
_onKeyDown(e) {
- const key = e.code;
- const hotkeyInfo = this._hotkeys.get(key);
+ const hotkeyInfo = this._hotkeys.get(e.code);
if (typeof hotkeyInfo !== 'undefined') {
const eventModifiers = DocumentUtil.getActiveModifiers(e);
- if (this._invokeHandlers(eventModifiers, hotkeyInfo)) {
+ if (this._invokeHandlers(eventModifiers, hotkeyInfo, e.key)) {
e.preventDefault();
return;
}
@@ -165,9 +164,9 @@ class HotkeyHandler extends EventDispatcher {
this.trigger('keydownNonHotkey', e);
}
- _invokeHandlers(modifiers, hotkeyInfo) {
+ _invokeHandlers(modifiers, hotkeyInfo, key) {
for (const {modifiers: handlerModifiers, action, argument} of hotkeyInfo.handlers) {
- if (!this._areSame(handlerModifiers, modifiers)) { continue; }
+ if (!this._areSame(handlerModifiers, modifiers) || !this._isHotkeyPermitted(modifiers, key)) { continue; }
const actionHandler = this._actions.get(action);
if (typeof actionHandler !== 'undefined') {
@@ -223,4 +222,16 @@ class HotkeyHandler extends EventDispatcher {
this._eventListeners.removeAllEventListeners();
}
}
+
+ _isHotkeyPermitted(modifiers, key) {
+ return !(
+ (modifiers.length === 0 || (modifiers.length === 1 && modifiers[0] === 'shift')) &&
+ DocumentUtil.isInputElementFocused() &&
+ this._isKeyCharacterInput(key)
+ );
+ }
+
+ _isKeyCharacterInput(key) {
+ return key.length === 1;
+ }
}
diff --git a/ext/js/pages/settings/settings-display-controller.js b/ext/js/pages/settings/settings-display-controller.js
index 9d3e5459..7a40381b 100644
--- a/ext/js/pages/settings/settings-display-controller.js
+++ b/ext/js/pages/settings/settings-display-controller.js
@@ -16,6 +16,7 @@
*/
/* global
+ * DocumentUtil
* PopupMenu
* SelectorObserver
*/
@@ -155,7 +156,7 @@ class SettingsDisplayController {
_onKeyDown(e) {
switch (e.code) {
case 'Escape':
- if (!this._isElementAnInput(document.activeElement)) {
+ if (!DocumentUtil.isInputElementFocused()) {
this._closeTopMenuOrModal();
e.preventDefault();
}
@@ -357,18 +358,6 @@ class SettingsDisplayController {
}
}
- _isElementAnInput(element) {
- const type = element !== null ? element.nodeName.toUpperCase() : null;
- switch (type) {
- case 'INPUT':
- case 'TEXTAREA':
- case 'SELECT':
- return true;
- default:
- return false;
- }
- }
-
_setupDeferLoadIframe(element) {
const parent = this._getMoreContainer(element);
if (parent === null) { return; }
diff --git a/ext/permissions.html b/ext/permissions.html
index 49daa940..04d1d5fa 100644
--- a/ext/permissions.html
+++ b/ext/permissions.html
@@ -263,6 +263,7 @@
+