diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index a5d4ac9c4..3e2fae464 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -98,6 +98,7 @@ pref('zen.view.sidebar-collapsed.hide-mute-button', true); pref('zen.keyboard.shortcuts.enabled', true); pref('zen.keyboard.shortcuts', ""); // Empty string means default shortcuts +pref('zen.keyboard.shortcuts.disable-firefox', false); pref('zen.tabs.dim-pending', true); pref('zen.themes.updated-value-observer', false); @@ -208,4 +209,4 @@ pref('media.ffmpeg.vaapi.enabled', true); pref('media.ffmpeg.encoder.enabled', true); pref("media.hardware-video-decoding.enabled", true); -pref("gfx.canvas.accelerated", true); +pref("gfx.canvas.accelerated", true); \ No newline at end of file diff --git a/src/browser/base/content/ZenStartup.mjs b/src/browser/base/content/ZenStartup.mjs index 6add4a1f8..b2e9c3c79 100644 --- a/src/browser/base/content/ZenStartup.mjs +++ b/src/browser/base/content/ZenStartup.mjs @@ -1,6 +1,12 @@ + { const lazy = {}; - XPCOMUtils.defineLazyPreferenceGetter(lazy, 'sidebarHeightThrottle', 'zen.view.sidebar-height-throttle', 500); + XPCOMUtils.defineLazyPreferenceGetter( + lazy, + "sidebarHeightThrottle", + "zen.view.sidebar-height-throttle", + 500 + ); var ZenStartup = { init() { this.logHeader(); @@ -39,7 +45,7 @@ gZenUIManager.init(); gZenVerticalTabsManager.init(); gZenCompactModeManager.init(); - gZenKeyboardShortcutsManager.init(); + gZenKeyboardShortcuts.init(); function throttle(f, delay) { let timer = 0; @@ -49,9 +55,7 @@ }; } - new ResizeObserver(throttle(this._updateTabsToolbar.bind(this), lazy.sidebarHeightThrottle)).observe( - document.getElementById('tabbrowser-tabs') - ); + new ResizeObserver(throttle(this._updateTabsToolbar.bind(this), lazy.sidebarHeightThrottle)).observe(document.getElementById('tabbrowser-tabs')); } catch (e) { console.error('ZenThemeModifier: Error initializing browser layout', e); } @@ -146,4 +150,4 @@ }; ZenStartup.init(); -} +} \ No newline at end of file diff --git a/src/browser/base/content/zen-components b/src/browser/base/content/zen-components index b4b3c1f0d..98734ff38 160000 --- a/src/browser/base/content/zen-components +++ b/src/browser/base/content/zen-components @@ -1 +1 @@ -Subproject commit b4b3c1f0d40a88f70f9cc3ce3ef34b5f95d90d4b +Subproject commit 98734ff389b08655ed1c5b09aea41e2a2763c8e4 diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index db37b40a5..389e84f2c 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -1,6 +1,7 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. + var gZenMarketplaceManager = { init() { const checkForUpdates = document.getElementById('zenThemeMarketplaceCheckForUpdates'); @@ -630,148 +631,150 @@ var gZenWorkspacesSettings = { }, }; -const ZEN_CKS_CLASS_BASE = 'zenCKSOption'; -const ZEN_CKS_INPUT_FIELD_CLASS = `${ZEN_CKS_CLASS_BASE}-input`; -const ZEN_CKS_LABEL_CLASS = `${ZEN_CKS_CLASS_BASE}-label`; -const ZEN_CKS_WRAPPER_ID = `${ZEN_CKS_CLASS_BASE}-wrapper`; -const ZEN_CKS_GROUP_PREFIX = `${ZEN_CKS_CLASS_BASE}-group`; -const KEYBIND_ATTRIBUTE_KEY = 'key'; - var gZenCKSSettings = { - async init() { + init() { this._currentAction = null; this._initializeEvents(); - await this._initializeCKS(); + this._initializeCKS(); + this._addPrefObservers(); + window.addEventListener('unload', () => { + Services.prefs.removeObserver('zen.keyboard.shortcuts.disable-firefox', this); + }); + }, + + _addPrefObservers() { + Services.prefs.addObserver('zen.keyboard.shortcuts.disable-firefox', this); + }, + + observe(subject, topic, data) { + this.onDisableFirefoxShortcutsChange(); + }, + + async onDisableFirefoxShortcutsChange(event) { + let checked = Services.prefs.getBoolPref('zen.keyboard.shortcuts.disable-firefox'); + if (checked) return; + let buttonIndex = await confirmRestartPrompt(true, 1, true, false); + if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); + return; + } + }, + + _initializeCKS() { + let wrapepr = document.getElementById('zenCKSOptions-wrapper'); + + // Create the groups first. + for (let key in kZKSActions) { + const data = kZKSActions[key]; + const group = data[2]; + if (!wrapepr.querySelector(`[data-group="${group}"]`)) { + let groupElem = document.createElement('h2'); + groupElem.setAttribute('data-group', group); + document.l10n.setAttributes(groupElem, `zen-cks-group-${group}`); + wrapepr.appendChild(groupElem); + } + } + + const keys = Object.keys(kZKSActions); + for (let i = keys.length - 1; i >= 0; i--) { + const key = keys[i]; + const data = kZKSActions[key]; + const l10nId = data[1]; + const group = data[2]; + let fragment = window.MozXULElement.parseXULToFragment(` + + + + + `); + document.l10n.setAttributes(fragment.querySelector('.zenCKSOption-label'), l10nId); + + let input = fragment.querySelector('.zenCKSOption-input'); + let shortcut = gZenKeyboardShortcuts.getShortcut(key); + if (shortcut) { + input.value = gZenKeyboardShortcuts.shortCutToString(shortcut); + } else { + this._resetCKS(input, key); + } + + input.setAttribute('data-key', key); + input.addEventListener('focus', (event) => { + const key = event.target.getAttribute('data-key'); + this._currentAction = key; + event.target.classList.add('zenCKSOption-input-editing'); + }); + + input.addEventListener('blur', (event) => { + this._currentAction = null; + event.target.classList.remove('zenCKSOption-input-editing'); + }); + + const groupElem = wrapepr.querySelector(`[data-group="${group}"]`); + groupElem.after(fragment); + } + }, + + _resetCKS(input, key) { + input.value = 'Not set'; + input.classList.add('zenCKSOption-input-not-set'); + input.classList.remove('zenCKSOption-input-invalid'); + gZenKeyboardShortcuts.setShortcut(key, null); }, _initializeEvents() { window.addEventListener('keydown', this._handleKeyDown.bind(this)); }, - async _initializeCKS() { - let wrapper = document.getElementById(ZEN_CKS_WRAPPER_ID); - - let shortcuts = await gZenKeyboardShortcutsManager.getModifiableShortcuts(); - - if (!shortcuts) { - throw Error('No shortcuts defined!'); - } - - // Generate section per each group - for (let group of VALID_SHORTCUT_GROUPS) { - let groupClass = `${ZEN_CKS_GROUP_PREFIX}-${group}`; - if (!wrapper.querySelector(`[data-group="${groupClass}"]`)) { - let groupElem = document.createElement('h2'); - groupElem.setAttribute('data-group', groupClass); - document.l10n.setAttributes(groupElem, `groupClass`); - wrapper.appendChild(groupElem); - } - } - - for (let shortcut of shortcuts) { - const keyID = shortcut.getID(); - const action = shortcut.getAction(); - const l10nID = shortcut.getL10NID(); - const group = shortcut.getGroup(); - const keyInString = shortcut.toUserString(); - console.debug(keyInString); - - // const labelValue = l10nID == null ? keyID : l10nID; - const labelValue = keyID; - - let fragment = window.MozXULElement.parseXULToFragment(` - - - - - `); - - document.l10n.setAttributes(fragment.querySelector(`.${ZEN_CKS_LABEL_CLASS}`), labelValue); - - let input = fragment.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}`); - if (keyInString) { - input.value = keyInString; - } else { - this._resetShortcut(input); - } - - input.setAttribute(KEYBIND_ATTRIBUTE_KEY, action); - - input.addEventListener('focus', (event) => { - const value = event.target.getAttribute(KEYBIND_ATTRIBUTE_KEY); - this._currentAction = value; - event.target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - }); - - input.addEventListener('editDone', (event) => { - const target = event.target; - target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - this._editDone(target); - }); - - const groupElem = wrapper.querySelector(`[data-group="${ZEN_CKS_GROUP_PREFIX}-${group}"]`); - groupElem.after(fragment); - } - }, - - async _resetShortcut(input) { - input.value = 'Not set'; - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); - - if (this._currentAction) { - this._editDone(); - await gZenKeyboardShortcutsManager.setShortcut(this._currentAction, null, null); - } - }, - - _editDone(shortcut, modifiers) { - gZenKeyboardShortcutsManager.setShortcut(this._currentAction, shortcut, modifiers); - this._currentAction = null; - }, - - //TODO Check for duplicates - async _handleKeyDown(event) { - event.preventDefault(); - + _handleKeyDown(event) { if (!this._currentAction) { return; } - let input = document.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}[${KEYBIND_ATTRIBUTE_KEY}="${this._currentAction}"]`); - const modifiers = new KeyShortcutModifiers(event.ctrlKey, event.altKey, event.shiftKey, event.metaKey); - const modifiersActive = modifiers.areAnyActive(); + let input = document.querySelector(`.zenCKSOption-input[data-key="${this._currentAction}"]`); + let shortcut = { + ctrl: event.ctrlKey, + alt: event.altKey, + shift: event.shiftKey, + meta: event.metaKey, + }; - let shortcut = event.key; + const shortcutWithoutModifiers = !shortcut.ctrl && !shortcut.alt && !shortcut.shift && !shortcut.meta; - shortcut = shortcut.replace(/Ctrl|Control|Shift|Alt|Option|Cmd|Meta/, ''); // Remove all modifiers - - if (shortcut == 'Tab' && !modifiersActive) { - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - this._latestValidKey = null; + if (event.key === 'Tab' && shortcutWithoutModifiers) { return; - } else if (shortcut == 'Escape' && !modifiersActive) { - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - - if (!this._latestValidKey) { - if (!input.classList.contains(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`)) { - input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - } - } else { - this._editDone(input, this._latestValidKey, modifiers); - this._latestValidKey = null; - } + } else if (event.key === 'Escape' && shortcutWithoutModifiers) { + this._currentAction = null; + input.blur(); return; - } else if (shortcut == 'Backspace' && !modifiersActive) { - this._resetShortcut(input); - this._latestValidKey = null; + } else if (event.key === 'Backspace' && shortcutWithoutModifiers) { + this._resetCKS(input, this._currentAction); return; } - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - input.value = modifiers.toUserString() + shortcut; - this._latestValidKey = shortcut; + if (!shortcut.ctrl && !shortcut.alt && !shortcut.shift && !shortcut.meta) { + this._resetCKS(input, this._currentAction); + return; // No modifiers, ignore. + } + + if (!['Control', 'Alt', 'Meta', 'Shift'].includes(event.key)) { + if (event.keycode) { + shortcut.keycode = event.keycode; + } else { + shortcut.key = event.key; + } + } + + event.preventDefault(); + gZenKeyboardShortcuts.setShortcut(this._currentAction, shortcut); + + input.value = gZenKeyboardShortcuts.shortCutToString(shortcut); + input.classList.remove('zenCKSOption-input-not-set'); + + if (gZenKeyboardShortcuts.isValidShortcut(shortcut)) { + input.classList.remove('zenCKSOption-input-invalid'); + } else { + input.classList.add('zenCKSOption-input-invalid'); + } }, }; @@ -826,6 +829,11 @@ Preferences.addAll([ type: 'bool', default: true, }, + { + id: 'zen.keyboard.shortcuts.disable-firefox', + type: 'bool', + default: false, + }, { id: 'zen.workspaces.hide-default-container-indicator', type: 'bool', @@ -841,4 +849,4 @@ Preferences.addAll([ type: 'bool', default: true, }, -]); +]); \ No newline at end of file diff --git a/src/browser/components/preferences/zenKeyboardShortcuts.inc.xhtml b/src/browser/components/preferences/zenKeyboardShortcuts.inc.xhtml index 19e9bfbf5..aff2f6a39 100644 --- a/src/browser/components/preferences/zenKeyboardShortcuts.inc.xhtml +++ b/src/browser/components/preferences/zenKeyboardShortcuts.inc.xhtml @@ -10,7 +10,12 @@ - + \ No newline at end of file