feat: Improved tab transitions and fixed a couple of issues with glance, b=(no-bug), c=tabs, common, glance, split-view, workspaces

This commit is contained in:
Mr. M 2025-05-25 17:06:22 +02:00
parent dda1dab6f3
commit 09ca430b88
No known key found for this signature in database
GPG key ID: 6292C4C8F8652B18
14 changed files with 374 additions and 176 deletions

View file

@ -9,6 +9,7 @@
content/browser/ZenCustomizableUI.sys.mjs (../../zen/common/ZenCustomizableUI.sys.mjs) content/browser/ZenCustomizableUI.sys.mjs (../../zen/common/ZenCustomizableUI.sys.mjs)
content/browser/zen-components/ZenUIMigration.mjs (../../zen/common/ZenUIMigration.mjs) content/browser/zen-components/ZenUIMigration.mjs (../../zen/common/ZenUIMigration.mjs)
content/browser/zen-components/ZenCommonUtils.mjs (../../zen/common/ZenCommonUtils.mjs) content/browser/zen-components/ZenCommonUtils.mjs (../../zen/common/ZenCommonUtils.mjs)
content/browser/zen-components/ZenSessionStore.mjs (../../zen/common/ZenSessionStore.mjs)
content/browser/zen-styles/zen-theme.css (../../zen/common/styles/zen-theme.css) content/browser/zen-styles/zen-theme.css (../../zen/common/styles/zen-theme.css)
content/browser/zen-styles/zen-buttons.css (../../zen/common/styles/zen-buttons.css) content/browser/zen-styles/zen-buttons.css (../../zen/common/styles/zen-buttons.css)

View file

@ -9,3 +9,5 @@
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaces.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaces.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesSync.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesSync.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenActorsManager.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenActorsManager.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenSessionStore.mjs"></script>

View file

@ -1,5 +1,5 @@
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d81447514e2c 100644 index 8c6047e1ada5a22e57e1e665965237c9e22641d7..8d0585e738a5a758ebbddfa0787c71d634dadd4d 100644
--- a/browser/components/sessionstore/SessionStore.sys.mjs --- a/browser/components/sessionstore/SessionStore.sys.mjs
+++ b/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs
@@ -2088,7 +2088,6 @@ var SessionStoreInternal = { @@ -2088,7 +2088,6 @@ var SessionStoreInternal = {
@ -31,17 +31,19 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
return; return;
} }
@@ -3925,6 +3922,9 @@ var SessionStoreInternal = { @@ -3925,6 +3922,11 @@ var SessionStoreInternal = {
Math.min(tabState.index, tabState.entries.length) Math.min(tabState.index, tabState.entries.length)
); );
tabState.pinned = false; tabState.pinned = false;
+ tabState.zenEssential = false; + tabState.zenEssential = false;
+ tabState.zenPinnedId = null; + tabState.zenPinnedId = null;
+ tabState.zenIsGlance = false;
+ tabState.zenGlanceId = null;
+ tabState.zenHasStaticLabel = false; + tabState.zenHasStaticLabel = false;
if (inBackground === false) { if (inBackground === false) {
aWindow.gBrowser.selectedTab = newTab; aWindow.gBrowser.selectedTab = newTab;
@@ -5239,7 +5239,7 @@ var SessionStoreInternal = { @@ -5239,7 +5241,7 @@ var SessionStoreInternal = {
} }
let workspaceID = aWindow.getWorkspaceID(); let workspaceID = aWindow.getWorkspaceID();
@ -50,7 +52,7 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
winData.workspaceID = workspaceID; winData.workspaceID = workspaceID;
} }
}, },
@@ -5430,14 +5430,15 @@ var SessionStoreInternal = { @@ -5430,14 +5432,15 @@ var SessionStoreInternal = {
} }
let tabbrowser = aWindow.gBrowser; let tabbrowser = aWindow.gBrowser;
@ -68,7 +70,7 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
continue; continue;
} }
let tabData = lazy.TabState.collect(tab, TAB_CUSTOM_VALUES.get(tab)); let tabData = lazy.TabState.collect(tab, TAB_CUSTOM_VALUES.get(tab));
@@ -5456,8 +5457,8 @@ var SessionStoreInternal = { @@ -5456,8 +5459,8 @@ var SessionStoreInternal = {
// We don't store the Firefox View tab in Session Store, so if it was the last selected "tab" when // We don't store the Firefox View tab in Session Store, so if it was the last selected "tab" when
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
// since it's only inserted into the tab strip after it's selected). // since it's only inserted into the tab strip after it's selected).
@ -79,7 +81,7 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
winData.title = tabbrowser.tabs[0].label; winData.title = tabbrowser.tabs[0].label;
} }
winData.selected = selectedIndex; winData.selected = selectedIndex;
@@ -5569,8 +5570,8 @@ var SessionStoreInternal = { @@ -5569,8 +5572,8 @@ var SessionStoreInternal = {
// selectTab represents. // selectTab represents.
let selectTab = 0; let selectTab = 0;
if (overwriteTabs) { if (overwriteTabs) {
@ -90,7 +92,7 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
selectTab = Math.min(selectTab, winData.tabs.length); selectTab = Math.min(selectTab, winData.tabs.length);
} }
@@ -5613,6 +5614,7 @@ var SessionStoreInternal = { @@ -5613,6 +5616,7 @@ var SessionStoreInternal = {
winData.tabs, winData.tabs,
winData.groups ?? [] winData.groups ?? []
); );
@ -98,12 +100,13 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
this._log.debug( this._log.debug(
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs` `restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
); );
@@ -6162,8 +6164,23 @@ var SessionStoreInternal = { @@ -6162,6 +6166,22 @@ var SessionStoreInternal = {
// Most of tabData has been restored, now continue with restoring // Most of tabData has been restored, now continue with restoring
// attributes that may trigger external events. // attributes that may trigger external events.
+ if (tabData.zenEssential) { + if (tabData.zenEssential) {
+ tab.setAttribute("zen-essential", "true"); + tab.setAttribute("zen-essential", "true");
+ tabData.pinned = true; // Essential tabs are always pinned.
+ } + }
+ if (tabData.zenIsEmpty) { + if (tabData.zenIsEmpty) {
+ tab.setAttribute("zen-empty-tab", "true"); + tab.setAttribute("zen-empty-tab", "true");
@ -118,8 +121,5 @@ index 8c6047e1ada5a22e57e1e665965237c9e22641d7..ccd2779d66eda9d034ca51cc3200d814
+ tab.setAttribute("zenDefaultUserContextId", true); + tab.setAttribute("zenDefaultUserContextId", true);
+ } + }
- if (tabData.pinned) { if (tabData.pinned) {
+ if (tabData.pinned || tabData.zenEssential) {
tabbrowser.pinTab(tab); tabbrowser.pinTab(tab);
} else {
tabbrowser.unpinTab(tab);

View file

@ -1,8 +1,8 @@
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..254849e13f7566029dc780c45e376e0f0d427cb5 100644 index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..76f4cf5aef30cb580ef0295fe6928b5a6a362f4b 100644
--- a/browser/components/sessionstore/TabState.sys.mjs --- a/browser/components/sessionstore/TabState.sys.mjs
+++ b/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs
@@ -84,6 +84,16 @@ class _TabState { @@ -84,6 +84,18 @@ class _TabState {
tabData.groupId = tab.group.id; tabData.groupId = tab.group.id;
} }
@ -15,6 +15,8 @@ index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..254849e13f7566029dc780c45e376e0f
+ tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon");
+ tabData.zenIsEmpty = tab.hasAttribute("zen-empty-tab"); + tabData.zenIsEmpty = tab.hasAttribute("zen-empty-tab");
+ tabData.zenHasStaticLabel = tab.hasAttribute("zen-has-static-label"); + tabData.zenHasStaticLabel = tab.hasAttribute("zen-has-static-label");
+ tabData.zenGlanceId = tab.getAttribute("glance-id");
+ tabData.zenIsGlance = tab.hasAttribute("zen-glance-tab");
+ +
tabData.searchMode = tab.ownerGlobal.gURLBar.getSearchMode(browser, true); tabData.searchMode = tab.ownerGlobal.gURLBar.getSearchMode(browser, true);

View file

@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b032cf200f1 100644 index d5aa64842a35c6697263c63fd3a0571b64b01344..14f5bc046f2e54109bd3fd0402a8f8b598a513c2 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js --- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -413,11 +413,41 @@ @@ -413,11 +413,41 @@
@ -292,37 +292,17 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
let url = "about:blank"; let url = "about:blank";
if (tabData.entries?.length) { if (tabData.entries?.length) {
@@ -3598,7 +3675,29 @@ @@ -3598,7 +3675,8 @@
skipLoad: true, skipLoad: true,
preferredRemoteType, preferredRemoteType,
}); });
-
+ tab._originalUrl = url; + tab._originalUrl = url;
+ gZenSessionStore.restoreInitialTabData(tab, tabData);
+ if (tabData.zenWorkspace) {
+ tab.setAttribute("zen-workspace-id", tabData.zenWorkspace);
+ }
+ if (tabData.zenPinnedId) {
+ tab.setAttribute("zen-pin-id", tabData.zenPinnedId);
+ }
+ if (tabData.zenIsEmpty) {
+ tab.setAttribute("zen-empty-tab", "true");
+ }
+ if (tabData.zenHasStaticLabel) {
+ tab.setAttribute("zen-has-static-label", "true");
+ }
+ if (tabData.zenEssential) {
+ tab.setAttribute("zen-essential", "true");
+ }
+ if (tabData.zenDefaultUserContextId) {
+ tab.setAttribute("zenDefaultUserContextId", "true");
+ }
+ if (tabData.zenPinnedEntry) {
+ tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry);
+ }
if (select) { if (select) {
tabToSelect = tab; tabToSelect = tab;
} }
@@ -3622,7 +3721,8 @@ @@ -3622,7 +3700,8 @@
// needs calling: // needs calling:
shouldUpdateForPinnedTabs = true; shouldUpdateForPinnedTabs = true;
} }
@ -332,7 +312,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
let { groupId } = tabData; let { groupId } = tabData;
const tabGroup = tabGroupWorkingData.get(groupId); const tabGroup = tabGroupWorkingData.get(groupId);
// if a tab refers to a tab group we don't know, skip any group // if a tab refers to a tab group we don't know, skip any group
@@ -3636,7 +3736,10 @@ @@ -3636,7 +3715,10 @@
tabGroup.stateData.id, tabGroup.stateData.id,
tabGroup.stateData.color, tabGroup.stateData.color,
tabGroup.stateData.collapsed, tabGroup.stateData.collapsed,
@ -344,7 +324,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
); );
tabsFragment.appendChild(tabGroup.node); tabsFragment.appendChild(tabGroup.node);
} }
@@ -3684,8 +3787,16 @@ @@ -3684,8 +3766,16 @@
// to remove the old selected tab. // to remove the old selected tab.
if (tabToSelect) { if (tabToSelect) {
let leftoverTab = this.selectedTab; let leftoverTab = this.selectedTab;
@ -363,7 +343,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} }
if (tabs.length > 1 || !tabs[0].selected) { if (tabs.length > 1 || !tabs[0].selected) {
@@ -3881,7 +3992,7 @@ @@ -3881,7 +3971,7 @@
// Ensure we have an index if one was not provided. // Ensure we have an index if one was not provided.
if (typeof elementIndex != "number" && typeof tabIndex != "number") { if (typeof elementIndex != "number" && typeof tabIndex != "number") {
// Move the new tab after another tab if needed, to the end otherwise. // Move the new tab after another tab if needed, to the end otherwise.
@ -372,7 +352,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if ( if (
!bulkOrderedOpen && !bulkOrderedOpen &&
((openerTab && ((openerTab &&
@@ -3904,7 +4015,7 @@ @@ -3904,7 +3994,7 @@
) { ) {
elementIndex = Infinity; elementIndex = Infinity;
} else if (previousTab.visible) { } else if (previousTab.visible) {
@ -381,7 +361,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} else if (previousTab == FirefoxViewHandler.tab) { } else if (previousTab == FirefoxViewHandler.tab) {
elementIndex = 0; elementIndex = 0;
} }
@@ -3932,10 +4043,10 @@ @@ -3932,14 +4022,14 @@
} }
// Ensure index is within bounds. // Ensure index is within bounds.
if (tab.pinned) { if (tab.pinned) {
@ -395,7 +375,12 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
index = Math.min(index, allItems.length); index = Math.min(index, allItems.length);
} }
/** @type {MozTabbrowserTab|undefined} */ /** @type {MozTabbrowserTab|undefined} */
@@ -3947,7 +4058,7 @@ - let itemAfter = allItems.at(index);
+ let itemAfter = gZenGlanceManager.getTabOrGlanceParent(allItems.at(index));
// Prevent a flash of unstyled content by setting up the tab content
// and inherited attributes before appending it (see Bug 1592054):
@@ -3947,7 +4037,7 @@
this.tabContainer._invalidateCachedTabs(); this.tabContainer._invalidateCachedTabs();
@ -404,7 +389,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if (this.isTab(itemAfter) && itemAfter.group == tabGroup) { if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
// Place at the front of, or between tabs in, the same tab group // Place at the front of, or between tabs in, the same tab group
this.tabContainer.insertBefore(tab, itemAfter); this.tabContainer.insertBefore(tab, itemAfter);
@@ -4268,6 +4379,9 @@ @@ -4268,6 +4358,9 @@
return; return;
} }
@ -414,7 +399,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
this.removeTabs(selectedTabs, { telemetrySource }); this.removeTabs(selectedTabs, { telemetrySource });
} }
@@ -4520,6 +4634,7 @@ @@ -4520,6 +4613,7 @@
telemetrySource, telemetrySource,
} = {} } = {}
) { ) {
@ -422,7 +407,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs // When 'closeWindowWithLastTab' pref is enabled, closing all tabs
// can be considered equivalent to closing the window. // can be considered equivalent to closing the window.
if ( if (
@@ -4604,6 +4719,7 @@ @@ -4604,6 +4698,7 @@
if (lastToClose) { if (lastToClose) {
this.removeTab(lastToClose, aParams); this.removeTab(lastToClose, aParams);
} }
@ -430,7 +415,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@@ -4641,6 +4757,12 @@ @@ -4641,6 +4736,12 @@
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
} }
@ -443,7 +428,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
// Handle requests for synchronously removing an already // Handle requests for synchronously removing an already
// asynchronously closing tab. // asynchronously closing tab.
if (!animate && aTab.closing) { if (!animate && aTab.closing) {
@@ -4655,7 +4777,9 @@ @@ -4655,7 +4756,9 @@
// frame created for it (for example, by updating the visually selected // frame created for it (for example, by updating the visually selected
// state). // state).
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
@ -454,7 +439,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if ( if (
!this._beginRemoveTab(aTab, { !this._beginRemoveTab(aTab, {
closeWindowFastpath: true, closeWindowFastpath: true,
@@ -4821,7 +4945,7 @@ @@ -4821,7 +4924,7 @@
closeWindowWithLastTab != null closeWindowWithLastTab != null
? closeWindowWithLastTab ? closeWindowWithLastTab
: !window.toolbar.visible || : !window.toolbar.visible ||
@ -463,7 +448,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if (closeWindow) { if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here, // We've already called beforeunload on all the relevant tabs if we get here,
@@ -4845,6 +4969,7 @@ @@ -4845,6 +4948,7 @@
newTab = true; newTab = true;
} }
@ -471,7 +456,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
aTab._endRemoveArgs = [closeWindow, newTab]; aTab._endRemoveArgs = [closeWindow, newTab];
// swapBrowsersAndCloseOther will take care of closing the window without animation. // swapBrowsersAndCloseOther will take care of closing the window without animation.
@@ -4885,9 +5010,7 @@ @@ -4885,9 +4989,7 @@
aTab._mouseleave(); aTab._mouseleave();
if (newTab) { if (newTab) {
@ -482,7 +467,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} else { } else {
TabBarVisibility.update(); TabBarVisibility.update();
} }
@@ -5016,6 +5139,8 @@ @@ -5016,6 +5118,8 @@
this.tabs[i]._tPos = i; this.tabs[i]._tPos = i;
} }
@ -491,7 +476,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if (!this._windowIsClosing) { if (!this._windowIsClosing) {
if (wasPinned) { if (wasPinned) {
this.tabContainer._positionPinnedTabs(); this.tabContainer._positionPinnedTabs();
@@ -5230,6 +5355,7 @@ @@ -5230,6 +5334,7 @@
} }
let excludeTabs = new Set(aExcludeTabs); let excludeTabs = new Set(aExcludeTabs);
@ -499,7 +484,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
// If this tab has a successor, it should be selectable, since // If this tab has a successor, it should be selectable, since
// hiding or closing a tab removes that tab as a successor. // hiding or closing a tab removes that tab as a successor.
@@ -5242,13 +5368,13 @@ @@ -5242,13 +5347,13 @@
!excludeTabs.has(aTab.owner) && !excludeTabs.has(aTab.owner) &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
) { ) {
@ -515,7 +500,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
); );
let tab = this.tabContainer.findNextTab(aTab, { let tab = this.tabContainer.findNextTab(aTab, {
@@ -5264,7 +5390,7 @@ @@ -5264,7 +5369,7 @@
} }
if (tab) { if (tab) {
@ -524,7 +509,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} }
// If no qualifying visible tab was found, see if there is a tab in // If no qualifying visible tab was found, see if there is a tab in
@@ -5285,7 +5411,7 @@ @@ -5285,7 +5390,7 @@
}); });
} }
@ -533,7 +518,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} }
_blurTab(aTab) { _blurTab(aTab) {
@@ -5686,10 +5812,10 @@ @@ -5686,10 +5791,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
} }
@ -546,7 +531,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
aTab.selected || aTab.selected ||
aTab.closing || aTab.closing ||
// Tabs that are sharing the screen, microphone or camera cannot be hidden. // Tabs that are sharing the screen, microphone or camera cannot be hidden.
@@ -5986,7 +6112,7 @@ @@ -5986,7 +6091,7 @@
// Don't allow mixing pinned and unpinned tabs. // Don't allow mixing pinned and unpinned tabs.
if (this.isTab(element) && element.pinned) { if (this.isTab(element) && element.pinned) {
@ -555,7 +540,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
} else { } else {
tabIndex = Math.max(tabIndex, this.pinnedTabCount); tabIndex = Math.max(tabIndex, this.pinnedTabCount);
} }
@@ -6012,10 +6138,16 @@ @@ -6012,10 +6117,16 @@
this.#handleTabMove( this.#handleTabMove(
element, element,
() => { () => {
@ -574,7 +559,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if (neighbor && this.isTab(element) && tabIndex > element._tPos) { if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
neighbor.after(element); neighbor.after(element);
} else { } else {
@@ -6084,17 +6216,26 @@ @@ -6084,17 +6195,29 @@
targetElement = targetElement.group; targetElement = targetElement.group;
} }
} }
@ -583,8 +568,12 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
+ element = element.group; + element = element.group;
+ } + }
// Don't allow mixing pinned and unpinned tabs. // Don't allow mixing pinned and unpinned tabs.
if (element.pinned && !targetElement?.pinned) { - if (element.pinned && !targetElement?.pinned) {
- targetElement = this.tabs[this.pinnedTabCount - 1]; - targetElement = this.tabs[this.pinnedTabCount - 1];
+ if (element.hasAttribute('zen-essential') && !targetElement?.hasAttribute('zen-essential')) {
+ targetElement = this.tabs.filter(tab => !tab.hasAttribute('zen-glance-tab'))[this._numZenEssentials - 1];
+ moveBefore = false;
+ } else if (element.pinned && !targetElement?.pinned) {
+ targetElement = this.tabs.filter(tab => !tab.hasAttribute('zen-glance-tab'))[this.pinnedTabCount - 1]; + targetElement = this.tabs.filter(tab => !tab.hasAttribute('zen-glance-tab'))[this.pinnedTabCount - 1];
moveBefore = false; moveBefore = false;
} else if (!element.pinned && targetElement && targetElement.pinned) { } else if (!element.pinned && targetElement && targetElement.pinned) {
@ -604,7 +593,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
if (element.pinned && this.tabContainer.verticalMode) { if (element.pinned && this.tabContainer.verticalMode) {
return this.tabContainer.verticalPinnedTabsContainer; return this.tabContainer.verticalPinnedTabsContainer;
} }
@@ -6154,7 +6295,7 @@ @@ -6154,7 +6277,7 @@
if (!this.isTab(aTab)) { if (!this.isTab(aTab)) {
throw new Error("Can only move a tab into a tab group"); throw new Error("Can only move a tab into a tab group");
} }
@ -613,7 +602,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
return; return;
} }
if (aTab.group && aTab.group.id === aGroup.id) { if (aTab.group && aTab.group.id === aGroup.id) {
@@ -6248,6 +6389,10 @@ @@ -6248,6 +6371,10 @@
moveActionCallback(); moveActionCallback();
@ -624,7 +613,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
// Clear tabs cache after moving nodes because the order of tabs may have // Clear tabs cache after moving nodes because the order of tabs may have
// changed. // changed.
this.tabContainer._invalidateCachedTabs(); this.tabContainer._invalidateCachedTabs();
@@ -7145,7 +7290,7 @@ @@ -7145,7 +7272,7 @@
// preventDefault(). It will still raise the window if appropriate. // preventDefault(). It will still raise the window if appropriate.
break; break;
} }
@ -633,7 +622,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
window.focus(); window.focus();
aEvent.preventDefault(); aEvent.preventDefault();
break; break;
@@ -8044,6 +8189,7 @@ @@ -8044,6 +8171,7 @@
aWebProgress.isTopLevel aWebProgress.isTopLevel
) { ) {
this.mTab.setAttribute("busy", "true"); this.mTab.setAttribute("busy", "true");
@ -641,7 +630,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
gBrowser._tabAttrModified(this.mTab, ["busy"]); gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected; this.mTab._notselectedsinceload = !this.mTab.selected;
} }
@@ -9009,7 +9155,7 @@ var TabContextMenu = { @@ -9009,7 +9137,7 @@ var TabContextMenu = {
); );
contextUnpinSelectedTabs.hidden = contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected; !this.contextTab.pinned || !this.multiselected;
@ -650,7 +639,7 @@ index d5aa64842a35c6697263c63fd3a0571b64b01344..6943dc7f1d3d95ab1da315cbdbda0b03
// Move Tab items // Move Tab items
let contextMoveTabOptions = document.getElementById( let contextMoveTabOptions = document.getElementById(
"context_moveTabOptions" "context_moveTabOptions"
@@ -9278,6 +9424,7 @@ var TabContextMenu = { @@ -9278,6 +9406,7 @@ var TabContextMenu = {
telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP, telemetrySource: gBrowser.TabMetrics.METRIC_SOURCE.TAB_STRIP,
}); });
} else { } else {

View file

@ -0,0 +1,13 @@
diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
index 6dc774ea335b0c5dba7dcf76cdb23728faae1343..b0b9ef236c2e8517db4bcf3270596456bbefe11d 100644
--- a/browser/components/tabbrowser/content/tabgroup.js
+++ b/browser/components/tabbrowser/content/tabgroup.js
@@ -301,7 +301,7 @@
*/
addTabs(tabs, metricsContext) {
for (let tab of tabs) {
- if (tab.pinned) {
+ if (tab.pinned !== this.pinned) {
tab.ownerGlobal.gBrowser.unpinTab(tab);
}
let tabToMove =

View file

@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea9596403cef 100644 index 84d633471c89230b981d8a07babef4e0c76c0338..7cef57d99eca61f49968a128378d71c44f52556e 100644
--- a/browser/components/tabbrowser/content/tabs.js --- a/browser/components/tabbrowser/content/tabs.js
+++ b/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js
@@ -83,7 +83,7 @@ @@ -83,7 +83,7 @@
@ -46,6 +46,15 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
expandGroupOnDrop = true; expandGroupOnDrop = true;
} }
} }
@@ -868,7 +869,7 @@
? event.screenY - window.screenY - tabOffset
: event.screenY - window.screenY,
scrollPos:
- this.verticalMode && tab.pinned
+ this.verticalMode && tab.pinned && false
? this.verticalPinnedTabsContainer.scrollPosition
: this.arrowScrollbox.scrollPosition,
screenX: event.screenX,
@@ -921,6 +922,10 @@ @@ -921,6 +922,10 @@
} }
@ -76,31 +85,32 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
if (draggedTab && dropEffect == "copy") { if (draggedTab && dropEffect == "copy") {
let duplicatedDraggedTab; let duplicatedDraggedTab;
let duplicatedTabs = []; let duplicatedTabs = [];
@@ -1116,10 +1133,11 @@ @@ -1116,7 +1133,7 @@
} }
} else { } else {
let isPinned = draggedTab.pinned; let isPinned = draggedTab.pinned;
- let numPinned = gBrowser.pinnedTabCount; - let numPinned = gBrowser.pinnedTabCount;
+ let numPinned = gBrowser._numVisiblePinTabsWithoutCollapsed; + let numPinned = gBrowser._numVisiblePinTabsWithoutCollapsed;
+ let essential = draggedTab.hasAttribute("zen-essential");
let tabs = this.ariaFocusableItems.slice( let tabs = this.ariaFocusableItems.slice(
- isPinned ? 0 : numPinned, isPinned ? 0 : numPinned,
- isPinned ? numPinned : undefined isPinned ? numPinned : undefined
+ isPinned ? (essential ? 0 : gBrowser._numZenEssentials) : numPinned, @@ -1135,8 +1152,14 @@
+ isPinned ? (essential ? gBrowser._numZenEssentials : numPinned) : undefined (lastMovingTabScreen + tabSize);
);
let size = this.verticalMode ? "height" : "width"; if (this.verticalMode) {
let screenAxis = this.verticalMode ? "screenY" : "screenX"; + if (oldTranslateY > 0 && translateOffsetY > tabHeight / 2) {
@@ -1211,7 +1229,7 @@ + newTranslateY += tabHeight;
item.removeAttribute("tabdrop-samewindow"); + }
resolve(); + if (oldTranslateY < 0 && -translateOffsetY > tabHeight / 2) {
}; + newTranslateY -= tabHeight;
- if (gReduceMotion) { + }
+ if (true || gReduceMotion) { newTranslateY = Math.min(
postTransitionCleanup(); - Math.max(oldTranslateY, firstBound),
} else { + Math.max(newTranslateY, firstBound),
let onTransitionEnd = transitionendEvent => { lastBound
@@ -1337,6 +1355,7 @@ );
} else {
@@ -1337,6 +1360,7 @@
let nextItem = this.ariaFocusableItems[newIndex]; let nextItem = this.ariaFocusableItems[newIndex];
let tabGroup = isTab(nextItem) && nextItem.group; let tabGroup = isTab(nextItem) && nextItem.group;
@ -108,7 +118,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
gBrowser.loadTabs(urls, { gBrowser.loadTabs(urls, {
inBackground, inBackground,
replace, replace,
@@ -1369,6 +1388,17 @@ @@ -1369,6 +1393,17 @@
this.finishMoveTogetherSelectedTabs(draggedTab); this.finishMoveTogetherSelectedTabs(draggedTab);
this.finishAnimateTabMove(); this.finishAnimateTabMove();
@ -126,7 +136,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
this.#expandGroupOnDrop(draggedTab); this.#expandGroupOnDrop(draggedTab);
if ( if (
@@ -1597,7 +1627,7 @@ @@ -1597,7 +1632,7 @@
} }
get newTabButton() { get newTabButton() {
@ -135,7 +145,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
} }
get verticalMode() { get verticalMode() {
@@ -1621,29 +1651,54 @@ @@ -1621,29 +1656,54 @@
if (this.#allTabs) { if (this.#allTabs) {
return this.#allTabs; return this.#allTabs;
} }
@ -198,7 +208,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
} }
/** /**
@@ -1698,23 +1753,18 @@ @@ -1698,23 +1758,18 @@
} }
let elementIndex = 0; let elementIndex = 0;
@ -226,7 +236,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let visibleTabsInGroup = child.tabs.filter(tab => tab.visible); let visibleTabsInGroup = child.tabs.filter(tab => tab.visible);
visibleTabsInGroup.forEach(tab => { visibleTabsInGroup.forEach(tab => {
tab.elementIndex = elementIndex++; tab.elementIndex = elementIndex++;
@@ -1724,10 +1774,7 @@ @@ -1724,10 +1779,7 @@
} }
} }
@ -238,7 +248,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
return this.#focusableItems; return this.#focusableItems;
} }
@@ -1735,6 +1782,7 @@ @@ -1735,6 +1787,7 @@
_invalidateCachedTabs() { _invalidateCachedTabs() {
this.#allTabs = null; this.#allTabs = null;
this._invalidateCachedVisibleTabs(); this._invalidateCachedVisibleTabs();
@ -246,7 +256,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
} }
_invalidateCachedVisibleTabs() { _invalidateCachedVisibleTabs() {
@@ -1749,8 +1797,8 @@ @@ -1749,8 +1802,8 @@
#isContainerVerticalPinnedGrid(tab) { #isContainerVerticalPinnedGrid(tab) {
return ( return (
this.verticalMode && this.verticalMode &&
@ -257,7 +267,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
!this.expandOnHover !this.expandOnHover
); );
} }
@@ -1766,7 +1814,7 @@ @@ -1766,7 +1819,7 @@
if (node == null) { if (node == null) {
// We have a container for non-tab elements at the end of the scrollbox. // We have a container for non-tab elements at the end of the scrollbox.
@ -266,7 +276,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
} }
node.before(tab); node.before(tab);
@@ -1861,7 +1909,7 @@ @@ -1861,7 +1914,7 @@
// There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and // There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and
// for when the tab strip is overflowed (which is shared by vertical and horizontal tabs); // for when the tab strip is overflowed (which is shared by vertical and horizontal tabs);
// Attach the long click popup to all of them. // Attach the long click popup to all of them.
@ -275,7 +285,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
const newTab2 = this.newTabButton; const newTab2 = this.newTabButton;
const newTabVertical = document.getElementById( const newTabVertical = document.getElementById(
"vertical-tabs-newtab-button" "vertical-tabs-newtab-button"
@@ -1956,10 +2004,12 @@ @@ -1956,10 +2009,12 @@
_handleTabSelect(aInstant) { _handleTabSelect(aInstant) {
let selectedTab = this.selectedItem; let selectedTab = this.selectedItem;
@ -288,7 +298,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
selectedTab._notselectedsinceload = false; selectedTab._notselectedsinceload = false;
} }
@@ -2132,6 +2182,7 @@ @@ -2132,6 +2187,7 @@
} }
_positionPinnedTabs() { _positionPinnedTabs() {
@ -296,7 +306,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let tabs = this.visibleTabs; let tabs = this.visibleTabs;
let numPinned = gBrowser.pinnedTabCount; let numPinned = gBrowser.pinnedTabCount;
let absPositionHorizontalTabs = let absPositionHorizontalTabs =
@@ -2206,7 +2257,7 @@ @@ -2206,7 +2262,7 @@
return; return;
} }
@ -305,16 +315,25 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let directionX = screenX > dragData.animLastScreenX; let directionX = screenX > dragData.animLastScreenX;
let directionY = screenY > dragData.animLastScreenY; let directionY = screenY > dragData.animLastScreenY;
@@ -2214,7 +2265,7 @@ @@ -2215,6 +2271,8 @@
dragData.animLastScreenX = screenX;
let { width: tabWidth, height: tabHeight } = let { width: tabWidth, height: tabHeight } =
- draggedTab.getBoundingClientRect(); draggedTab.getBoundingClientRect();
+ (draggedTab.group?.hasAttribute("split-view-group") ? draggedTab.group : draggedTab).getBoundingClientRect(); + tabWidth += 4; // Add 4px to account for the gap
+ tabHeight += 4;
let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeX = tabWidth * movingTabs.length;
let shiftSizeY = tabHeight; let shiftSizeY = tabHeight;
dragData.tabWidth = tabWidth; dragData.tabWidth = tabWidth;
@@ -2389,12 +2440,16 @@ @@ -2244,7 +2302,7 @@
let translateX = screenX - dragData.screenX;
let translateY = screenY - dragData.screenY;
translateY +=
- this.verticalPinnedTabsContainer.scrollPosition - dragData.scrollPos;
+ dragData.scrollPos;
let firstBoundX = firstTabInRow.screenX - firstMovingTabScreenX;
let firstBoundY = firstTabInRow.screenY - firstMovingTabScreenY;
let lastBoundX =
@@ -2389,12 +2447,16 @@
this.#clearDragOverCreateGroupTimer(); this.#clearDragOverCreateGroupTimer();
@ -335,7 +354,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
if (this.#rtlMode) { if (this.#rtlMode) {
tabs.reverse(); tabs.reverse();
@@ -2408,7 +2463,7 @@ @@ -2408,7 +2470,7 @@
let size = this.verticalMode ? "height" : "width"; let size = this.verticalMode ? "height" : "width";
let translateAxis = this.verticalMode ? "translateY" : "translateX"; let translateAxis = this.verticalMode ? "translateY" : "translateX";
let scrollDirection = this.verticalMode ? "scrollTop" : "scrollLeft"; let scrollDirection = this.verticalMode ? "scrollTop" : "scrollLeft";
@ -344,7 +363,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let translateX = event.screenX - dragData.screenX; let translateX = event.screenX - dragData.screenX;
let translateY = event.screenY - dragData.screenY; let translateY = event.screenY - dragData.screenY;
@@ -2422,12 +2477,21 @@ @@ -2422,12 +2484,21 @@
let lastTab = tabs.at(-1); let lastTab = tabs.at(-1);
let lastMovingTab = movingTabs.at(-1); let lastMovingTab = movingTabs.at(-1);
let firstMovingTab = movingTabs[0]; let firstMovingTab = movingTabs[0];
@ -367,7 +386,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
translate += translate +=
this.arrowScrollbox.scrollbox[scrollDirection] - dragData.scrollPos; this.arrowScrollbox.scrollbox[scrollDirection] - dragData.scrollPos;
} else if (isPinned && this.verticalMode) { } else if (isPinned && this.verticalMode) {
@@ -2446,6 +2510,9 @@ @@ -2446,6 +2517,9 @@
// Shift the `.tab-group-label-container` to shift the label element. // Shift the `.tab-group-label-container` to shift the label element.
item = item.parentElement; item = item.parentElement;
} }
@ -377,7 +396,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
item.style.transform = `${translateAxis}(${translate}px)`; item.style.transform = `${translateAxis}(${translate}px)`;
} }
@@ -2583,6 +2650,9 @@ @@ -2583,6 +2657,9 @@
break; break;
} }
let element = tabs[mid]; let element = tabs[mid];
@ -387,7 +406,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let elementForSize = isTabGroupLabel(element) let elementForSize = isTabGroupLabel(element)
? element.parentElement ? element.parentElement
: element; : element;
@@ -2605,6 +2675,10 @@ @@ -2605,6 +2682,10 @@
if (!dropElement) { if (!dropElement) {
dropElement = this.ariaFocusableItems[oldDropElementIndex]; dropElement = this.ariaFocusableItems[oldDropElementIndex];
} }
@ -398,7 +417,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
let newDropElementIndex = dropElement let newDropElementIndex = dropElement
? dropElement.elementIndex ? dropElement.elementIndex
: oldDropElementIndex; : oldDropElementIndex;
@@ -2613,7 +2687,7 @@ @@ -2613,7 +2694,7 @@
let shouldCreateGroupOnDrop; let shouldCreateGroupOnDrop;
let dropBefore; let dropBefore;
if (dropElement) { if (dropElement) {
@ -407,7 +426,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
? dropElement.parentElement ? dropElement.parentElement
: dropElement; : dropElement;
@@ -2675,12 +2749,12 @@ @@ -2675,12 +2756,12 @@
} }
} }
@ -422,7 +441,16 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
dropElement != draggedTab && dropElement != draggedTab &&
isTab(dropElement) && isTab(dropElement) &&
!dropElement?.group && !dropElement?.group &&
@@ -2750,7 +2824,7 @@ @@ -2720,7 +2801,7 @@
// Dropping right before the tab group.
dropElement = dropElementGroup;
colorCode = undefined;
- } else if (dropElementGroup.collapsed) {
+ } else if (dropElement?.group?.hasAttribute("split-view-group")) {
// Dropping right after the collapsed tab group.
dropElement = dropElementGroup;
colorCode = undefined;
@@ -2750,7 +2831,7 @@
// Shift background tabs to leave a gap where the dragged tab // Shift background tabs to leave a gap where the dragged tab
// would currently be dropped. // would currently be dropped.
for (let item of tabs) { for (let item of tabs) {
@ -431,7 +459,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
continue; continue;
} }
@@ -2759,6 +2833,9 @@ @@ -2759,6 +2840,9 @@
if (isTabGroupLabel(item)) { if (isTabGroupLabel(item)) {
// Shift the `.tab-group-label-container` to shift the label element. // Shift the `.tab-group-label-container` to shift the label element.
item = item.parentElement; item = item.parentElement;
@ -441,7 +469,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
} }
item.style.transform = transform; item.style.transform = transform;
} }
@@ -2811,8 +2888,9 @@ @@ -2811,8 +2895,9 @@
); );
} }
@ -453,7 +481,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
return; return;
} }
@@ -2824,6 +2902,12 @@ @@ -2824,6 +2909,12 @@
item = item.parentElement; item = item.parentElement;
} }
item.style.transform = ""; item.style.transform = "";
@ -466,7 +494,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
item.removeAttribute("dragover-createGroup"); item.removeAttribute("dragover-createGroup");
} }
this.removeAttribute("movingtab-createGroup"); this.removeAttribute("movingtab-createGroup");
@@ -2870,7 +2954,7 @@ @@ -2870,7 +2961,7 @@
let postTransitionCleanup = () => { let postTransitionCleanup = () => {
movingTab._moveTogetherSelectedTabsData.animate = false; movingTab._moveTogetherSelectedTabsData.animate = false;
}; };
@ -475,7 +503,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
postTransitionCleanup(); postTransitionCleanup();
} else { } else {
let onTransitionEnd = transitionendEvent => { let onTransitionEnd = transitionendEvent => {
@@ -3043,7 +3127,7 @@ @@ -3043,7 +3134,7 @@
} }
_notifyBackgroundTab(aTab) { _notifyBackgroundTab(aTab) {
@ -484,7 +512,7 @@ index 84d633471c89230b981d8a07babef4e0c76c0338..1a9c56846ff27d68c16b939fb759ea95
return; return;
} }
@@ -3169,6 +3253,9 @@ @@ -3169,6 +3260,9 @@
return null; return null;
} }
} }

View file

@ -1,13 +1,12 @@
diff --git a/toolkit/themes/shared/menu.css b/toolkit/themes/shared/menu.css diff --git a/toolkit/themes/shared/menu.css b/toolkit/themes/shared/menu.css
index ecf66f30b2dd18765af467913bb0bc66a8d36a41..6b58db0c1590b0151a3e169b75d4d2ee19db912c 100644 index ecf66f30b2dd18765af467913bb0bc66a8d36a41..8ecb03f8f09100dc76e8e4dabd13c366717268b4 100644
--- a/toolkit/themes/shared/menu.css --- a/toolkit/themes/shared/menu.css
+++ b/toolkit/themes/shared/menu.css +++ b/toolkit/themes/shared/menu.css
@@ -345,7 +345,7 @@ menuitem[highlightable] > .menu-text { @@ -345,7 +345,6 @@ menuitem[highlightable] > .menu-text {
/* On macOS and Windows, empty icons shouldn't take up any space */ /* On macOS and Windows, empty icons shouldn't take up any space */
menuitem:not(.menuitem-iconic, [image]) > &, menuitem:not(.menuitem-iconic, [image]) > &,
menu:not(.menu-iconic) > & { menu:not(.menu-iconic) > & {
- display: none; - display: none;
+
} }
} }
} }

View file

@ -0,0 +1,99 @@
{
class ZenSessionStore extends ZenPreloadedFeature {
init() {
this.#waitAndCleanup();
}
#glanceTabs = {};
promiseInitialized = new Promise((resolve) => {
this._resolveInitialized = resolve;
});
restoreInitialTabData(tab, tabData) {
if (tabData.zenWorkspace) {
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
}
if (tabData.zenPinnedId) {
tab.setAttribute('zen-pin-id', tabData.zenPinnedId);
}
if (tabData.zenIsEmpty) {
tab.setAttribute('zen-empty-tab', 'true');
}
if (tabData.zenHasStaticLabel) {
tab.setAttribute('zen-has-static-label', 'true');
}
if (tabData.zenEssential) {
tab.setAttribute('zen-essential', 'true');
}
if (tabData.zenDefaultUserContextId) {
tab.setAttribute('zenDefaultUserContextId', 'true');
}
if (tabData.zenPinnedEntry) {
tab.setAttribute('zen-pinned-entry', tabData.zenPinnedEntry);
}
if (tabData.zenGlanceId) {
// We just found the background used for glance. Find
// the current
if (tabData.zenIsGlance) {
if (this.#glanceTabs[tabData.zenGlanceId]) {
this.#glanceTabs[tabData.zenGlanceId].tab = tab;
} else {
this.#glanceTabs[tabData.zenGlanceId] = {
tab: tab,
background: null,
};
}
} else {
if (this.#glanceTabs[tabData.zenGlanceId]) {
this.#glanceTabs[tabData.zenGlanceId].background = tab;
} else {
this.#glanceTabs[tabData.zenGlanceId] = {
tab: null,
background: tab,
};
}
}
}
}
async #resolveGlanceTabs() {
for (const [id, data] of Object.entries(this.#glanceTabs)) {
const { tab, background } = data;
// TODO(Restore glance tab): Finish this implementation
continue;
if (!tab || !background) {
tab?.removeAttribute('glance-id');
background?.removeAttribute('glance-id');
continue;
}
console.log(tab, background);
const browserRect = gBrowser.tabbox.getBoundingClientRect();
await gZenGlanceManager.openGlance(
{
url: undefined,
x: browserRect.width / 2,
y: browserRect.height / 2,
width: 0,
height: 0,
},
tab,
background
);
}
}
async #waitAndCleanup() {
await SessionStore.promiseInitialized;
await this.#resolveGlanceTabs();
this.#cleanup();
}
#cleanup() {
this._resolveInitialized();
delete window.gZenSessionStore;
}
}
window.gZenSessionStore = new ZenSessionStore();
}

View file

@ -989,43 +989,54 @@ var gZenVerticalTabsManager = {
async renameTabKeydown(event) { async renameTabKeydown(event) {
event.stopPropagation(); event.stopPropagation();
if (event.key === 'Enter') { if (event.key === 'Enter') {
let label = this._tabEdited.querySelector('.tab-label-container-editing'); const isTab = !!event.target.closest('.tabbrowser-tab');
let input = this._tabEdited.querySelector('#tab-label-input'); let label = isTab
? this._tabEdited.querySelector('.tab-label-container-editing')
: this._tabEdited;
let input = document.getElementById('tab-label-input');
let newName = input.value.trim(); let newName = input.value.trim();
// Check if name is blank, reset if so document.documentElement.removeAttribute('zen-renaming-tab');
// Always remove, so we can always rename and if it's empty, input.remove();
// it will reset to the original name anyway if (!isTab) {
this._tabEdited.removeAttribute('zen-has-static-label'); await this._tabEdited.onRenameFinished(newName);
if (newName) {
gBrowser._setTabLabel(this._tabEdited, newName);
this._tabEdited.setAttribute('zen-has-static-label', 'true');
gZenUIManager.showToast('zen-tabs-renamed');
} else { } else {
gBrowser.setTabTitle(this._tabEdited); // Check if name is blank, reset if so
} // Always remove, so we can always rename and if it's empty,
if (this._tabEdited.getAttribute('zen-pin-id')) { // it will reset to the original name anyway
// Update pin title in storage this._tabEdited.removeAttribute('zen-has-static-label');
await gZenPinnedTabManager.updatePinTitle( if (newName) {
gBrowser._setTabLabel(this._tabEdited, newName);
this._tabEdited.setAttribute('zen-has-static-label', 'true');
gZenUIManager.showToast('zen-tabs-renamed');
} else {
gBrowser.setTabTitle(this._tabEdited);
}
if (this._tabEdited.getAttribute('zen-pin-id')) {
// Update pin title in storage
await gZenPinnedTabManager.updatePinTitle(
this._tabEdited,
this._tabEdited.label,
!!newName
);
}
// Maybe add some confetti here?!?
gZenUIManager.motion.animate(
this._tabEdited, this._tabEdited,
this._tabEdited.label, {
!!newName scale: [1, 0.98, 1],
},
{
duration: 0.25,
}
); );
} }
document.documentElement.removeAttribute('zen-renaming-tab');
// Maybe add some confetti here?!? const editorContainer = this._tabEdited.querySelector('.tab-editor-container');
gZenUIManager.motion.animate( if (editorContainer) {
this._tabEdited, editorContainer.remove();
{ }
scale: [1, 0.98, 1],
},
{
duration: 0.25,
}
);
this._tabEdited.querySelector('.tab-editor-container').remove();
label.classList.remove('tab-label-container-editing'); label.classList.remove('tab-label-container-editing');
this._tabEdited = null; this._tabEdited = null;
@ -1035,34 +1046,45 @@ var gZenVerticalTabsManager = {
}, },
renameTabStart(event) { renameTabStart(event) {
const isTab = !!event.target.closest('.tabbrowser-tab');
if ( if (
this._tabEdited || this._tabEdited ||
!Services.prefs.getBoolPref('zen.tabs.rename-tabs') || ((!Services.prefs.getBoolPref('zen.tabs.rename-tabs') ||
Services.prefs.getBoolPref('browser.tabs.closeTabByDblclick') || Services.prefs.getBoolPref('browser.tabs.closeTabByDblclick')) &&
isTab) ||
!gZenVerticalTabsManager._prefsSidebarExpanded !gZenVerticalTabsManager._prefsSidebarExpanded
) )
return; return;
this._tabEdited = event.target.closest('.tabbrowser-tab'); this._tabEdited =
event.target.closest('.tabbrowser-tab') ||
event.target.closest('.zen-current-workspace-indicator-name') ||
gZenWorkspaces.activeWorkspaceIndicator.querySelector(
'.zen-current-workspace-indicator-name'
);
if ( if (
!this._tabEdited || !this._tabEdited ||
!this._tabEdited.pinned || ((!this._tabEdited.pinned || this._tabEdited.hasAttribute('zen-essential')) && isTab)
this._tabEdited.hasAttribute('zen-essential')
) { ) {
this._tabEdited = null; this._tabEdited = null;
return; return;
} }
event.stopPropagation();
document.documentElement.setAttribute('zen-renaming-tab', 'true'); document.documentElement.setAttribute('zen-renaming-tab', 'true');
const label = this._tabEdited.querySelector('.tab-label-container'); const label = isTab ? this._tabEdited.querySelector('.tab-label-container') : this._tabEdited;
label.classList.add('tab-label-container-editing'); label.classList.add('tab-label-container-editing');
const container = window.MozXULElement.parseXULToFragment(` if (isTab) {
<vbox class="tab-label-container tab-editor-container" flex="1" align="start" pack="center"></vbox> const container = window.MozXULElement.parseXULToFragment(`
`); <vbox class="tab-label-container tab-editor-container" flex="1" align="start" pack="center"></vbox>
label.after(container); `);
const containerHtml = this._tabEdited.querySelector('.tab-editor-container'); label.after(container);
}
const containerHtml = isTab
? this._tabEdited.querySelector('.tab-editor-container')
: this._tabEdited.parentNode;
const input = document.createElement('input'); const input = document.createElement('input');
input.id = 'tab-label-input'; input.id = 'tab-label-input';
input.value = this._tabEdited.label; input.value = isTab ? this._tabEdited.label : this._tabEdited.textContent;
input.addEventListener('keydown', this.renameTabKeydown.bind(this)); input.addEventListener('keydown', this.renameTabKeydown.bind(this));
containerHtml.appendChild(input); containerHtml.appendChild(input);
@ -1077,8 +1099,16 @@ var gZenVerticalTabsManager = {
return; return;
} }
document.documentElement.removeAttribute('zen-renaming-tab'); document.documentElement.removeAttribute('zen-renaming-tab');
this._tabEdited.querySelector('.tab-editor-container').remove(); const editorContainer = this._tabEdited.querySelector('.tab-editor-container');
const label = this._tabEdited.querySelector('.tab-label-container-editing'); let input = document.getElementById('tab-label-input');
input.remove();
if (editorContainer) {
editorContainer.remove();
}
const isTab = !!this._tabEdited.closest('.tabbrowser-tab');
const label = isTab
? this._tabEdited.querySelector('.tab-label-container-editing')
: this._tabEdited;
label.classList.remove('tab-label-container-editing'); label.classList.remove('tab-label-container-editing');
this._tabEdited = null; this._tabEdited = null;

View file

@ -705,8 +705,8 @@
} }
getTabOrGlanceParent(tab) { getTabOrGlanceParent(tab) {
if (tab?.hasAttribute('glance-id')) { if (tab?.hasAttribute('glance-id') && this.#glances) {
const parentTab = this.#glances.get(tab.getAttribute('glance-id')).parentTab; const parentTab = this.#glances.get(tab.getAttribute('glance-id'))?.parentTab;
if (parentTab) { if (parentTab) {
return parentTab; return parentTab;
} }

View file

@ -104,6 +104,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
); );
window.addEventListener('TabClose', this.handleTabClose.bind(this)); window.addEventListener('TabClose', this.handleTabClose.bind(this));
window.addEventListener('TabBrowserDiscarded', this.handleTabBrowserDiscarded.bind(this));
window.addEventListener('TabSelect', this.onTabSelect.bind(this)); window.addEventListener('TabSelect', this.onTabSelect.bind(this));
this.initializeContextMenu(); this.initializeContextMenu();
this.insertIntoContextMenu(); this.insertIntoContextMenu();
@ -150,6 +151,17 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.removeTabFromGroup(tab, groupIndex, true); this.removeTabFromGroup(tab, groupIndex, true);
} }
/**
* @param {Event} event - The event that triggered the tab browser discard.
* @description Handles the tab browser discard event.
*/
async handleTabBrowserDiscarded(event) {
const tab = event.target;
if (tab.group?.hasAttribute('split-view-group')) {
gBrowser.explicitUnloadTabs(tab.group.tabs);
}
}
/** /**
* @param {Event} event - The event that triggered the tab select. * @param {Event} event - The event that triggered the tab select.
* @description Handles the tab select event. * @description Handles the tab select event.

View file

@ -356,6 +356,7 @@
margin-block: 0 !important; margin-block: 0 !important;
margin-inline: 0 !important; margin-inline: 0 !important;
box-shadow: none !important; box-shadow: none !important;
border-radius: calc(var(--border-radius-medium) - 2px);
} }
/* Adjust padding for content */ /* Adjust padding for content */
& .tab-content { & .tab-content {
@ -374,6 +375,27 @@
width: 14px; width: 14px;
height: 14px; height: 14px;
} }
& .tab-audio-button {
display: none !important;
}
&[soundplaying]:not([muted]) .tab-icon-stack::after {
content: '';
position: absolute;
width: 110%;
height: 110%;
background-repeat: no-repeat;
opacity: 1;
background: url('chrome://browser/content/zen-images/note-indicator.svg') no-repeat;
top: -70%;
left: 50%;
transform: translateX(-50%);
z-index: 0;
pointer-events: none;
transition: opacity 0.8s ease;
opacity: 1;
}
} }
/* --- Essentials Glance Tab Specifics (Floating) --- */ /* --- Essentials Glance Tab Specifics (Floating) --- */
@ -1239,7 +1261,7 @@
padding-bottom: var(--zen-toolbox-padding); padding-bottom: var(--zen-toolbox-padding);
overflow: hidden; overflow: hidden;
gap: calc(var(--zen-toolbox-padding) - 2px); gap: 4px;
transition: transition:
max-height 0.3s ease-out, max-height 0.3s ease-out,
grid-template-columns 0.3s ease-out; grid-template-columns 0.3s ease-out;

View file

@ -42,11 +42,6 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._resolveInitialized = resolve; this._resolveInitialized = resolve;
}); });
workspaceIndicatorXUL = `
<hbox class="zen-current-workspace-indicator-icon"></hbox>
<hbox class="zen-current-workspace-indicator-name"></hbox>
`;
async waitForPromises() { async waitForPromises() {
if (this.privateWindowOrDisabled) { if (this.privateWindowOrDisabled) {
return; return;
@ -858,6 +853,9 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
console.error('gZenWorkspaces: Error initializing theme picker', e); console.error('gZenWorkspaces: Error initializing theme picker', e);
} }
this.onWindowResize(); this.onWindowResize();
if (window.gZenSessionStore) {
await gZenSessionStore.promiseInitialized;
}
await this._selectStartPage(); await this._selectStartPage();
this._fixTabPositions(); this._fixTabPositions();
this._resolveInitialized(); this._resolveInitialized();
@ -915,7 +913,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
) { ) {
this.log(`Found tab to select: ${this._tabToSelect}, ${tabs.length}`); this.log(`Found tab to select: ${this._tabToSelect}, ${tabs.length}`);
setTimeout(() => { setTimeout(() => {
gBrowser.selectedTab = tabs[this._tabToSelect]; gBrowser.selectedTab = gZenGlanceManager.getTabOrGlanceParent(tabs[this._tabToSelect]);
this._removedByStartupPage = true; this._removedByStartupPage = true;
gBrowser.removeTab(this._tabToRemoveForEmpty, { gBrowser.removeTab(this._tabToRemoveForEmpty, {
skipSessionStore: true, skipSessionStore: true,
@ -2941,6 +2939,9 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
_initializeWorkspaceTabContextMenus() { _initializeWorkspaceTabContextMenus() {
if (this.privateWindowOrDisabled) {
return;
}
const menu = document.createXULElement('menu'); const menu = document.createXULElement('menu');
menu.setAttribute('id', 'context-zen-change-workspace-tab'); menu.setAttribute('id', 'context-zen-change-workspace-tab');
menu.setAttribute('data-l10n-id', 'context-zen-change-workspace-tab'); menu.setAttribute('data-l10n-id', 'context-zen-change-workspace-tab');