feat: implement automatic tab grouping

This commit is contained in:
Alex Kontos
2025-07-01 15:14:11 +01:00
parent 40a1cbe696
commit 5f4596402e
9 changed files with 1203 additions and 0 deletions

View File

@@ -1382,6 +1382,9 @@
},
});
newTab.dispatchEvent(event);
// Notify observers for native tab grouping feature
Services.obs.notifyObservers(newTab, "browser-tab-activated");
this._tabAttrModified(oldTab, ["selected"]);
this._tabAttrModified(newTab, ["selected"]);
@@ -4037,6 +4040,9 @@
detail: eventDetail || {},
});
tab.dispatchEvent(evt);
// Notify observers for native tab grouping feature
Services.obs.notifyObservers(tab, "browser-tab-created");
}
/**
@@ -5013,6 +5019,8 @@
}
_endRemoveTab(aTab) {
// Notify observers for native tab grouping feature
Services.obs.notifyObservers(aTab, "browser-tab-removed");
if (!aTab || !aTab._endRemoveArgs) {
return;
}
@@ -7220,6 +7228,10 @@
// Intentional fallthrough
case "deactivate":
this.selectedTab.updateLastSeenActive();
// Notify observers for native tab grouping feature
if (aEvent.type === "activate") {
Services.obs.notifyObservers(null, "browser-window-focus-changed");
}
break;
}
}

View File

@@ -271,6 +271,7 @@
@RESPATH@/browser/defaults/settings
; Waterfox preference files
@RESPATH@/browser/@PREF_DIR@/prefs-lepton.js
@RESPATH@/browser/@PREF_DIR@/prefs-tabgroups.js
# channel-prefs.js has been removed on macOS.
#ifndef XP_MACOSX

View File

@@ -15,6 +15,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
PrivateTab: "resource:///modules/PrivateTab.sys.mjs",
StatusBar: "resource:///modules/StatusBar.sys.mjs",
TabFeatures: "resource:///modules/TabFeatures.sys.mjs",
TabGrouping: "resource:///modules/TabGrouping.sys.mjs",
setTimeout: "resource://gre/modules/Timer.sys.mjs",
UICustomizations: "resource:///modules/UICustomizations.sys.mjs",
});
@@ -75,6 +76,9 @@ export const WaterfoxGlue = {
this.addAddonListener();
// Register about:cfg
lazy.AboutPages.init();
// Initialize automatic tab grouping
lazy.TabGrouping.init();
},
async _setPrefObservers() {
@@ -215,6 +219,9 @@ export const WaterfoxGlue = {
this._beforeUIStartup();
this._delayedTasks();
break;
case "quit-application-granted":
this.shutdown();
break;
}
},
@@ -406,6 +413,11 @@ export const WaterfoxGlue = {
}
},
shutdown() {
// Shutdown TabGrouping
lazy.TabGrouping.shutdown();
},
updateCustomStylesheets(addon) {
if (addon.type === "theme") {
// If any theme and WF on any theme, reload stylesheets for every theme enable.

View File

@@ -14,6 +14,7 @@ DIRS += [
"search",
"statusbar",
"tabfeatures",
"tabgrouping",
"uicustomizations",
"utils",
]

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 David Demri
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,58 @@
# Automatic Tab Grouping Feature
This feature is inspired by the Firefox WebExtension "New Tab Same Group" by onlybets.
(Source: https://github.com/onlybets/firefox-addon-new-tab-same-group/blob/main/README.md)
This module implements automatic tab grouping functionality, which automatically adds new tabs to the same group as the currently active tab.
## Features
- **Automatic Grouping**: When enabled, new tabs are automatically added to the same group as the source tab (the tab that was active when the new tab was created).
- **Configurable Placement**: Users can choose where new tabs appear within the group:
- After the source tab (default)
- At the beginning of the group
- At the end of the group
- **Optional Delay**: Users can enable a 1-second delay before grouping occurs, allowing them to cancel the operation if desired.
- **Keyboard Shortcut**: When delay is enabled, users can press a keyboard shortcut (default: Ctrl+` on Windows/Linux, Alt+` on macOS) to cancel pending grouping operations.
- **Bypass Shortcut**: Press Alt+Shift+T to open a new tab in the standard way (no grouping). This can be configured via preferences.
- **Smart Tab Tracking**: The feature maintains a history of active tabs to handle edge cases where the source tab might not be immediately available.
## Implementation
The feature consists of:
1. **TabGrouping.sys.mjs**: Core module that handles all the grouping logic
2. **Preferences**: User-configurable settings with defaults
3. **UI Overlays**: Integration with the preferences UI
4. **Localization**: User-facing strings in tabgrouping.ftl
## Preferences
- `browser.tabs.autoGroupNewTabs`: Enable/disable the feature (default: true)
- `browser.tabs.autoGroupNewTabs.placement`: Tab placement mode (default: "after")
- `browser.tabs.autoGroupNewTabs.delayEnabled`: Enable grouping delay (default: false)
- `browser.tabs.autoGroupNewTabs.delayMs`: Delay duration in milliseconds (default: 1000)
- `browser.tabs.autoGroupNewTabs.cancelShortcut`: Keyboard shortcut to cancel (platform-specific default)
- `browser.tabs.autoGroupNewTabs.bypassShortcut`: Keyboard shortcut to open a standard new tab without grouping (default: "Alt+Shift+T")
## Architecture
The module:
- Listens for tab creation events via observer notifications
- Tracks active tab history to determine the appropriate source tab
- Manages pending grouping operations with timers
- Handles keyboard shortcuts dynamically when delay is enabled
- Integrates with the existing tab group infrastructure in tabbrowser.js
## Usage
The feature is automatically initialized when the browser starts via WaterfoxGlue.sys.mjs.
This project contains code under two licenses:
- Original implementation: MIT License (see LICENSE)
- Rewritten portions: Mozilla Public License 2.0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXTRA_JS_MODULES += [
"TabGrouping.sys.mjs",
]
JS_PREFERENCE_PP_FILES += [
"prefs-tabgroups.js",
]

View File

@@ -0,0 +1,40 @@
/* 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/. */
// Default preferences for automatic tab grouping feature
// Enable automatic tab grouping
pref("browser.tabs.autoGroupNewTabs", false);
// Placement mode for new tabs in groups
// Options: "after" (after source tab), "first" (beginning of group), "last" (end of group)
pref("browser.tabs.autoGroupNewTabs.placement", "after");
// Enable delay before grouping (allows user to cancel)
pref("browser.tabs.autoGroupNewTabs.delayEnabled", false);
// Delay in milliseconds before grouping occurs
pref("browser.tabs.autoGroupNewTabs.delayMs", 1000);
// Keyboard shortcut to cancel pending grouping
// Default: Ctrl+` on Windows/Linux, Option+` on macOS
#ifdef XP_MACOSX
pref("browser.tabs.autoGroupNewTabs.cancelShortcut", "Option+`");
#else
pref("browser.tabs.autoGroupNewTabs.cancelShortcut", "Ctrl+`");
#endif
// Keyboard shortcut to open a standard new tab (bypass grouping)
// Default: Alt+Shift+T (Windows/Linux), Option+Shift+T (macOS)
#ifdef XP_MACOSX
pref("browser.tabs.autoGroupNewTabs.bypassShortcut", "Option+Shift+T");
#else
pref("browser.tabs.autoGroupNewTabs.bypassShortcut", "Alt+Shift+T");
#endif
// Enable verbose debug logging for TabGrouping
pref("browser.tabs.autoGroupNewTabs.debugLog", false);
// Grace period after session restore before resuming auto-grouping (ms)
pref("browser.tabs.autoGroupNewTabs.resumeGraceMs", 1000);