From 8a2e015048cccf36818c0fc04565f30e7887d10a Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Sun, 25 Jan 2026 12:26:26 +0100 Subject: [PATCH] fix: Fixed dragging split views into blank windows, b=no-bug, c=no-component --- .../tabbrowser/content/tabbrowser-js.patch | 114 ++++++++++-------- 1 file changed, 61 insertions(+), 53 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 6073eeab2..ce3436c45 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 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a1417570d4f1266 100644 +index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..ab301a3a8e83727e5316c3af9eb43cdfc028a122 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -398,6 +398,7 @@ @@ -384,7 +384,15 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 ); } -@@ -3746,6 +3867,7 @@ +@@ -3599,6 +3720,7 @@ + color: group.color, + insertBefore: newTabs[0], + isAdoptingGroup: true, ++ forSplitView: group.hasAttribute('split-view-group'), + }); + } + +@@ -3746,6 +3868,7 @@ openWindowInfo, skipLoad, triggeringRemoteType, @@ -392,7 +400,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } ) { // If we don't have a preferred remote type (or it is `NOT_REMOTE`), and -@@ -3815,6 +3937,7 @@ +@@ -3815,6 +3938,7 @@ openWindowInfo, name, skipLoad, @@ -400,7 +408,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 }); } -@@ -4003,7 +4126,7 @@ +@@ -4003,7 +4127,7 @@ // Add a new tab if needed. if (!tab) { let createLazyBrowser = @@ -409,7 +417,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 let url = "about:blank"; if (tabData.entries?.length) { -@@ -4040,8 +4163,10 @@ +@@ -4040,8 +4164,10 @@ insertTab: false, skipLoad: true, preferredRemoteType, @@ -421,7 +429,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (select) { tabToSelect = tab; } -@@ -4053,7 +4178,8 @@ +@@ -4053,7 +4179,8 @@ this.pinTab(tab); // Then ensure all the tab open/pinning information is sent. this._fireTabOpen(tab, {}); @@ -431,7 +439,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 let { groupId } = tabData; const tabGroup = tabGroupWorkingData.get(groupId); // if a tab refers to a tab group we don't know, skip any group -@@ -4067,7 +4193,10 @@ +@@ -4067,7 +4194,10 @@ tabGroup.stateData.id, tabGroup.stateData.color, tabGroup.stateData.collapsed, @@ -443,7 +451,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 ); tabsFragment.appendChild(tabGroup.node); } -@@ -4112,9 +4241,23 @@ +@@ -4112,9 +4242,23 @@ // to remove the old selected tab. if (tabToSelect) { let leftoverTab = this.selectedTab; @@ -467,7 +475,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (tabs.length > 1 || !tabs[0].selected) { this._updateTabsAfterInsert(); -@@ -4305,11 +4448,14 @@ +@@ -4305,11 +4449,14 @@ if (ownerTab) { tab.owner = ownerTab; } @@ -483,7 +491,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if ( !bulkOrderedOpen && ((openerTab && -@@ -4321,7 +4467,7 @@ +@@ -4321,7 +4468,7 @@ let lastRelatedTab = openerTab && this._lastRelatedTabMap.get(openerTab); let previousTab = lastRelatedTab || openerTab || this.selectedTab; @@ -492,7 +500,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 tabGroup = previousTab.group; } if ( -@@ -4337,7 +4483,7 @@ +@@ -4337,7 +4484,7 @@ previousTab.splitview ) + 1; } else if (previousTab.visible) { @@ -501,7 +509,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } else if (previousTab == FirefoxViewHandler.tab) { elementIndex = 0; } -@@ -4365,14 +4511,14 @@ +@@ -4365,14 +4512,14 @@ } // Ensure index is within bounds. if (tab.pinned) { @@ -520,7 +528,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (pinned && !itemAfter?.pinned) { itemAfter = null; -@@ -4385,7 +4531,7 @@ +@@ -4385,7 +4532,7 @@ this.tabContainer._invalidateCachedTabs(); @@ -529,7 +537,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if ( (this.isTab(itemAfter) && itemAfter.group == tabGroup) || this.isSplitViewWrapper(itemAfter) -@@ -4416,7 +4562,11 @@ +@@ -4416,7 +4563,11 @@ const tabContainer = pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; @@ -541,7 +549,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } if (tab.group?.collapsed) { -@@ -4431,6 +4581,7 @@ +@@ -4431,6 +4582,7 @@ if (pinned) { this._updateTabBarForPinnedTabs(); } @@ -549,7 +557,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 TabBarVisibility.update(); } -@@ -4983,6 +5134,7 @@ +@@ -4983,6 +5135,7 @@ telemetrySource, } = {} ) { @@ -557,7 +565,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // When 'closeWindowWithLastTab' pref is enabled, closing all tabs // can be considered equivalent to closing the window. if ( -@@ -5072,6 +5224,7 @@ +@@ -5072,6 +5225,7 @@ if (lastToClose) { this.removeTab(lastToClose, aParams); } @@ -565,7 +573,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } catch (e) { console.error(e); } -@@ -5110,6 +5263,12 @@ +@@ -5110,6 +5264,12 @@ aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); } @@ -578,7 +586,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -5124,6 +5283,9 @@ +@@ -5124,6 +5284,9 @@ // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let isLastTab = this.#isLastTabInWindow(aTab); @@ -588,7 +596,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -5172,7 +5334,13 @@ +@@ -5172,7 +5335,13 @@ // We're not animating, so we can cancel the animation stopwatch. Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId); aTab._closeTimeAnimTimerId = null; @@ -603,7 +611,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 return; } -@@ -5306,7 +5474,7 @@ +@@ -5306,7 +5475,7 @@ closeWindowWithLastTab != null ? closeWindowWithLastTab : !window.toolbar.visible || @@ -612,7 +620,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -5330,6 +5498,7 @@ +@@ -5330,6 +5499,7 @@ newTab = true; } @@ -620,7 +628,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -5370,13 +5539,7 @@ +@@ -5370,13 +5540,7 @@ aTab._mouseleave(); if (newTab) { @@ -635,7 +643,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } else { TabBarVisibility.update(); } -@@ -5509,6 +5672,7 @@ +@@ -5509,6 +5673,7 @@ this.tabs[i]._tPos = i; } @@ -643,7 +651,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (!this._windowIsClosing) { // update tab close buttons state this.tabContainer._updateCloseButtons(); -@@ -5732,6 +5896,7 @@ +@@ -5732,6 +5897,7 @@ } let excludeTabs = new Set(aExcludeTabs); @@ -651,7 +659,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // If this tab has a successor, it should be selectable, since // hiding or closing a tab removes that tab as a successor. -@@ -5744,15 +5909,22 @@ +@@ -5744,15 +5910,22 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -676,7 +684,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 let tab = this.tabContainer.findNextTab(aTab, { direction: 1, filter: _tab => remainingTabs.includes(_tab), -@@ -5766,7 +5938,7 @@ +@@ -5766,7 +5939,7 @@ } if (tab) { @@ -685,7 +693,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } // If no qualifying visible tab was found, see if there is a tab in -@@ -5787,7 +5959,7 @@ +@@ -5787,7 +5960,7 @@ }); } @@ -694,7 +702,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } _blurTab(aTab) { -@@ -5798,7 +5970,7 @@ +@@ -5798,7 +5971,7 @@ * @returns {boolean} * False if swapping isn't permitted, true otherwise. */ @@ -703,7 +711,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // Do not allow transfering a private tab to a non-private window // and vice versa. if ( -@@ -5852,6 +6024,7 @@ +@@ -5852,6 +6025,7 @@ // fire the beforeunload event in the process. Close the other // window if this was its last tab. if ( @@ -711,7 +719,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 !remoteBrowser._beginRemoveTab(aOtherTab, { adoptedByTab: aOurTab, closeWindowWithLastTab: true, -@@ -5863,7 +6036,7 @@ +@@ -5863,7 +6037,7 @@ // If this is the last tab of the window, hide the window // immediately without animation before the docshell swap, to avoid // about:blank being painted. @@ -720,7 +728,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (closeWindow) { let win = aOtherTab.ownerGlobal; win.windowUtils.suppressAnimation(true); -@@ -5987,11 +6160,13 @@ +@@ -5987,11 +6161,13 @@ } // Finish tearing down the tab that's going away. @@ -734,7 +742,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 this.setTabTitle(aOurTab); -@@ -6193,10 +6368,10 @@ +@@ -6193,10 +6369,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -747,7 +755,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -6254,7 +6429,8 @@ +@@ -6254,7 +6430,8 @@ * * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab */ @@ -757,7 +765,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (this.tabs.length == 1) { return null; } -@@ -6278,12 +6454,14 @@ +@@ -6278,12 +6455,14 @@ } // tell a new window to take the "dropped" tab @@ -773,7 +781,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } /** -@@ -6388,7 +6566,7 @@ +@@ -6388,7 +6567,7 @@ * `true` if element is a `` */ isTabGroup(element) { @@ -782,7 +790,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } /** -@@ -6473,8 +6651,8 @@ +@@ -6473,8 +6652,8 @@ } // Don't allow mixing pinned and unpinned tabs. @@ -793,7 +801,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } else { tabIndex = Math.max(tabIndex, this.pinnedTabCount); } -@@ -6500,10 +6678,16 @@ +@@ -6500,10 +6679,16 @@ this.#handleTabMove( element, () => { @@ -812,7 +820,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 if (neighbor && this.isTab(element) && tabIndex > element._tPos) { neighbor.after(element); } else { -@@ -6561,23 +6745,31 @@ +@@ -6561,23 +6746,31 @@ #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) { if (this.isTabGroupLabel(targetElement)) { targetElement = targetElement.group; @@ -850,7 +858,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } 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 -@@ -6590,14 +6782,34 @@ +@@ -6590,14 +6783,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. @@ -886,7 +894,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 element.pinned ? this.tabContainer.pinnedTabsContainer : this.tabContainer; -@@ -6606,7 +6818,7 @@ +@@ -6606,7 +6819,7 @@ element, () => { if (moveBefore) { @@ -895,7 +903,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 } else if (targetElement) { targetElement.after(element); } else { -@@ -6676,10 +6888,10 @@ +@@ -6676,10 +6889,10 @@ * @param {TabMetricsContext} [metricsContext] */ moveTabToExistingGroup(aTab, aGroup, metricsContext) { @@ -908,7 +916,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -6751,6 +6963,7 @@ +@@ -6751,6 +6964,7 @@ let state = { tabIndex: tab._tPos, @@ -916,7 +924,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 }; if (tab.visible) { state.elementIndex = tab.elementIndex; -@@ -6777,7 +6990,7 @@ +@@ -6777,7 +6991,7 @@ let changedTabGroup = previousTabState.tabGroupId != currentTabState.tabGroupId; @@ -925,7 +933,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 tab.dispatchEvent( new CustomEvent("TabMove", { bubbles: true, -@@ -6818,6 +7031,10 @@ +@@ -6818,6 +7032,10 @@ moveActionCallback(); @@ -936,7 +944,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -6869,6 +7086,19 @@ +@@ -6869,6 +7087,19 @@ * The new tab in the current window, null if the tab couldn't be adopted. */ adoptTab(aTab, { elementIndex, tabIndex, selectTab = false } = {}) { @@ -956,7 +964,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 // Swap the dropped tab with a new one we create and then close // it in the other window (making it seem to have moved between // windows). We also ensure that the tab we create to swap into has -@@ -6910,6 +7140,8 @@ +@@ -6910,6 +7141,8 @@ params.userContextId = aTab.getAttribute("usercontextid"); } let newTab = this.addWebTab("about:blank", params); @@ -965,7 +973,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 let newBrowser = this.getBrowserForTab(newTab); aTab.container.tabDragAndDrop.finishAnimateTabMove(); -@@ -7718,7 +7950,7 @@ +@@ -7718,7 +7951,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -974,7 +982,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 window.focus(); aEvent.preventDefault(); break; -@@ -7735,7 +7967,6 @@ +@@ -7735,7 +7968,6 @@ } case "TabGroupCollapse": aEvent.target.tabs.forEach(tab => { @@ -982,7 +990,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 }); break; case "TabGroupCreateByUser": -@@ -7895,7 +8126,9 @@ +@@ -7895,7 +8127,9 @@ let filter = this._tabFilters.get(tab); if (filter) { @@ -992,7 +1000,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 let listener = this._tabListeners.get(tab); if (listener) { -@@ -8698,6 +8931,7 @@ +@@ -8698,6 +8932,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -1000,7 +1008,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8778,6 +9012,7 @@ +@@ -8778,6 +9013,7 @@ // known defaults. Note we use the original URL since about:newtab // redirects to a prerendered page. const shouldRemoveFavicon = @@ -1008,7 +1016,7 @@ index 0eaca7a58e0026237b71b2ad515efe84d9e8c779..9c1fa86151f3d5896c45fef31a141757 !this.mBrowser.mIconURL && !ignoreBlank && !(originalLocation.spec in FAVICON_DEFAULTS); -@@ -9803,7 +10038,7 @@ var TabContextMenu = { +@@ -9803,7 +10039,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !this.multiselected;