From 249d793b5deab944e85728fe4273b189f3216cf4 Mon Sep 17 00:00:00 2001 From: Jun Jie <71215065+junnjiee@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:53:39 +0800 Subject: [PATCH] feat: Ctrl+Tab cycling to keep within essentials/regular tabs only, p=#11242 * feat: ctrl+tab cycles within essential/workspace tabs only * add test for ctrl+tab cycling by attribute * move settings UI related code to /src/zen, revert patches for main.inc.xhtml and main.js, use simple tab filter when current tab is hidden * chore: Cleanup and add extra pref, b=no-bug, c=tests, tabs --------- Co-authored-by: mr. m --- .../browser/preferences/zen-preferences.ftl | 8 +- prefs/zen/zen.yaml | 6 ++ .../components/preferences/zen-settings.js | 41 +++++++++ .../preferences/zenTabsManagement.inc.xhtml | 8 ++ src/toolkit/content/widgets/tabbox-js.patch | 64 ++++++++++++-- src/zen/tests/tabs/browser.toml | 3 +- .../tabs/browser_tabs_cycle_by_attribute.js | 86 +++++++++++++++++++ 7 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 src/zen/tests/tabs/browser_tabs_cycle_by_attribute.js diff --git a/locales/en-US/browser/browser/preferences/zen-preferences.ftl b/locales/en-US/browser/browser/preferences/zen-preferences.ftl index d053124e2..2941a5157 100644 --- a/locales/en-US/browser/browser/preferences/zen-preferences.ftl +++ b/locales/en-US/browser/browser/preferences/zen-preferences.ftl @@ -59,6 +59,12 @@ zen-tabs-unloader-enabled = zen-tabs-close-on-back-with-no-history = .label = Close tab and switch to its owner tab (or most recently used tab) when going back with no history +zen-tabs-cycle-by-attribute = + .label = Ctrl+Tab cycles within Essential or Workspace tabs only +zen-tabs-cycle-ignore-pending-tabs = + .label = Ignore Pending tabs when cycling with Ctrl+Tab +zen-tabs-cycle-by-attribute-warning = Ctrl+Tab will cycle by recently used order, as it is enabled + zen-look-and-feel-compact-toolbar-themed = .label = Use themed background for compact toolbar @@ -150,7 +156,7 @@ zen-theme-marketplace-input-default-placeholder = .placeholder = Type something... pane-zen-marketplace-title = Zen Mods zen-themes-auto-update = - .label = Automatically update installed mods on startup + .label = Automatically update installed mods on startup zen-settings-workspaces-force-container-tabs-to-workspace = .label = Switch to workspace where container is set as default when opening container tabs diff --git a/prefs/zen/zen.yaml b/prefs/zen/zen.yaml index c44a0e626..9c6e9d787 100644 --- a/prefs/zen/zen.yaml +++ b/prefs/zen/zen.yaml @@ -37,3 +37,9 @@ - name: zen.tabs.close-on-back-with-no-history value: true + +- name: zen.tabs.ctrl-tab.ignore-essential-tabs + value: false + +- name: zen.tabs.ctrl-tab.ignore-pending-tabs + value: false diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index a126c8a38..35fbccbf7 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -707,13 +707,39 @@ var gZenWorkspacesSettings = { } }, }; + + let toggleZenCycleByAttrWarning = { + observe() { + const warning = document.getElementById('zenTabsCycleByAttributeWarning'); + warning.hidden = !( + Services.prefs.getBoolPref('zen.tabs.ctrl-tab.ignore-essential-tabs', false) && + Services.prefs.getBoolPref('browser.ctrlTab.sortByRecentlyUsed', false) + ); + }, + }; + + toggleZenCycleByAttrWarning.observe(); // call it once on initial load + Services.prefs.addObserver('zen.glance.enabled', tabsUnloaderPrefListener); // We can use the same listener for both prefs Services.prefs.addObserver('zen.workspaces.separate-essentials', tabsUnloaderPrefListener); Services.prefs.addObserver('zen.glance.activation-method', tabsUnloaderPrefListener); + Services.prefs.addObserver( + 'zen.tabs.ctrl-tab.ignore-essential-tabs', + toggleZenCycleByAttrWarning + ); + Services.prefs.addObserver('browser.ctrlTab.sortByRecentlyUsed', toggleZenCycleByAttrWarning); window.addEventListener('unload', () => { Services.prefs.removeObserver('zen.glance.enabled', tabsUnloaderPrefListener); Services.prefs.removeObserver('zen.glance.activation-method', tabsUnloaderPrefListener); Services.prefs.removeObserver('zen.workspaces.separate-essentials', tabsUnloaderPrefListener); + Services.prefs.removeObserver( + 'zen.tabs.ctrl-tab.ignore-essential-tabs', + toggleZenCycleByAttrWarning + ); + Services.prefs.removeObserver( + 'browser.ctrlTab.sortByRecentlyUsed', + toggleZenCycleByAttrWarning + ); }); }, }; @@ -1135,6 +1161,21 @@ Preferences.addAll([ type: 'bool', default: true, }, + { + id: 'zen.tabs.ctrl-tab.ignore-essential-tabs', + type: 'bool', + default: false, + }, + { + id: 'zen.tabs.ctrl-tab.ignore-pending-tabs', + type: 'bool', + default: false, + }, + { + id: 'zen.tabs.close-on-back-with-no-history', + type: 'bool', + default: false, + }, ]); Preferences.addSetting({ diff --git a/src/browser/components/preferences/zenTabsManagement.inc.xhtml b/src/browser/components/preferences/zenTabsManagement.inc.xhtml index 2943b863b..6effbd1bd 100644 --- a/src/browser/components/preferences/zenTabsManagement.inc.xhtml +++ b/src/browser/components/preferences/zenTabsManagement.inc.xhtml @@ -29,6 +29,14 @@ + + +