diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index ceced730d..e2c5d4927 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -632,28 +632,11 @@ var gZenVerticalTabsManager = { _insertDoubleClickListenerPinnedTabs() { const tabs = gBrowser.tabs; for (const tab of tabs) { - tab.addEventListener('dblclick', this.contextRenameTabStart.bind(this)); - tab.renamedName = null; - tab.originalName = null; - - // Persist tab label and store changes for resetting - let observer = new MutationObserver((mutations) => { - if (!tab.renamedName) { - return; - } - mutations.forEach((mutation) => { - if (tab.label !== tab.renamedName) { - tab.originalName = tab.label; - tab.label = tab.renamedName; - } - }); - }); - // Run on all changes of label - observer.observe(tab, { attributes: true, attributeFilter: ['label'] }); + tab.addEventListener('dblclick', this.renameTabStart.bind(this)); } }, - contextRenameTabKeydown(event) { + renameTabKeydown(event) { if (event.key === 'Enter') { let label = this._tabEdited.querySelector('.tab-label-container-editing'); let input = this._tabEdited.querySelector('#tab-label-input'); @@ -661,19 +644,21 @@ var gZenVerticalTabsManager = { // Check if name is blank, reset if so if (newName) { - this._tabEdited.originalName = this._tabEdited.label; this._tabEdited.label = newName; - this._tabEdited.renamedName = newName; + this._tabEdited.setAttribute('zen-has-static-label', 'true'); } else { - this._tabEdited.label = this._tabEdited.originalName; - this._tabEdited.originalName = null; - this._tabEdited.renamedName = null; + // If the page is loaded, get the title of the page. Otherwise, keep name as is + this._tabEdited.label = gBrowser.getBrowserForTab(this._tabEdited).contentTitle || this._tabEdited.label; + // If the page had a title, reset the zen-has-static-label attribute + if (gBrowser.getBrowserForTab(this._tabEdited).contentTitle) { + this._tabEdited.removeAttribute('zen-has-static-label'); + } } this._tabEdited.querySelector('.tab-editor-container').remove(); label.style.display = ''; label.className = label.className.replace(' tab-label-container-editing', ''); - document.removeEventListener('click', this.contextRenameTabHalt.bind(this)); + document.removeEventListener('click', this.renameTabHalt.bind(this)); this._tabEdited = null; } else if (event.key === 'Escape') { @@ -682,12 +667,12 @@ var gZenVerticalTabsManager = { label.style.display = ''; label.className = label.className.replace(' tab-label-container-editing', ''); - document.removeEventListener('click', this.contextRenameTabHalt.bind(this)); + document.removeEventListener('click', this.renameTabHalt.bind(this)); this._tabEdited = null; } }, - contextRenameTabStart(event) { + renameTabStart(event) { if (this._tabEdited) return; this._tabEdited = event.target.closest('.tabbrowser-tab'); if (!this._tabEdited.pinned) { @@ -706,7 +691,7 @@ var gZenVerticalTabsManager = { const input = document.createElement('input'); input.id = 'tab-label-input'; input.value = this._tabEdited.label; - input.addEventListener('keydown', this.contextRenameTabKeydown.bind(this)); + input.addEventListener('keydown', this.renameTabKeydown.bind(this)); input.style['white-space'] = 'nowrap'; input.style['overflow-x'] = 'scroll'; input.style['margin'] = '0'; @@ -715,10 +700,10 @@ var gZenVerticalTabsManager = { input.focus(); input.select(); - document.addEventListener('click', this.contextRenameTabHalt.bind(this)); + document.addEventListener('click', this.renameTabHalt.bind(this)); }, - contextRenameTabHalt(event) { + renameTabHalt(event) { // Ignore click event if it's clicking the input if (event.target.closest('#tab-label-input')) { return; @@ -731,7 +716,7 @@ var gZenVerticalTabsManager = { label.style.display = ''; label.className = label.className.replace(' tab-label-container-editing', ''); - document.removeEventListener('click', this.contextRenameTabHalt.bind(this)); + document.removeEventListener('click', this.renameTabHalt.bind(this)); this._tabEdited = null; }, }; diff --git a/src/browser/components/sessionstore/TabState-sys-mjs.patch b/src/browser/components/sessionstore/TabState-sys-mjs.patch index a38f9b7c4..26972ac49 100644 --- a/src/browser/components/sessionstore/TabState-sys-mjs.patch +++ b/src/browser/components/sessionstore/TabState-sys-mjs.patch @@ -1,8 +1,8 @@ diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs -index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..83bf443ca158c07e05075777da02b7f228d83dff 100644 +index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..dc0fdf17952df397a684f8a1da2f71739d007350 100644 --- a/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs -@@ -84,6 +84,13 @@ class _TabState { +@@ -84,6 +84,14 @@ class _TabState { tabData.groupId = tab.group.id; } @@ -12,6 +12,7 @@ index 8f7ed557e6aa61e7e16ed4a8d785ad5fe651b3d8..83bf443ca158c07e05075777da02b7f2 + tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId"); + tabData.zenPinnedEntry = tab.getAttribute("zen-pinned-entry"); + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); ++ tabData.zenHasStaticLabel = tab.getAttribute("zen-has-static-label"); + tabData.searchMode = tab.ownerGlobal.gURLBar.getSearchMode(browser, true); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 3a56da16a..fc40d1675 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 ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafeda43b085 100644 +index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..4faba37097f376b57c7376e320f46e9cd3aacffe 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -406,11 +406,52 @@ @@ -25,7 +25,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe + if (!tab.pinned) { + break; + } -+ if (!tab.hidden && !tab.hasAttribute("zen-glance-tab")) { ++ if (!tab.hidden) { + i++; + } + } @@ -177,7 +177,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe // Additionally send pinned tab events if (pinned) { this._notifyPinnedStatus(t); -@@ -3403,6 +3468,21 @@ +@@ -3403,6 +3455,24 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -195,11 +195,14 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe + } + if (tabData.zenPinnedEntry) { + tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry); ++ } ++ if (tabData.zenHasStaticLabel) { ++ tab.setAttribute("zen-has-static-label", "true"); + } if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3416,6 +3496,7 @@ +@@ -3416,6 +3486,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -207,7 +210,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3451,7 +3532,21 @@ +@@ -3451,7 +3522,24 @@ skipLoad: true, preferredRemoteType, }); @@ -226,22 +229,14 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe + } + if (tabData.zenPinnedEntry) { + tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry); ++ } ++ if (tabData.zenHasStaticLabel) { ++ tab.setAttribute("zen-has-static-label", "true"); + } if (select) { tabToSelect = tab; } -@@ -3464,8 +3559,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) { -- tab._tPos = this.pinnedTabCount; -- this.tabContainer.insertBefore(tab, this.tabs[this.pinnedTabCount]); -+ tab._tPos = this._numVisiblePinTabs; -+ this.tabContainer.insertBefore(tab, this.tabs[this._numVisiblePinTabs]); - tab.toggleAttribute("pinned", true); - this.tabContainer._invalidateCachedTabs(); - // Then ensure all the tab open/pinning information is sent. -@@ -3729,7 +3824,7 @@ +@@ -3729,7 +3817,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. @@ -250,7 +245,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe if ( !bulkOrderedOpen && ((openerTab && -@@ -3780,7 +3875,7 @@ +@@ -3780,7 +3868,7 @@ } /** @type {MozTabbrowserTab|undefined} */ @@ -259,7 +254,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe this.tabContainer._invalidateCachedTabs(); if (tabGroup) { -@@ -4095,6 +4190,9 @@ +@@ -4095,6 +4183,9 @@ return; } @@ -269,7 +264,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe this.removeTabs(selectedTabs); } -@@ -4427,6 +4525,7 @@ +@@ -4427,6 +4518,7 @@ skipSessionStore, } = {} ) { @@ -277,7 +272,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4443,6 +4542,12 @@ +@@ -4443,6 +4535,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -290,7 +285,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4457,7 +4562,9 @@ +@@ -4457,7 +4555,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -301,7 +296,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4471,7 +4578,6 @@ +@@ -4471,7 +4571,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -309,7 +304,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4610,14 +4716,14 @@ +@@ -4610,14 +4709,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -326,16 +321,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4812,6 +4918,8 @@ - this.tabs[i]._tPos = i; - } - -+ ZenWorkspaces.updateTabsContainers(); -+ - if (!this._windowIsClosing) { - if (wasPinned) { - this.tabContainer._positionPinnedTabs(); -@@ -5465,10 +5573,10 @@ +@@ -5465,10 +5564,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -348,28 +334,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5706,9 +5814,9 @@ - - // Don't allow mixing pinned and unpinned tabs. - if (aTab.pinned) { -- aIndex = Math.min(aIndex, this.pinnedTabCount - 1); -+ aIndex = Math.min(aIndex, (aTab.hasAttribute('zen-essential') ? this._numZenEssentials : this._numVisiblePinTabsWithoutGlance) - 1); - } else { -- aIndex = Math.max(aIndex, this.pinnedTabCount); -+ aIndex = Math.max(aIndex, this._numVisiblePinTabsWithoutGlance); - } - if (aTab._tPos == aIndex) { - return; -@@ -5717,7 +5825,7 @@ - this._lastRelatedTabMap = new WeakMap(); - - this._handleTabMove(aTab, () => { -- let neighbor = this.tabs[aIndex]; -+ let neighbor = this.tabs.filter(tab => !tab.hasAttribute("zen-glance-tab"))[aIndex]; - if (forceStandaloneTab && neighbor.group) { - neighbor = neighbor.group; - } -@@ -5727,6 +5835,9 @@ +@@ -5727,6 +5826,9 @@ this.tabContainer.insertBefore(aTab, neighbor); } }); @@ -379,16 +344,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe } moveTabToGroup(aTab, aGroup) { -@@ -5802,7 +5913,7 @@ - createLazyBrowser, - }; - -- let numPinned = this.pinnedTabCount; -+ let numPinned = this._numVisiblePinTabs; - if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { - params.pinned = true; - } -@@ -7443,6 +7554,7 @@ +@@ -7443,6 +7545,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -396,7 +352,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; gBrowser.syncThrobberAnimations(this.mTab); -@@ -8411,7 +8523,7 @@ var TabContextMenu = { +@@ -8411,7 +8514,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -405,7 +361,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8444,7 +8556,7 @@ var TabContextMenu = { +@@ -8444,7 +8547,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -414,7 +370,7 @@ index ff90a70bdad6c94ec4b90027ff102972d0eb28e5..8f2cd9ecd708e58a6b162740bb21dafe contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8677,6 +8789,7 @@ var TabContextMenu = { +@@ -8677,6 +8780,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else {