From b3d981c585252efcbe3acee28e1f36736db38e0b Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 11:45:50 +0200 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20Lazy=20load=20database=20for=20omni?= =?UTF-8?q?box=20results=C3=A7,=20b=3Dno-bug,=20c=3Dno-component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/zen/urlbar/ZenUBResultsLearner.sys.mjs | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/zen/urlbar/ZenUBResultsLearner.sys.mjs b/src/zen/urlbar/ZenUBResultsLearner.sys.mjs index 99165f85f..6df19367d 100644 --- a/src/zen/urlbar/ZenUBResultsLearner.sys.mjs +++ b/src/zen/urlbar/ZenUBResultsLearner.sys.mjs @@ -10,11 +10,22 @@ const DEFAULT_DB_DATA = '{}'; const DEPRIORITIZE_MAX = -4; const PRIORITIZE_MAX = 5; +function addDataToLazy(data) { + try { + lazy.databaseData = JSON.parse(data); + } catch { + lazy.databaseData = {}; + } +} + XPCOMUtils.defineLazyPreferenceGetter( lazy, - 'database', + 'rawDatabase', 'zen.urlbar.suggestions-learner', - 'DEFAULT_DB_DATA' + DEFAULT_DB_DATA, + (_aPreference, _previousValue, newValue) => { + addDataToLazy(newValue); + } ); /** @@ -33,14 +44,12 @@ XPCOMUtils.defineLazyPreferenceGetter( * The priority number is incremented each time the command is executed. */ class ZenUrlbarResultsLearner { - constructor() {} + constructor() { + addDataToLazy(lazy.rawDatabase); + } get database() { - try { - return JSON.parse(lazy.database); - } catch { - return {}; - } + return lazy.databaseData; } saveDatabase(db) { From bb33bbcc39819216187f06d4c0f4e93b931bf906 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 12:02:47 +0200 Subject: [PATCH 2/6] fix: Fixed essentials being ignored when closing tabs, b=closes #6968, c=workspaces --- .../tabbrowser/content/tabbrowser-js.patch | 106 ++++++------------ src/zen/workspaces/ZenWorkspaces.mjs | 7 +- 2 files changed, 39 insertions(+), 74 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 5b1277a5f..6494a3137 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c1ee4358d 100644 +index 3204f253c23551650991d3385dd256d55892a012..7c30015ac4591fdb97426521ae87b80ed9d2317a 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -427,15 +427,64 @@ @@ -128,22 +128,6 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1249,13 +1312,13 @@ - let oldTab = this.selectedTab; - - // Preview mode should not reset the owner -- if (!this._previewMode && !oldTab.selected) { -+ if (!this._previewMode && !oldTab.selected && oldTab.owner && !oldTab.hasAttribute("zen-essential")) { - oldTab.owner = null; - } - - let lastRelatedTab = this._lastRelatedTabMap.get(oldTab); - if (lastRelatedTab) { -- if (!lastRelatedTab.selected) { -+ if (!lastRelatedTab.selected && lastRelatedTab.owner && !lastRelatedTab.hasAttribute("zen-essential")) { - lastRelatedTab.owner = null; - } - } @@ -1333,6 +1396,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); @@ -249,15 +233,6 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (!UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.start("browser.tabs.opening", "initting", window); } -@@ -2752,7 +2827,7 @@ - ownerTab ??= inBackground ? null : this.selectedTab; - - // if we're adding tabs, we're past interrupt mode, ditch the owner -- if (this.selectedTab.owner) { -+ if (this.selectedTab.owner && !this.selectedTab.hasAttribute("zen-essential")) { - this.selectedTab.owner = null; - } - @@ -2807,6 +2882,19 @@ noInitialLabel, skipBackgroundNotify, @@ -453,7 +428,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c tabGroup = previousTab.group; } if ( -@@ -3975,13 +4101,15 @@ +@@ -3975,7 +4101,7 @@ ) { elementIndex = Infinity; } else if (previousTab.visible) { @@ -462,16 +437,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } else if (previousTab == FirefoxViewHandler.tab) { elementIndex = 0; } - - if (lastRelatedTab) { -- lastRelatedTab.owner = null; -+ if (!lastRelatedTab.hasAttribute("zen-essential")) { -+ lastRelatedTab.owner = null; -+ } - } else if (openerTab) { - tab.owner = openerTab; - } -@@ -4003,14 +4131,14 @@ +@@ -4003,14 +4129,14 @@ } // Ensure index is within bounds. if (tab.pinned) { @@ -490,7 +456,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (pinned && !itemAfter?.pinned) { itemAfter = null; -@@ -4021,7 +4149,7 @@ +@@ -4021,7 +4147,7 @@ this.tabContainer._invalidateCachedTabs(); @@ -499,7 +465,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (this.isTab(itemAfter) && itemAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, itemAfter); -@@ -4057,6 +4185,7 @@ +@@ -4057,6 +4183,7 @@ if (pinned) { this._updateTabBarForPinnedTabs(); } @@ -507,7 +473,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c TabBarVisibility.update(); } -@@ -4346,6 +4475,9 @@ +@@ -4346,6 +4473,9 @@ return; } @@ -517,7 +483,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource }); } -@@ -4607,6 +4739,7 @@ +@@ -4607,6 +4737,7 @@ telemetrySource, } = {} ) { @@ -525,7 +491,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c // When 'closeWindowWithLastTab' pref is enabled, closing all tabs // can be considered equivalent to closing the window. if ( -@@ -4696,6 +4829,7 @@ +@@ -4696,6 +4827,7 @@ if (lastToClose) { this.removeTab(lastToClose, aParams); } @@ -533,7 +499,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } catch (e) { console.error(e); } -@@ -4734,6 +4868,12 @@ +@@ -4734,6 +4866,12 @@ aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); } @@ -546,7 +512,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4748,6 +4888,9 @@ +@@ -4748,6 +4886,9 @@ // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let isLastTab = this.#isLastTabInWindow(aTab); @@ -556,7 +522,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4796,7 +4939,13 @@ +@@ -4796,7 +4937,13 @@ // We're not animating, so we can cancel the animation stopwatch. Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId); aTab._closeTimeAnimTimerId = null; @@ -571,7 +537,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c return; } -@@ -4930,7 +5079,7 @@ +@@ -4930,7 +5077,7 @@ closeWindowWithLastTab != null ? closeWindowWithLastTab : !window.toolbar.visible || @@ -580,7 +546,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4954,6 +5103,7 @@ +@@ -4954,6 +5101,7 @@ newTab = true; } @@ -588,7 +554,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4994,13 +5144,7 @@ +@@ -4994,13 +5142,7 @@ aTab._mouseleave(); if (newTab) { @@ -603,7 +569,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } else { TabBarVisibility.update(); } -@@ -5133,6 +5277,7 @@ +@@ -5133,6 +5275,7 @@ this.tabs[i]._tPos = i; } @@ -611,7 +577,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (!this._windowIsClosing) { // update tab close buttons state this.tabContainer._updateCloseButtons(); -@@ -5345,6 +5490,7 @@ +@@ -5345,6 +5488,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -619,7 +585,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5357,13 +5503,13 @@ +@@ -5357,13 +5501,13 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -635,7 +601,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c ); let tab = this.tabContainer.findNextTab(aTab, { -@@ -5379,7 +5525,7 @@ +@@ -5379,7 +5523,7 @@ } if (tab) { @@ -644,7 +610,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } // If no qualifying visible tab was found, see if there is a tab in -@@ -5400,7 +5546,7 @@ +@@ -5400,7 +5544,7 @@ }); } @@ -653,7 +619,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } _blurTab(aTab) { -@@ -5802,10 +5948,10 @@ +@@ -5802,10 +5946,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -666,7 +632,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5864,6 +6010,7 @@ +@@ -5864,6 +6008,7 @@ * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab */ replaceTabWithWindow(aTab, aOptions) { @@ -674,7 +640,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (this.tabs.length == 1) { return null; } -@@ -5997,7 +6144,7 @@ +@@ -5997,7 +6142,7 @@ * `true` if element is a `` */ isTabGroup(element) { @@ -683,7 +649,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } /** -@@ -6073,8 +6220,8 @@ +@@ -6073,8 +6218,8 @@ } // Don't allow mixing pinned and unpinned tabs. @@ -694,7 +660,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6100,10 +6247,16 @@ +@@ -6100,10 +6245,16 @@ this.#handleTabMove( element, () => { @@ -713,7 +679,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6161,23 +6314,28 @@ +@@ -6161,23 +6312,28 @@ #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) { if (this.isTabGroupLabel(targetElement)) { targetElement = targetElement.group; @@ -748,7 +714,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } else if (!element.pinned && targetElement && targetElement.pinned) { // If the caller asks to move an unpinned element next to a pinned // tab, move the unpinned element to be the first unpinned element -@@ -6190,14 +6348,34 @@ +@@ -6190,14 +6346,34 @@ // move the tab group right before the first unpinned tab. // 4. Moving a tab group and the first unpinned tab is grouped: // move the tab group right before the first unpinned tab's tab group. @@ -784,7 +750,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c element.pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; -@@ -6206,7 +6384,7 @@ +@@ -6206,7 +6382,7 @@ element, () => { if (moveBefore) { @@ -793,7 +759,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c } else if (targetElement) { targetElement.after(element); } else { -@@ -6252,10 +6430,10 @@ +@@ -6252,10 +6428,10 @@ * @param {TabMetricsContext} [metricsContext] */ moveTabToGroup(aTab, aGroup, metricsContext) { @@ -806,7 +772,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6285,6 +6463,7 @@ +@@ -6285,6 +6461,7 @@ let state = { tabIndex: tab._tPos, @@ -814,7 +780,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c }; if (tab.visible) { state.elementIndex = tab.elementIndex; -@@ -6311,7 +6490,7 @@ +@@ -6311,7 +6488,7 @@ let changedTabGroup = previousTabState.tabGroupId != currentTabState.tabGroupId; @@ -823,7 +789,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c tab.dispatchEvent( new CustomEvent("TabMove", { bubbles: true, -@@ -6348,6 +6527,10 @@ +@@ -6348,6 +6525,10 @@ moveActionCallback(); @@ -834,7 +800,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -7249,7 +7432,7 @@ +@@ -7249,7 +7430,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -843,7 +809,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c window.focus(); aEvent.preventDefault(); break; -@@ -7264,7 +7447,6 @@ +@@ -7264,7 +7445,6 @@ } case "TabGroupCollapse": aEvent.target.tabs.forEach(tab => { @@ -851,7 +817,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c }); break; case "TabGroupCreateByUser": -@@ -8199,6 +8381,7 @@ +@@ -8199,6 +8379,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -859,7 +825,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -9200,7 +9383,7 @@ var TabContextMenu = { +@@ -9200,7 +9381,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected; @@ -868,7 +834,7 @@ index 3204f253c23551650991d3385dd256d55892a012..792e54079e9f82013617306243fe313c // Build Ask Chat items TabContextMenu.GenAI.buildTabMenu( document.getElementById("context_askChat"), -@@ -9520,6 +9703,7 @@ var TabContextMenu = { +@@ -9520,6 +9701,7 @@ var TabContextMenu = { ) ); } else { diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index 3bfece219..f76daecb5 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -1495,6 +1495,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { continue; } + tab.owner = null; if (container) { if (tab.group?.hasAttribute('split-view-group')) { gBrowser.zenHandleTabMove(tab.group, () => { @@ -2751,14 +2752,12 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { getTabsToExclude(aTab) { const tabWorkspaceId = aTab.getAttribute('zen-workspace-id'); + const containerId = aTab.getAttribute('usercontextid') ?? '0'; // Return all tabs that are not on the same workspace return this.allStoredTabs.filter( (tab) => tab.getAttribute('zen-workspace-id') !== tabWorkspaceId && - !( - this.containerSpecificEssentials && - tab.getAttribute('container') !== aTab.getAttribute('container') - ) && + !this._shouldShowTab(tab, tabWorkspaceId, containerId, this._workspaceCache) && !tab.hasAttribute('zen-empty-tab') ); } From 528f3d6a0b1157f0b749a70e027793e197c98007 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 12:53:41 +0200 Subject: [PATCH 3/6] fix: Fixed cancelling drag mid-split, b=closes #10554, c=tabs, split-view --- .../tabbrowser/content/tabs-js.patch | 71 ++++++++++--------- src/zen/split-view/ZenViewSplitter.mjs | 17 ++--- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index f168b3737..3f0fd1ff9 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 c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd0698e189659 100644 +index c7557dad38db9ef02b981c46de9595df77cb67db..f45ecacd23179f06a436d5f3d372b536322388ea 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -44,6 +44,9 @@ @@ -157,7 +157,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 gBrowser.loadTabs(urls, { inBackground, replace, -@@ -1541,6 +1568,16 @@ +@@ -1541,6 +1568,17 @@ } this.#resetTabsAfterDrop(draggedTab.ownerDocument); @@ -168,13 +168,14 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 + return; + } + } else if (dt.mozUserCancelled) { ++ gZenViewSplitter.onBrowserDragEndToSplit(event, true); + if (gZenViewSplitter._lastOpenedTab) gZenViewSplitter._lastOpenedTab._visuallySelected = false; + } + if ( dt.mozUserCancelled || dt.dropEffect != "none" || -@@ -1707,7 +1744,6 @@ +@@ -1707,7 +1745,6 @@ this.toggleAttribute("overflow", true); this._updateCloseButtons(); @@ -182,7 +183,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 document .getElementById("tab-preview-panel") -@@ -1765,7 +1801,7 @@ +@@ -1765,7 +1802,7 @@ } get newTabButton() { @@ -191,7 +192,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } get verticalMode() { -@@ -1781,6 +1817,7 @@ +@@ -1781,6 +1818,7 @@ } get overflowing() { @@ -199,7 +200,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 return this.hasAttribute("overflow"); } -@@ -1789,31 +1826,51 @@ +@@ -1789,31 +1827,51 @@ if (this.#allTabs) { return this.#allTabs; } @@ -267,7 +268,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } /** -@@ -1880,29 +1937,23 @@ +@@ -1880,29 +1938,23 @@ let elementIndex = 0; @@ -306,7 +307,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } } -@@ -1914,6 +1965,7 @@ +@@ -1914,6 +1966,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -314,7 +315,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } _invalidateCachedVisibleTabs() { -@@ -1929,8 +1981,8 @@ +@@ -1929,8 +1982,8 @@ #isContainerVerticalPinnedGrid(tab) { return ( this.verticalMode && @@ -325,7 +326,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 !this.expandOnHover ); } -@@ -1946,7 +1998,7 @@ +@@ -1946,7 +1999,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -334,7 +335,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } node.before(tab); -@@ -2041,7 +2093,7 @@ +@@ -2041,7 +2094,7 @@ // 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); // Attach the long click popup to all of them. @@ -343,7 +344,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -2139,8 +2191,10 @@ +@@ -2139,8 +2192,10 @@ */ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -354,7 +355,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 selectedTab._notselectedsinceload = false; } -@@ -2149,7 +2203,7 @@ +@@ -2149,7 +2204,7 @@ * @param {boolean} [shouldScrollInstantly=false] */ #ensureTabIsVisible(tab, shouldScrollInstantly = false) { @@ -363,7 +364,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 if (arrowScrollbox.overflowing) { arrowScrollbox.ensureElementIsVisible(tab, shouldScrollInstantly); } -@@ -2288,6 +2342,16 @@ +@@ -2288,6 +2343,16 @@ when the tab is first selected to be dragged. */ #updateTabStylesOnDrag(tab) { @@ -380,7 +381,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let isPinned = tab.pinned; let numPinned = gBrowser.pinnedTabCount; let allTabs = this.ariaFocusableItems; -@@ -2540,7 +2604,7 @@ +@@ -2540,7 +2605,7 @@ return; } @@ -389,7 +390,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2549,6 +2613,8 @@ +@@ -2549,6 +2614,8 @@ let { width: tabWidth, height: tabHeight } = draggedTab.getBoundingClientRect(); @@ -398,7 +399,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2585,8 +2651,8 @@ +@@ -2585,8 +2652,8 @@ let lastBoundX = lastTabInRow.screenX + lastTabInRow.getBoundingClientRect().width - @@ -409,7 +410,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 translateX = Math.min(Math.max(translateX, firstBoundX), lastBoundX); translateY = Math.min(Math.max(translateY, firstBoundY), lastBoundY); -@@ -2743,13 +2809,18 @@ +@@ -2743,13 +2810,18 @@ this.#clearDragOverGroupingTimer(); @@ -432,7 +433,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 if (this.#rtlMode) { tabs.reverse(); -@@ -2760,7 +2831,7 @@ +@@ -2760,7 +2832,7 @@ let screenAxis = this.verticalMode ? "screenY" : "screenX"; let size = this.verticalMode ? "height" : "width"; let translateAxis = this.verticalMode ? "translateY" : "translateX"; @@ -441,7 +442,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let tabSize = this.verticalMode ? tabHeight : tabWidth; let translateX = event.screenX - dragData.screenX; let translateY = event.screenY - dragData.screenY; -@@ -2776,6 +2847,12 @@ +@@ -2776,6 +2848,12 @@ ); let lastMovingTab = movingTabs.at(-1); let firstMovingTab = movingTabs[0]; @@ -454,7 +455,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let endEdge = ele => ele[screenAxis] + bounds(ele)[size]; let lastMovingTabScreen = endEdge(lastMovingTab); let firstMovingTabScreen = firstMovingTab[screenAxis]; -@@ -2790,6 +2867,11 @@ +@@ -2790,6 +2868,11 @@ let endBound = this.#rtlMode ? endEdge(this) - lastMovingTabScreen : periphery[screenAxis] - 1 - lastMovingTabScreen; @@ -466,7 +467,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 translate = Math.min(Math.max(translate, startBound), endBound); // Center the tab under the cursor if the tab is not under the cursor while dragging -@@ -2979,6 +3061,8 @@ +@@ -2979,6 +3062,8 @@ }; let dropElement = getOverlappedElement(); @@ -475,7 +476,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let newDropElementIndex; if (dropElement) { -@@ -3060,7 +3144,7 @@ +@@ -3060,7 +3145,7 @@ ? Services.prefs.getIntPref( "browser.tabs.dragDrop.moveOverThresholdPercent" ) / 100 @@ -484,7 +485,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 moveOverThreshold = Math.min(1, Math.max(0, moveOverThreshold)); let shouldMoveOver = overlapPercent > moveOverThreshold; if (logicalForward && shouldMoveOver) { -@@ -3093,6 +3177,7 @@ +@@ -3093,6 +3178,7 @@ // If dragging a group over another group, don't make it look like it is // possible to drop the dragged group inside the other group. if ( @@ -492,7 +493,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 isTabGroupLabel(draggedTab) && dropElement?.group && (!dropElement.group.collapsed || -@@ -3119,20 +3204,13 @@ +@@ -3119,20 +3205,13 @@ let isOutOfBounds = isPinned ? dropElement.elementIndex >= numPinned : dropElement.elementIndex < numPinned; @@ -517,7 +518,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 let groupingDelay = Services.prefs.getIntPref( "browser.tabs.dragDrop.createGroup.delayMS" ); -@@ -3140,6 +3218,7 @@ +@@ -3140,6 +3219,7 @@ // When dragging tab(s) over an ungrouped tab, signal to the user // that dropping the tab(s) will create a new tab group. let shouldCreateGroupOnDrop = @@ -525,7 +526,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 !movingTabsSet.has(dropElement) && isTab(dropElement) && !dropElement?.group && -@@ -3148,6 +3227,7 @@ +@@ -3148,6 +3228,7 @@ // When dragging tab(s) over a collapsed tab group label, signal to the // user that dropping the tab(s) will add them to the group. let shouldDropIntoCollapsedTabGroup = @@ -533,7 +534,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 isTabGroupLabel(dropElement) && dropElement.group.collapsed && overlapPercent > dragOverGroupingThreshold; -@@ -3192,19 +3272,14 @@ +@@ -3192,19 +3273,14 @@ dropElement = dropElementGroup; colorCode = undefined; } else if (isTabGroupLabel(dropElement)) { @@ -561,7 +562,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } this.#setDragOverGroupColor(colorCode); this.toggleAttribute("movingtab-addToGroup", colorCode); -@@ -3223,11 +3298,11 @@ +@@ -3223,11 +3299,11 @@ dragData.dropElement = dropElement; dragData.dropBefore = dropBefore; dragData.animDropElementIndex = newDropElementIndex; @@ -575,7 +576,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 continue; } -@@ -3346,12 +3421,14 @@ +@@ -3346,12 +3422,14 @@ element?.removeAttribute("dragover-groupTarget"); } @@ -592,7 +593,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 for (let item of this.ariaFocusableItems) { this.#resetGroupTarget(item); -@@ -3394,16 +3471,15 @@ +@@ -3394,16 +3472,15 @@ tab.style.left = ""; tab.style.top = ""; tab.style.maxWidth = ""; @@ -611,7 +612,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 } let periphery = draggedTabDocument.getElementById( "tabbrowser-arrowscrollbox-periphery" -@@ -3475,7 +3551,7 @@ +@@ -3475,7 +3552,7 @@ let postTransitionCleanup = () => { movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -620,7 +621,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -3639,7 +3715,7 @@ +@@ -3639,7 +3716,7 @@ } _notifyBackgroundTab(aTab) { @@ -629,7 +630,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 return; } -@@ -3748,7 +3824,10 @@ +@@ -3748,7 +3825,10 @@ #getDragTarget(event, { ignoreSides = false } = {}) { let { target } = event; while (target) { @@ -641,7 +642,7 @@ index c7557dad38db9ef02b981c46de9595df77cb67db..4192dc797d5f07ece57e7e9ecb0cd069 break; } target = target.parentNode; -@@ -3765,6 +3844,9 @@ +@@ -3765,6 +3845,9 @@ return null; } } diff --git a/src/zen/split-view/ZenViewSplitter.mjs b/src/zen/split-view/ZenViewSplitter.mjs index f80455bb6..2dd3c6424 100644 --- a/src/zen/split-view/ZenViewSplitter.mjs +++ b/src/zen/split-view/ZenViewSplitter.mjs @@ -380,20 +380,21 @@ class nsZenViewSplitter extends nsZenDOMOperatedFeature { } } - onBrowserDragEndToSplit(event) { + onBrowserDragEndToSplit(event, cancelled = false) { if (!this._canDrop) { return; } const panelsRect = gBrowser.tabbox.getBoundingClientRect(); const fakeBrowserRect = this.fakeBrowser && this.fakeBrowser.getBoundingClientRect(); if ( - (event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) || - (fakeBrowserRect && - event.clientX > fakeBrowserRect.left && - event.clientX < fakeBrowserRect.left + fakeBrowserRect.width && - event.clientY > fakeBrowserRect.top && - event.clientY < fakeBrowserRect.top + fakeBrowserRect.height) || - (event.screenX === 0 && event.screenY === 0) // It's equivalent to 0 if the event has been dropped + ((event.target.closest('#tabbrowser-tabbox') && event.target != this.fakeBrowser) || + (fakeBrowserRect && + event.clientX > fakeBrowserRect.left && + event.clientX < fakeBrowserRect.left + fakeBrowserRect.width && + event.clientY > fakeBrowserRect.top && + event.clientY < fakeBrowserRect.top + fakeBrowserRect.height) || + (event.screenX === 0 && event.screenY === 0)) && // It's equivalent to 0 if the event has been dropped + !cancelled ) { return; } From 8c6c13573b4c7122abd051dbf923196c798ef4a9 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 13:14:03 +0200 Subject: [PATCH 4/6] fix: Fixed essentials reordering on every restart, b=bug #10309, c=tabs, workspaces --- .../sessionstore/SessionStore-sys-mjs.patch | 48 ++++++++++++------ src/zen/tabs/ZenPinnedTabManager.mjs | 50 +++++++++++++------ src/zen/workspaces/ZenWorkspaces.mjs | 25 +++++----- 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch index af429e2ed..08585dd50 100644 --- a/src/browser/components/sessionstore/SessionStore-sys-mjs.patch +++ b/src/browser/components/sessionstore/SessionStore-sys-mjs.patch @@ -1,8 +1,26 @@ diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs -index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f79bdefd9e 100644 +index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..cf13724d147c8b8fc35c76d7f77601eb1077ea5c 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs -@@ -2133,7 +2133,6 @@ var SessionStoreInternal = { +@@ -126,6 +126,8 @@ const TAB_EVENTS = [ + "TabUngrouped", + "TabGroupCollapse", + "TabGroupExpand", ++ "TabAddedToEssentials", ++ "TabRemovedFromEssentials", + ]; + + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; +@@ -1898,6 +1900,8 @@ var SessionStoreInternal = { + case "TabPinned": + case "TabUnpinned": + case "SwapDocShells": ++ case "TabRemovedFromEssentials": ++ case "TabAddedToEssentials": + this.saveStateDelayed(win); + break; + case "TabGroupCreate": +@@ -2133,7 +2137,6 @@ var SessionStoreInternal = { if (closedWindowState) { let newWindowState; if ( @@ -10,7 +28,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 !lazy.SessionStartup.willRestore() ) { // We want to split the window up into pinned tabs and unpinned tabs. -@@ -2366,11 +2365,9 @@ var SessionStoreInternal = { +@@ -2366,11 +2369,9 @@ var SessionStoreInternal = { tabbrowser.selectedTab.label; } @@ -22,7 +40,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 // Store the window's close date to figure out when each individual tab // was closed. This timestamp should allow re-arranging data based on how -@@ -3355,7 +3352,7 @@ var SessionStoreInternal = { +@@ -3355,7 +3356,7 @@ var SessionStoreInternal = { if (!isPrivateWindow && tabState.isPrivate) { return; } @@ -31,7 +49,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 return; } -@@ -4067,6 +4064,11 @@ var SessionStoreInternal = { +@@ -4067,6 +4068,11 @@ var SessionStoreInternal = { Math.min(tabState.index, tabState.entries.length) ); tabState.pinned = false; @@ -43,7 +61,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 if (inBackground === false) { aWindow.gBrowser.selectedTab = newTab; -@@ -4503,6 +4505,7 @@ var SessionStoreInternal = { +@@ -4503,6 +4509,7 @@ var SessionStoreInternal = { // Append the tab if we're opening into a different window, tabIndex: aSource == aTargetWindow ? pos : Infinity, pinned: state.pinned, @@ -51,7 +69,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 userContextId: state.userContextId, skipLoad: true, preferredRemoteType, -@@ -5358,7 +5361,7 @@ var SessionStoreInternal = { +@@ -5358,7 +5365,7 @@ var SessionStoreInternal = { for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) { let tab = tabbrowser.tabs[i]; @@ -60,7 +78,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 removableTabs.push(tab); } } -@@ -5418,7 +5421,7 @@ var SessionStoreInternal = { +@@ -5418,7 +5425,7 @@ var SessionStoreInternal = { } let workspaceID = aWindow.getWorkspaceID(); @@ -69,7 +87,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 winData.workspaceID = workspaceID; } }, -@@ -5609,11 +5612,12 @@ var SessionStoreInternal = { +@@ -5609,11 +5616,12 @@ var SessionStoreInternal = { } let tabbrowser = aWindow.gBrowser; @@ -83,7 +101,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 // update the internal state data for this window for (let tab of tabs) { if (tab == aWindow.FirefoxViewHandler.tab) { -@@ -5624,6 +5628,7 @@ var SessionStoreInternal = { +@@ -5624,6 +5632,7 @@ var SessionStoreInternal = { tabsData.push(tabData); } @@ -91,7 +109,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 // update tab group state for this window winData.groups = []; for (let tabGroup of aWindow.gBrowser.tabGroups) { -@@ -5636,7 +5641,7 @@ var SessionStoreInternal = { +@@ -5636,7 +5645,7 @@ var SessionStoreInternal = { // 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). if (aWindow.FirefoxViewHandler.tab?.selected) { @@ -100,7 +118,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 winData.title = tabbrowser.tabs[0].label; } winData.selected = selectedIndex; -@@ -5748,8 +5753,8 @@ var SessionStoreInternal = { +@@ -5748,8 +5757,8 @@ var SessionStoreInternal = { // selectTab represents. let selectTab = 0; if (overwriteTabs) { @@ -111,7 +129,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 selectTab = Math.min(selectTab, winData.tabs.length); } -@@ -5792,6 +5797,8 @@ var SessionStoreInternal = { +@@ -5792,6 +5801,8 @@ var SessionStoreInternal = { winData.tabs, winData.groups ?? [] ); @@ -120,7 +138,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 this._log.debug( `restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs` ); -@@ -6349,6 +6356,25 @@ var SessionStoreInternal = { +@@ -6349,6 +6360,25 @@ var SessionStoreInternal = { // Most of tabData has been restored, now continue with restoring // attributes that may trigger external events. @@ -146,7 +164,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7 if (tabData.pinned) { tabbrowser.pinTab(tab); -@@ -7264,7 +7290,7 @@ var SessionStoreInternal = { +@@ -7264,7 +7294,7 @@ var SessionStoreInternal = { let groupsToSave = new Map(); for (let tIndex = 0; tIndex < window.tabs.length; ) { diff --git a/src/zen/tabs/ZenPinnedTabManager.mjs b/src/zen/tabs/ZenPinnedTabManager.mjs index 6478041bf..f6e7b44f5 100644 --- a/src/zen/tabs/ZenPinnedTabManager.mjs +++ b/src/zen/tabs/ZenPinnedTabManager.mjs @@ -19,6 +19,8 @@ 'TabGrouped', 'TabUngrouped', 'ZenFolderChangedWorkspace', + 'TabAddedToEssentials', + 'TabRemovedFromEssentials', ]; #listeners = []; @@ -396,12 +398,23 @@ _onPinnedTabEvent(action, event) { if (!this.enabled) return; const tab = event.target; + if (this._ignoreNextTabPinnedEvent) { + delete this._ignoreNextTabPinnedEvent; + return; + } switch (action) { case 'TabPinned': + case 'TabAddedToEssentials': tab._zenClickEventListener = this._zenClickEventListener; tab.addEventListener('click', tab._zenClickEventListener); this._setPinnedAttributes(tab); break; + case 'TabRemovedFromEssentials': + if (tab.pinned) { + this.#onTabMove(tab); + break; + } + // [Fall through] case 'TabUnpinned': this._removePinnedAttributes(tab); if (tab._zenClickEventListener) { @@ -957,30 +970,33 @@ const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); if (pin) { pin.isEssential = true; + pin.workspaceUuid = null; this.savePin(pin); } - if (tab.ownerGlobal !== window) { - tab = gBrowser.adoptTab(tab, { - selectTab: tab.selected, - }); - tab.setAttribute('zen-essential', 'true'); - } else { - section.appendChild(tab); - } - gBrowser.tabContainer._invalidateCachedTabs(); + gBrowser.zenHandleTabMove(tab, () => { + if (tab.ownerGlobal !== window) { + tab = gBrowser.adoptTab(tab, { + selectTab: tab.selected, + }); + tab.setAttribute('zen-essential', 'true'); + } else { + section.appendChild(tab); + } + }); } else { gBrowser.pinTab(tab); + this._ignoreNextTabPinnedEvent = true; } tab.setAttribute('zenDefaultUserContextId', true); if (tab.selected) { gZenWorkspaces.switchTabIfNeeded(tab); } - this.#onTabMove(tab); this.onTabIconChanged(tab); - // Dispatch the event to update the UI const event = new CustomEvent('TabAddedToEssentials', { detail: { tab }, + bubbles: true, + cancelable: false, }); tab.dispatchEvent(event); } @@ -1003,15 +1019,16 @@ if (unpin) { gBrowser.unpinTab(tab); } else { - const pinContainer = gZenWorkspaces.pinnedTabsContainer; - pinContainer.prepend(tab); - gBrowser.tabContainer._invalidateCachedTabs(); - this.#onTabMove(tab); + gBrowser.zenHandleTabMove(tab, () => { + const pinContainer = gZenWorkspaces.pinnedTabsContainer; + pinContainer.prepend(tab); + }); } - // Dispatch the event to update the UI const event = new CustomEvent('TabRemovedFromEssentials', { detail: { tab }, + bubbles: true, + cancelable: false, }); tab.dispatchEvent(event); } @@ -1068,6 +1085,7 @@ document .getElementById('cmd_contextZenAddToEssentials') .setAttribute('disabled', !this.canEssentialBeAdded(contextTab)); + document.getElementById('context_closeTab').hidden = contextTab.hasAttribute('zen-essential'); document.getElementById('context_zen-remove-essential').hidden = !contextTab.getAttribute('zen-essential'); document.getElementById('zen-context-menu-new-folder').hidden = diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index f76daecb5..ea881aeff 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -510,7 +510,9 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { #organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) { const workspaceTabs = Array.from(tabs).filter( - (tab) => tab.getAttribute('zen-workspace-id') === workspace.uuid + (tab) => + tab.getAttribute('zen-workspace-id') === workspace.uuid && + !tab.hasAttribute('zen-essential') ); let folders = new Set(); const getFolderRoot = (tab) => { @@ -2387,7 +2389,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { // get extra tabs remaning (e.g. on new profiles) and just move them to the new workspace const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter( (child) => - child.tagName === 'tab' && + gBrowser.isTab(child) && !child.hasAttribute('zen-workspace-id') && !child.hasAttribute('zen-empty-tab') && !child.hasAttribute('zen-essential') @@ -2812,7 +2814,12 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { pinnedContainers = [document.getElementById('pinned-tabs-container')]; normalContainers = [this.activeWorkspaceStrip]; } else { - for (const workspace of this._workspaceCache.workspaces) { + let workspaces = Array.from(this._workspaceCache?.workspaces || []); + // Make the active workspace first + workspaces = workspaces.sort((a, b) => + a.uuid === this.activeWorkspace ? -1 : b.uuid === this.activeWorkspace ? 1 : 0 + ); + for (const workspace of workspaces) { const container = this.workspaceElement(workspace.uuid); if (container) { pinnedContainers.push(container.pinnedTabsContainer); @@ -2826,7 +2833,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { continue; } for (const tab of container.children) { - if (tab.tagName === 'tab') { + if (gBrowser.isTab(tab)) { tabs.push(tab); const glance = tab.querySelector('.tabbrowser-tab[glance-id]'); if (glance) { @@ -2843,13 +2850,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { } } } - const currentWorkspace = this.activeWorkspace; - this._allStoredTabs = tabs.sort((a, b) => { - const aWorkspaceId = a.getAttribute('zen-workspace-id'); - const bWorkspaceId = b.getAttribute('zen-workspace-id'); - return aWorkspaceId === currentWorkspace ? -1 : bWorkspaceId === currentWorkspace ? 1 : 0; - }); - return this._allStoredTabs; + return (this._allStoredTabs = tabs); } get allTabGroups() { @@ -2908,7 +2909,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature { reorganizeTabsAfterWelcome() { const children = gBrowser.tabContainer.arrowScrollbox.children; - const remainingTabs = Array.from(children).filter((child) => child.tagName === 'tab'); + const remainingTabs = Array.from(children).filter((child) => gBrowser.isTab(child)); for (const tab of remainingTabs) { this.moveTabToWorkspace(tab, this.activeWorkspace); } From 31f6b2ab121efe65359a8e5934db34fff0013066 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 14:07:20 +0200 Subject: [PATCH 5/6] chore: Disabled crashreporter, b=closes #10560, c=common, configs --- configs/common/mozconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/common/mozconfig b/configs/common/mozconfig index d4c149fe1..952c6c67b 100644 --- a/configs/common/mozconfig +++ b/configs/common/mozconfig @@ -92,7 +92,7 @@ if test "$ZEN_RELEASE"; then ac_add_options --enable-js-shell export MOZ_PACKAGE_JSSHELL=1 -else + ac_add_options --disable-crashreporter fi From 3d83fed14f4f35f27f3dabae9ed89f57161cd58e Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sat, 27 Sep 2025 14:37:08 +0200 Subject: [PATCH 6/6] fix: Fixed aligment issues with new workspace icons, b=no-bug, c=workspaces --- src/zen/workspaces/zen-workspaces.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/zen/workspaces/zen-workspaces.css b/src/zen/workspaces/zen-workspaces.css index de6354db7..a37da3d66 100644 --- a/src/zen/workspaces/zen-workspaces.css +++ b/src/zen/workspaces/zen-workspaces.css @@ -43,13 +43,16 @@ fill-opacity: 0.6; & .zen-workspace-icon { - padding: 6px; pointer-events: none; + line-height: 0; + + &:is(img) { + padding: 6px; + } &[no-icon='true'] { width: 6px; height: 6px; - padding: 0; background: light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)); border-radius: 50%; }