diff --git a/src/browser/base/content/zen-styles/zen-folders.css b/src/browser/base/content/zen-styles/zen-folders.css index c3f5aa8a..761aab18 100644 --- a/src/browser/base/content/zen-styles/zen-folders.css +++ b/src/browser/base/content/zen-styles/zen-folders.css @@ -120,8 +120,7 @@ tab-group[split-view-group] .tabbrowser-tab { } tab-group[split-view-group] .tab-group-label-container { - display: none; - width: 100%; + visibility: collapse; } tab-group[split-view-group] .tab-close-button { diff --git a/src/browser/base/zen-components/ZenFolders.mjs b/src/browser/base/zen-components/ZenFolders.mjs index 976598be..a4c49985 100644 --- a/src/browser/base/zen-components/ZenFolders.mjs +++ b/src/browser/base/zen-components/ZenFolders.mjs @@ -9,6 +9,8 @@ document.addEventListener('TabUngrouped', this.#onTabUngrouped.bind(this)); document.addEventListener('TabGroupRemoved', this.#onTabGroupRemoved.bind(this)); document.addEventListener('TabGroupCreate', this.#onTabGroupCreate.bind(this)); + document.addEventListener('TabPinned', this.#onTabPinned.bind(this)); + document.addEventListener('TabUnpinned', this.#onTabUnpinned.bind(this)); } #onTabGrouped(event) { @@ -49,6 +51,22 @@ #onTabGroupRemoved(event) {} + #onTabPinned(event) { + const tab = event.target; + const group = tab.group; + if (group && group.hasAttribute('split-view-group')) { + group.pinned = true; + } + } + + #onTabUnpinned(event) { + const tab = event.target; + const group = tab.group; + if (group && group.hasAttribute('split-view-group')) { + group.pinned = false; + } + } + expandGroupTabs(group) { for (const tab of group.tabs.reverse()) { gBrowser.ungroupTab(tab); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 055a0599..8778f7c8 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035ace83e08 100644 +index 5f406ea5d09273c9b70b84eee24c6267f88692f8..25076e5fdbe5a60cc0f35640652ba8525a55b093 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js -@@ -424,11 +424,66 @@ +@@ -424,11 +424,67 @@ return this.tabContainer.visibleTabs; } @@ -19,17 +19,18 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 + return i; + } + -+ get _numVisiblePinTabsWithFolders() { ++ get _numVisiblePinTabsWithoutCollapsed() { + let i = 0; -+ for (let tab of this.tabs) { -+ if (!tab.pinned && !tab.hasAttribute("zen-glance-tab")) { ++ for (let item of this.tabContainer.ariaFocusableItems) { ++ if (!!item?.classList?.contains("tab-group-label")) { ++ i += 1; ++ continue; ++ } ++ if (!item.pinned && !item.hasAttribute("zen-glance-tab")) { + break; + } -+ if (!tab.hidden) { -+ i += !tab.hasAttribute("zen-glance-tab"); -+ } -+ if (tab.group?.tabs[0] == tab) { -+ i++; ++ if ((!item.group?.hasAttribute("split-view-group") && !item.group?.collapsed) && !item.hidden) { ++ i += !item.hasAttribute("zen-glance-tab"); + } + } + return i; @@ -71,7 +72,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } return i; } -@@ -558,6 +613,7 @@ +@@ -558,6 +614,7 @@ this.tabpanels.appendChild(panel); let tab = this.tabs[0]; @@ -79,7 +80,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 tab.linkedPanel = uniqueId; this._selectedTab = tab; this._selectedBrowser = browser; -@@ -823,11 +879,13 @@ +@@ -823,11 +880,13 @@ } this.showTab(aTab); @@ -96,7 +97,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 this.moveTabTo(aTab, this.pinnedTabCount, { forceStandaloneTab: true }); } aTab.setAttribute("pinned", "true"); -@@ -841,12 +899,15 @@ +@@ -841,12 +900,15 @@ } if (this.tabContainer.verticalMode) { @@ -113,7 +114,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 }); } else { this.moveTabTo(aTab, this.pinnedTabCount - 1, { -@@ -1029,6 +1090,8 @@ +@@ -1029,6 +1091,8 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; @@ -122,7 +123,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if ( aIconURL && !aLoadingPrincipal && -@@ -1039,6 +1102,9 @@ +@@ -1039,6 +1103,9 @@ ); return; } @@ -132,7 +133,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1287,6 +1353,7 @@ +@@ -1287,6 +1354,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -140,7 +141,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1439,6 +1506,9 @@ +@@ -1439,6 +1507,9 @@ } let activeEl = document.activeElement; @@ -150,7 +151,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -1762,7 +1832,7 @@ +@@ -1762,7 +1833,7 @@ } _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { @@ -159,7 +160,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 return false; } -@@ -1865,7 +1935,7 @@ +@@ -1865,7 +1936,7 @@ newIndex = this.selectedTab._tPos + 1; } @@ -168,7 +169,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 let browser; if (targetTab) { browser = this.getBrowserForTab(targetTab); -@@ -2122,6 +2192,7 @@ +@@ -2122,6 +2193,7 @@ uriIsAboutBlank, userContextId, skipLoad, @@ -176,7 +177,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } = {}) { let b = document.createXULElement("browser"); // Use the JSM global to create the permanentKey, so that if the -@@ -2195,8 +2266,7 @@ +@@ -2195,8 +2267,7 @@ // we use a different attribute name for this? b.setAttribute("name", name); } @@ -186,7 +187,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 b.setAttribute("transparent", "true"); } -@@ -2373,7 +2443,7 @@ +@@ -2373,7 +2444,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -195,7 +196,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2432,8 +2502,8 @@ +@@ -2432,8 +2503,8 @@ // If we transitioned from one browser to two browsers, we need to set // hasSiblings=false on both the existing browser and the new browser. if (this.tabs.length == 2) { @@ -206,7 +207,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2655,6 +2725,7 @@ +@@ -2655,6 +2726,7 @@ schemelessInput, hasValidUserGestureActivation = false, textDirectiveUserActivation = false, @@ -214,7 +215,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } = {} ) { // all callers of addTab that pass a params object need to pass -@@ -2665,6 +2736,12 @@ +@@ -2665,6 +2737,12 @@ ); } @@ -227,7 +228,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (!UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.start("browser.tabs.opening", "initting", window); } -@@ -2728,6 +2805,15 @@ +@@ -2728,6 +2806,15 @@ noInitialLabel, skipBackgroundNotify, }); @@ -243,7 +244,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (insertTab) { // insert the tab into the tab container in the correct position this._insertTabAtIndex(t, { -@@ -2752,6 +2838,7 @@ +@@ -2752,6 +2839,7 @@ initialBrowsingContextGroupId, openWindowInfo, skipLoad, @@ -251,7 +252,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 })); if (focusUrlBar) { -@@ -2871,6 +2958,9 @@ +@@ -2871,6 +2959,9 @@ } } @@ -261,7 +262,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 // Additionally send pinned tab events if (pinned) { this._notifyPinnedStatus(t); -@@ -2891,12 +2981,15 @@ +@@ -2891,12 +2982,15 @@ * @param {string} [label=] * @returns {MozTabbrowserTabGroup} */ @@ -278,7 +279,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 return group; } -@@ -2937,6 +3030,7 @@ +@@ -2937,6 +3031,7 @@ insertBefore = null, isUserCreated = false, telemetryUserCreateSource = "unknown", @@ -286,7 +287,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } = {} ) { if (!tabs?.length) { -@@ -2951,7 +3045,12 @@ +@@ -2951,7 +3046,12 @@ id = `${Date.now()}-${Math.round(Math.random() * 100)}`; } let group = this._createTabGroup(id, color, false, label); @@ -300,7 +301,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 group, insertBefore?.group ?? insertBefore ); -@@ -3268,6 +3367,7 @@ +@@ -3268,6 +3368,7 @@ initialBrowsingContextGroupId, openWindowInfo, skipLoad, @@ -308,7 +309,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } ) { // If we don't have a preferred remote type, and we have a remote -@@ -3331,6 +3431,7 @@ +@@ -3331,6 +3432,7 @@ openWindowInfo, name, skipLoad, @@ -316,7 +317,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 }); } -@@ -3509,6 +3610,27 @@ +@@ -3509,6 +3611,27 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -344,7 +345,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3522,6 +3644,7 @@ +@@ -3522,6 +3645,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -352,7 +353,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3557,7 +3680,27 @@ +@@ -3557,7 +3681,27 @@ skipLoad: true, preferredRemoteType, }); @@ -381,7 +382,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (select) { tabToSelect = tab; } -@@ -3570,8 +3713,8 @@ +@@ -3570,8 +3714,8 @@ // inserted in the DOM. If the tab is not yet in the DOM, // just insert it in the right place from the start. if (!tab.parentNode) { @@ -392,7 +393,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3581,7 +3724,8 @@ +@@ -3581,7 +3725,8 @@ // needs calling: shouldUpdateForPinnedTabs = true; } @@ -402,7 +403,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 let { groupId } = tabData; const tabGroup = tabGroupWorkingData.get(groupId); // if a tab refers to a tab group we don't know, skip any group -@@ -3595,7 +3739,10 @@ +@@ -3595,7 +3740,10 @@ tabGroup.stateData.id, tabGroup.stateData.color, tabGroup.stateData.collapsed, @@ -414,7 +415,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 ); tabsFragment.appendChild(tabGroup.node); } -@@ -3646,6 +3793,9 @@ +@@ -3646,6 +3794,9 @@ this.selectedTab = tabToSelect; this.removeTab(leftoverTab); } @@ -424,7 +425,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (tabs.length > 1 || !tabs[0].selected) { this._updateTabsAfterInsert(); -@@ -3830,7 +3980,7 @@ +@@ -3830,7 +3981,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -433,7 +434,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if ( !bulkOrderedOpen && ((openerTab && -@@ -3876,18 +4026,18 @@ +@@ -3876,18 +4027,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -456,7 +457,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (tabAfter && tabAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, tabAfter); -@@ -4199,6 +4349,9 @@ +@@ -4199,6 +4350,9 @@ return; } @@ -466,7 +467,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 this.removeTabs(selectedTabs); } -@@ -4556,6 +4709,7 @@ +@@ -4556,6 +4710,7 @@ skipSessionStore, } = {} ) { @@ -474,7 +475,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4572,6 +4726,12 @@ +@@ -4572,6 +4727,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -487,7 +488,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4586,7 +4746,9 @@ +@@ -4586,7 +4747,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -498,7 +499,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4600,7 +4762,6 @@ +@@ -4600,7 +4763,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -506,7 +507,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4739,14 +4900,14 @@ +@@ -4739,14 +4901,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -523,7 +524,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4770,6 +4931,7 @@ +@@ -4770,6 +4932,7 @@ newTab = true; } @@ -531,7 +532,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4810,9 +4972,7 @@ +@@ -4810,9 +4973,7 @@ aTab._mouseleave(); if (newTab) { @@ -542,7 +543,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } else { TabBarVisibility.update(); } -@@ -4941,6 +5101,8 @@ +@@ -4941,6 +5102,8 @@ this.tabs[i]._tPos = i; } @@ -551,7 +552,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -5159,7 +5321,7 @@ +@@ -5159,7 +5322,7 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -560,7 +561,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } // Try to find a remaining tab that comes after the given tab -@@ -5181,7 +5343,7 @@ +@@ -5181,7 +5344,7 @@ } if (tab) { @@ -569,7 +570,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5599,10 +5761,10 @@ +@@ -5599,10 +5762,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -582,7 +583,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5838,7 +6000,7 @@ +@@ -5838,7 +6001,7 @@ moveTabTo(aTab, aIndex, { forceStandaloneTab = false } = {}) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -591,7 +592,7 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 } else { aIndex = Math.max(aIndex, this.pinnedTabCount); } -@@ -5848,10 +6010,17 @@ +@@ -5848,10 +6011,17 @@ this.#handleTabMove(aTab, () => { let neighbor = this.tabs[aIndex]; @@ -611,13 +612,10 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 neighbor.after(aTab); } else { this.tabContainer.insertBefore(aTab, neighbor); -@@ -5901,6 +6070,13 @@ +@@ -5901,13 +6071,22 @@ * Bug 1955388 - prevent pinned tabs from commingling with non-pinned tabs * when there are hidden tabs present */ -+ if (targetElement?.group?.hasAttribute("split-view-group")) { -+ targetElement = targetElement.group; -+ } + if (tab.group?.hasAttribute("split-view-group")) { + tab = tab.group; + } @@ -625,9 +623,12 @@ index 5f406ea5d09273c9b70b84eee24c6267f88692f8..52e9414c9b6606510538a9f565cb0035 if (tab.pinned && !targetElement?.pinned) { // prevent pinned tab from being dragged past a non-pinned tab targetElement = this.tabs[this.pinnedTabCount - 1]; -@@ -5908,6 +6084,9 @@ + moveBefore = false; } - +- ++ if (targetElement?.group?.hasAttribute("split-view-group")) { ++ targetElement = targetElement.group; ++ } let getContainer = () => { + if (tab.hasAttribute("zen-essential")) { + return document.getElementById("zen-essentials-container"); diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index a018abc4..a3634fb2 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb83c74c10 100644 +index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..40593b305688d24a0b702714a91af551c7f833f9 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -93,7 +93,7 @@ @@ -75,7 +75,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb - let tabs = this.ariaFocusableItems.slice( - isPinned ? 0 : numPinned, - isPinned ? numPinned : undefined -+ let numPinned = gBrowser._numVisiblePinTabsWithFolders; ++ let numPinned = gBrowser._numVisiblePinTabsWithoutCollapsed; + let essential = draggedTab.hasAttribute("zen-essential"); + let tabs = this.ariaFocusableItems.filter(tab => !tab.hasAttribute("zen-glance-tab")).slice( + isPinned ? (essential ? 0 : gBrowser._numZenVisibleEssentials) : numPinned, @@ -195,7 +195,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb } return this.#visibleTabs; } -@@ -1601,16 +1641,11 @@ +@@ -1601,23 +1641,18 @@ } let elementIndex = 0; @@ -215,6 +215,14 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb if (isTab(child) && child.visible) { child.elementIndex = elementIndex++; focusableItems.push(child); + } else if (isTabGroup(child)) { + child.labelElement.elementIndex = elementIndex++; + focusableItems.push(child.labelElement); +- if (!child.collapsed) { ++ if (!child.collapsed && !child.hasAttribute("split-view-group")) { + let visibleTabsInGroup = child.tabs.filter(tab => tab.visible); + visibleTabsInGroup.forEach(tab => { + tab.elementIndex = elementIndex++; @@ -1627,10 +1662,7 @@ } } @@ -385,7 +393,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2296,10 +2328,11 @@ +@@ -2296,11 +2328,15 @@ this.#clearDragOverCreateGroupTimer(); let isPinned = draggedTab.pinned; @@ -393,28 +401,32 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb - let tabs = this.ariaFocusableItems.slice( - isPinned ? 0 : numPinned, - isPinned ? numPinned : undefined -+ let numPinned = gBrowser._numVisiblePinTabsWithFolders; ++ let numPinned = gBrowser._numVisiblePinTabsWithoutCollapsed; + let essential = draggedTab.hasAttribute("zen-essential"); + let tabs = this.ariaFocusableItems.filter(tab => !tab.hasAttribute("zen-glance-tab")).slice( + isPinned ? (essential ? 0 : gBrowser._numZenVisibleEssentials) : numPinned, + isPinned ? (essential ? gBrowser._numZenVisibleEssentials : numPinned) : undefined ); ++ if (draggedTab.group?.hasAttribute("split-view-group")) { ++ draggedTab = draggedTab.group.labelElement; ++ } if (this.#rtlMode) { -@@ -2325,6 +2358,12 @@ - - // Move the dragged tab based on the mouse position. - let firstTab = tabs[0]; -+ if (isTabGroupLabel(firstTab)) { -+ const group = firstTab.closest("tab-group"); -+ if (group?.hasAttribute("split-view-group")) { -+ firstTab = group; -+ } -+ } + tabs.reverse(); +@@ -2328,6 +2364,12 @@ let lastTab = tabs.at(-1); let lastMovingTab = movingTabs.at(-1); let firstMovingTab = movingTabs[0]; -@@ -2348,7 +2387,11 @@ ++ if (lastMovingTab.group?.hasAttribute("split-view-group")) { ++ lastMovingTab = lastMovingTab.group; ++ } ++ if (firstMovingTab.group?.hasAttribute("split-view-group")) { ++ firstMovingTab = firstMovingTab.group; ++ } + let endEdge = ele => ele[screenAxis] + bounds(ele)[size]; + let lastMovingTabScreen = endEdge(lastMovingTab); + let firstMovingTabScreen = firstMovingTab[screenAxis]; +@@ -2348,7 +2390,11 @@ translate = Math.min(Math.max(translate, firstBound), lastBound); for (let tab of movingTabs) { @@ -427,27 +439,42 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb } dragData.translatePos = translate; -@@ -2507,6 +2550,10 @@ +@@ -2379,7 +2425,7 @@ + let getTabShift = (item, dropElementIndex) => { + if ( + item.elementIndex < draggedTab.elementIndex && +- item.elementIndex >= dropElementIndex ++ item.elementIndex + !!item.closest("tab-group")?.hasAttribute("split-view-group") >= dropElementIndex + ) { + return this.#rtlMode ? -shiftSize : shiftSize; + } +@@ -2507,6 +2553,10 @@ if (!dropElement) { dropElement = this.ariaFocusableItems[oldDropElementIndex]; } + if (dropElement?.group?.hasAttribute("split-view-group")) { + // We focus the group label element, not the group itself. -+ dropElement = dropElement.group.querySelector(".tab-group-label"); ++ dropElement = dropElement.group.labelElement; + } let newDropElementIndex = dropElement ? dropElement.elementIndex : oldDropElementIndex; -@@ -2566,7 +2613,7 @@ +@@ -2566,12 +2616,12 @@ } } - if (gBrowser._tabGroupsEnabled && !isPinned) { -+ if (false) { ++ if (true) { let dragOverGroupingThreshold = 1 - moveOverThreshold; // When dragging tab(s) over an ungrouped tab, signal to the user -@@ -2639,7 +2686,7 @@ + // that dropping the tab(s) will create a new tab group. +- shouldCreateGroupOnDrop = ++ shouldCreateGroupOnDrop = false && + dropElement != draggedTab && + isTab(dropElement) && + !dropElement?.group && +@@ -2639,7 +2689,7 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let item of tabs) { @@ -456,9 +483,13 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb continue; } -@@ -2649,7 +2696,11 @@ +@@ -2648,8 +2698,15 @@ + if (isTabGroupLabel(item)) { // Shift the `.tab-group-label-container` to shift the label element. item = item.parentElement; ++ if (item.parentElement?.hasAttribute("split-view-group")) { ++ item = item.parentElement; ++ } } + if (item.group?.hasAttribute("split-view-group")) { + item.group.style.transform = transform; @@ -468,7 +499,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb } } -@@ -2697,8 +2748,9 @@ +@@ -2697,8 +2754,9 @@ ); } @@ -480,15 +511,20 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb return; } -@@ -2711,6 +2763,7 @@ +@@ -2711,6 +2769,12 @@ item = item.parentElement; } item.style.transform = ""; -+ if (item.group?.hasAttribute("split-view-group")) item.group.style.transform = ""; ++ if (item.closest("tab-group")?.hasAttribute("split-view-group")) item.closest("tab-group").style.transform = ""; ++ if (item.closest("tab-group")?.hasAttribute("split-view-group")) { ++ for (let tab of item.closest("tab-group").tabs) { ++ tab.style.transform = ""; ++ } ++ } item.removeAttribute("dragover-createGroup"); } this.removeAttribute("movingtab-createGroup"); -@@ -2754,7 +2807,7 @@ +@@ -2754,7 +2818,7 @@ let postTransitionCleanup = () => { movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -497,7 +533,7 @@ index 0fbdbf3aefc467880e6b0bae2615cb145735cb0f..0f809f610f78f672716b9af66ddf3cfb postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2924,7 +2977,7 @@ +@@ -2924,7 +2988,7 @@ } _notifyBackgroundTab(aTab) {