diff --git a/docs/changes.md b/docs/changes.md index c2f7e9a83..39d27ab15 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -12,3 +12,4 @@ - Overall UX - Themes Page - Settings Page +- Keyboard shortcuts, check if there are any missing or not working diff --git a/src/browser/base/zen-components/ZenKeyboardShortcuts.mjs b/src/browser/base/zen-components/ZenKeyboardShortcuts.mjs index ed7997026..947cbcd96 100644 --- a/src/browser/base/zen-components/ZenKeyboardShortcuts.mjs +++ b/src/browser/base/zen-components/ZenKeyboardShortcuts.mjs @@ -103,6 +103,7 @@ const defaultKeyboardGroups = { 'zen-bidi-switch-direction-shortcut', 'zen-screenshot-shortcut', ], + devTools: [/*Filled automatically*/], }; const fixedL10nIds = { @@ -113,6 +114,7 @@ const fixedL10nIds = { }; const ZEN_MAIN_KEYSET_ID = 'mainKeyset'; +const ZEN_DEVTOOLS_KEYSET_ID = 'devtoolsKeyset'; const ZEN_KEYSET_ID = 'zenKeyset'; const ZEN_COMPACT_MODE_SHORTCUTS_GROUP = 'zen-compact-mode'; @@ -224,14 +226,14 @@ class KeyShortcutModifiers { if (this.#control) { str += 'control,'; } - if (this.#alt) { - str += 'alt,'; + if (this.#accel) { + str += 'accel,'; } if (this.#shift) { str += 'shift,'; } - if (this.#accel) { - str += 'accel,'; + if (this.#alt) { + str += 'alt,'; } if (this.#meta) { str += 'meta,'; @@ -355,12 +357,12 @@ class KeyShortcut { ); } - static parseFromXHTML(key) { + static parseFromXHTML(key, { group = undefined } = {}) { return new KeyShortcut( key.getAttribute('id'), key.getAttribute('key'), key.getAttribute('keycode'), - KeyShortcut.getGroupFromL10nId(KeyShortcut.sanitizeL10nId(key.getAttribute('data-l10n-id')), key.getAttribute('id')), + group ?? KeyShortcut.getGroupFromL10nId(KeyShortcut.sanitizeL10nId(key.getAttribute('data-l10n-id')), key.getAttribute('id')), KeyShortcutModifiers.parseFromXHTMLAttribute(key.getAttribute('modifiers')), key.getAttribute('command'), key.getAttribute('data-l10n-id'), @@ -383,13 +385,19 @@ class KeyShortcut { toXHTMLElement(window) { let key = window.document.createXULElement('key'); + return this.replaceWithChild(key); + } + + replaceWithChild(key) { key.id = this.#id; if (this.#keycode) { key.setAttribute('keycode', this.#keycode); + key.removeAttribute('key'); } else { // note to "mr. macos": Better use setAttribute, because without it, there's a // risk of malforming the XUL element. key.setAttribute('key', this.#key); + key.removeAttribute('keycode'); } key.setAttribute('group', this.#group); @@ -578,159 +586,179 @@ class ZenKeyboardShortcutsLoader { async remove() { await IOUtils.remove(this.shortcutsFile); } -} -function zenGetDefaultShortcuts() { - // DO NOT CHANGE ANYTHING HERE - // For adding new default shortcuts, add them to inside the migration function - // and increment the version number. + static zenGetDefaultShortcuts() { + // DO NOT CHANGE ANYTHING HERE + // For adding new default shortcuts, add them to inside the migration function + // and increment the version number. - let keySet = document.getElementById(ZEN_MAIN_KEYSET_ID); - let newShortcutList = []; + let keySet = document.getElementById(ZEN_MAIN_KEYSET_ID); + let newShortcutList = []; - // Firefox's standard keyset. Reverse order to keep the order of the keys - for (let i = keySet.children.length - 1; i >= 0; i--) { - let key = keySet.children[i]; - let parsed = KeyShortcut.parseFromXHTML(key); - newShortcutList.push(parsed); - } + // Firefox's standard keyset. Reverse order to keep the order of the keys + for (let i = keySet.children.length - 1; i >= 0; i--) { + let key = keySet.children[i]; + let parsed = KeyShortcut.parseFromXHTML(key); + newShortcutList.push(parsed); + } - // Compact mode's keyset - newShortcutList.push( - new KeyShortcut( - 'zen-compact-mode-toggle', - 'C', - '', - ZEN_COMPACT_MODE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - 'code:gZenCompactModeManager.toggle()', - 'zen-compact-mode-shortcut-toggle' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-compact-mode-show-sidebar', - 'S', - '', - ZEN_COMPACT_MODE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - 'code:gZenCompactModeManager.toggleSidebar()', - 'zen-compact-mode-shortcut-show-sidebar' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-compact-mode-show-toolbar', - 'T', - '', - ZEN_COMPACT_MODE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - 'code:gZenCompactModeManager.toggleToolbar()', - 'zen-compact-mode-shortcut-show-toolbar' - ) - ); - - // Workspace's keyset - for (let i = 10; i > 0; i--) { + // Compact mode's keyset newShortcutList.push( new KeyShortcut( - `zen-workspace-switch-${i}`, + 'zen-compact-mode-toggle', + 'C', '', - '', - ZEN_WORKSPACE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({}), - `code:ZenWorkspaces.shortcutSwitchTo(${i - 1})`, - `zen-workspace-shortcut-switch-${i}` + ZEN_COMPACT_MODE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'code:gZenCompactModeManager.toggle()', + 'zen-compact-mode-shortcut-toggle' ) ); + newShortcutList.push( + new KeyShortcut( + 'zen-compact-mode-show-sidebar', + 'S', + '', + ZEN_COMPACT_MODE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'code:gZenCompactModeManager.toggleSidebar()', + 'zen-compact-mode-shortcut-show-sidebar' + ) + ); + newShortcutList.push( + new KeyShortcut( + 'zen-compact-mode-show-toolbar', + 'T', + '', + ZEN_COMPACT_MODE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'code:gZenCompactModeManager.toggleToolbar()', + 'zen-compact-mode-shortcut-show-toolbar' + ) + ); + + // Workspace's keyset + for (let i = 10; i > 0; i--) { + newShortcutList.push( + new KeyShortcut( + `zen-workspace-switch-${i}`, + '', + '', + ZEN_WORKSPACE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({}), + `code:ZenWorkspaces.shortcutSwitchTo(${i - 1})`, + `zen-workspace-shortcut-switch-${i}` + ) + ); + } + newShortcutList.push( + new KeyShortcut( + 'zen-workspace-forward', + 'E', + '', + ZEN_WORKSPACE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'code:ZenWorkspaces.changeWorkspaceShortcut()', + 'zen-workspace-shortcut-forward' + ) + ); + newShortcutList.push( + new KeyShortcut( + 'zen-workspace-backward', + 'Q', + '', + ZEN_WORKSPACE_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + 'code:ZenWorkspaces.changeWorkspaceShortcut(-1)', + 'zen-workspace-shortcut-backward' + ) + ); + + // Other keyset + newShortcutList.push( + new KeyShortcut( + 'zen-toggle-web-panel', + 'P', + '', + ZEN_OTHER_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ alt: true }), + 'code:gZenBrowserManagerSidebar.toggle()', + 'zen-web-panel-shortcut-toggle' + ) + ); + + // Split view + newShortcutList.push( + new KeyShortcut( + 'zen-split-view-grid', + 'G', + '', + ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + "code:gZenViewSplitter.toggleShortcut('grid')", + 'zen-split-view-shortcut-grid' + ) + ); + newShortcutList.push( + new KeyShortcut( + 'zen-split-view-vertical', + 'V', + '', + ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + "code:gZenViewSplitter.toggleShortcut('vsep')", + 'zen-split-view-shortcut-vertical' + ) + ); + newShortcutList.push( + new KeyShortcut( + 'zen-split-view-horizontal', + 'H', + '', + ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + "code:gZenViewSplitter.toggleShortcut('hsep')", + 'zen-split-view-shortcut-horizontal' + ) + ); + newShortcutList.push( + new KeyShortcut( + 'zen-split-view-unsplit', + 'U', + '', + ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, + KeyShortcutModifiers.fromObject({ accel: true, alt: true }), + "code:gZenViewSplitter.toggleShortcut('unsplit')", + 'zen-split-view-shortcut-unsplit' + ) + ); + + return newShortcutList; } - newShortcutList.push( - new KeyShortcut( - 'zen-workspace-forward', - 'E', - '', - ZEN_WORKSPACE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - 'code:ZenWorkspaces.changeWorkspaceShortcut()', - 'zen-workspace-shortcut-forward' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-workspace-backward', - 'Q', - '', - ZEN_WORKSPACE_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - 'code:ZenWorkspaces.changeWorkspaceShortcut(-1)', - 'zen-workspace-shortcut-backward' - ) - ); - // Other keyset - newShortcutList.push( - new KeyShortcut( - 'zen-toggle-web-panel', - 'P', - '', - ZEN_OTHER_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ alt: true }), - 'code:gZenBrowserManagerSidebar.toggle()', - 'zen-web-panel-shortcut-toggle' - ) - ); + // Make sure to stay in sync with https://searchfox.org/mozilla-central/source/devtools/startup/DevToolsStartup.sys.mjs#879 + static IGNORED_DEVTOOLS_SHORTCUTS = ['key_toggleToolboxF12', 'profilerStartStop', + 'profilerStartStopAlternate', 'profilerCapture', 'profilerCaptureAlternate', + 'javascriptTracingToggle']; - // Split view - newShortcutList.push( - new KeyShortcut( - 'zen-split-view-grid', - 'G', - '', - ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - "code:gZenViewSplitter.toggleShortcut('grid')", - 'zen-split-view-shortcut-grid' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-split-view-vertical', - 'V', - '', - ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - "code:gZenViewSplitter.toggleShortcut('vsep')", - 'zen-split-view-shortcut-vertical' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-split-view-horizontal', - 'H', - '', - ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - "code:gZenViewSplitter.toggleShortcut('hsep')", - 'zen-split-view-shortcut-horizontal' - ) - ); - newShortcutList.push( - new KeyShortcut( - 'zen-split-view-unsplit', - 'U', - '', - ZEN_SPLIT_VIEW_SHORTCUTS_GROUP, - KeyShortcutModifiers.fromObject({ accel: true, alt: true }), - "code:gZenViewSplitter.toggleShortcut('unsplit')", - 'zen-split-view-shortcut-unsplit' - ) - ); + static zenGetDefaultDevToolsShortcuts() { + let keySet = document.getElementById(ZEN_DEVTOOLS_KEYSET_ID); + let newShortcutList = []; + for (let i = keySet.children.length - 1; i >= 0; i--) { + let key = keySet.children[i]; + if (this.IGNORED_DEVTOOLS_SHORTCUTS.includes(key.id)) { + continue; + } + let parsed = KeyShortcut.parseFromXHTML(key, { group: 'devTools' }); + newShortcutList.push(parsed); + } - return newShortcutList; + return newShortcutList; + } } class ZenKeyboardShortcutsVersioner { - static LATEST_KBS_VERSION = 6; + static LATEST_KBS_VERSION = 7; constructor() {} @@ -789,7 +817,7 @@ class ZenKeyboardShortcutsVersioner { // Migrate from 0 to 1 // Here, we do a complet reset of the shortcuts, // since nothing seems to work properly. - data = zenGetDefaultShortcuts(); + data = ZenKeyboardShortcutsLoader.zenGetDefaultShortcuts(); } if (version < 2) { // Migrate from 1 to 2 @@ -819,7 +847,7 @@ class ZenKeyboardShortcutsVersioner { // detection for internal keys was not working properly, so every internal // shortcut was being saved as a user-editable shortcut. // This migration will fix this issue. - const defaultShortcuts = zenGetDefaultShortcuts(); + const defaultShortcuts = ZenKeyboardShortcutsLoader.zenGetDefaultShortcuts(); // Get the default shortcut, compare the id and set the internal flag if needed for (let shortcut of data) { for (let defaultShortcut of defaultShortcuts) { @@ -865,12 +893,31 @@ class ZenKeyboardShortcutsVersioner { ) ); } + if (version < 7) { + // Migrate from 6 to 7 + // In this new version, we add the devtools shortcuts + const listener = (event) => { + event.stopPropagation(); + + const devToolsShortcuts = ZenKeyboardShortcutsLoader.zenGetDefaultDevToolsShortcuts(); + gZenKeyboardShortcutsManager.updatedDefaultDevtoolsShortcuts(devToolsShortcuts); + + window.removeEventListener('zen-devtools-keyset-added', listener); + }; + + // We need to load after an event because the devtools keyset is not in the DOM yet + // and we need to wait for it to be added. + gZenKeyboardShortcutsManager._hasToLoadDefaultDevtools = true; + window.addEventListener('zen-devtools-keyset-added', listener); + } return data; } } var gZenKeyboardShortcutsManager = { loader: new ZenKeyboardShortcutsLoader(), + _hasToLoadDevtools: false, + beforeInit() { if (!this.inBrowserView) { return; @@ -881,6 +928,7 @@ var gZenKeyboardShortcutsManager = { void(this.getZenKeyset()); this._hasCleared = Services.prefs.getBoolPref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); + window.addEventListener('zen-devtools-keyset-added', this._hasAddedDevtoolShortcuts.bind(this)); this.init(); }, @@ -948,6 +996,25 @@ var gZenKeyboardShortcutsManager = { return browser.gZenKeyboardShortcutsManager._zenKeyset; }, + getZenDevtoolsKeyset() { + // note: we use `this` here because we are in the context of the browser + if (!this._zenDevtoolsKeyset) { + const id = `zen-${ZEN_DEVTOOLS_KEYSET_ID}`; + const existingKeyset = document.getElementById(id); + if (existingKeyset) { + this._zenDevtoolsKeyset = existingKeyset; + return existingKeyset; + } + + this._zenDevtoolsKeyset = document.createXULElement('keyset'); + this._zenDevtoolsKeyset.id = id; + + const mainKeyset = document.getElementById(ZEN_DEVTOOLS_KEYSET_ID); + mainKeyset.before(this._zenDevtoolsKeyset); + } + return this._zenDevtoolsKeyset; + }, + clearMainKeyset(element) { if (this._hasCleared) { return; @@ -968,6 +1035,21 @@ var gZenKeyboardShortcutsManager = { parent.prepend(element); }, + async updatedDefaultDevtoolsShortcuts(shortcuts) { + this._hasToLoadDefaultDevtools = false; + this._currentShortcutList = this._currentShortcutList.concat(shortcuts); + await this._saveShortcuts(); + this._hasAddedDevtoolShortcuts(); + }, + + _hasAddedDevtoolShortcuts() { + if (this._hasToLoadDevtools || this._hasToLoadDefaultDevtools) { + return; + } + this._hasToLoadDevtools = true; + this.triggerShortcutRebuild(); + }, + _applyShortcuts() { for (const browser of ZenMultiWindowFeature.browsers) { let mainKeyset = browser.document.getElementById(ZEN_MAIN_KEYSET_ID); @@ -992,10 +1074,39 @@ var gZenKeyboardShortcutsManager = { keyset.appendChild(child); } + this._applyDevtoolsShortcuts(browser); mainKeyset.after(keyset); } }, + _applyDevtoolsShortcuts(browser) { + if (!browser.gZenKeyboardShortcutsManager?._hasToLoadDevtools) { + return; + } + let devtoolsKeyset = browser.gZenKeyboardShortcutsManager.getZenDevtoolsKeyset(browser); + for (let key of this._currentShortcutList) { + if (key.getGroup() != 'devTools') { + continue; + } + if (ZenKeyboardShortcutsLoader.IGNORED_DEVTOOLS_SHORTCUTS.includes(key.getID())) { + continue; + } + const originalKey = browser.document.getElementById(key.getID()); + // We do not want to remove and create a new key in these cases, + // because it will lose the event listeners. + key.replaceWithChild(originalKey); + // Move the key to the main keyset if it's not there, this is because + // changing modifiers will not work if they are under the devtools keyset + // for some really weird reason. + if (originalKey.parentElement.id === ZEN_DEVTOOLS_KEYSET_ID) { + devtoolsKeyset.prepend(originalKey); + } + } + + const originalDevKeyset = browser.document.getElementById(ZEN_DEVTOOLS_KEYSET_ID); + originalDevKeyset.after(devtoolsKeyset); + }, + async resetAllShortcuts() { await this.loader.remove(); Services.prefs.clearUserPref('zen.keyboard.shortcuts.version'); diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index f96b360ce..b4d3f4ce8 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -733,6 +733,21 @@ var zenMissingKeyboardShortcutL10n = { goHome: 'zen-key-go-home', key_redo: 'zen-key-redo', + + // Devtools + key_toggleToolbox: 'zen-devtools-toggle-shortcut', + key_browserToolbox: 'zen-devtools-toggle-browser-toolbox-shortcut', + key_browserConsole: 'zen-devtools-toggle-browser-console-shortcut', + key_responsiveDesignMode: 'zen-devtools-toggle-responsive-design-mode-shortcut', + key_inspector: 'zen-devtools-toggle-inspector-shortcut', + key_webconsole: 'zen-devtools-toggle-web-console-shortcut', + key_jsdebugger: 'zen-devtools-toggle-js-debugger-shortcut', + key_netmonitor: 'zen-devtools-toggle-net-monitor-shortcut', + key_styleeditor: 'zen-devtools-toggle-style-editor-shortcut', + key_performance: 'zen-devtools-toggle-performance-shortcut', + key_storage: 'zen-devtools-toggle-storage-shortcut', + key_dom: 'zen-devtools-toggle-dom-shortcut', + key_accessibility: 'zen-devtools-toggle-accessibility-shortcut', }; var gZenCKSSettings = { diff --git a/src/devtools/startup/DevToolsStartup-sys-mjs.patch b/src/devtools/startup/DevToolsStartup-sys-mjs.patch new file mode 100644 index 000000000..9607d3aac --- /dev/null +++ b/src/devtools/startup/DevToolsStartup-sys-mjs.patch @@ -0,0 +1,13 @@ +diff --git a/devtools/startup/DevToolsStartup.sys.mjs b/devtools/startup/DevToolsStartup.sys.mjs +index 0c9db6cb85c491a9f0fc216071afc66e553dcd51..10faeb699a35bb53bd0bd4bce36f18626a8f3288 100644 +--- a/devtools/startup/DevToolsStartup.sys.mjs ++++ b/devtools/startup/DevToolsStartup.sys.mjs +@@ -806,6 +806,8 @@ DevToolsStartup.prototype = { + // account (see bug 832984). + const mainKeyset = doc.getElementById("mainKeyset"); + mainKeyset.parentNode.insertBefore(keyset, mainKeyset); ++ ++ window.dispatchEvent(new window.Event("zen-devtools-keyset-added")); + }, + + /**