tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit f34d222f9942de544359cccb6f60a84ce58ad535
parent 22a51d63447cfa7985ea1d40dcbbb52dcb8b8f33
Author: agoloman <agoloman@mozilla.com>
Date:   Tue, 16 Dec 2025 22:56:02 +0200

Revert "Bug 1986948 - Implement drag n'drop for splitview containers r=tabbrowser-reviewers,nsharpley" for causing bc failures @browser_drag_splitview.js.

This reverts commit 44baaa9ed3fd7f3ecea2f222f5d34d0d6512dfb1.

Diffstat:
Mbrowser/base/content/browser-init.js | 7-------
Mbrowser/components/tabbrowser/content/drag-and-drop.js | 22++++------------------
Mbrowser/components/tabbrowser/content/tab-stacking.js | 31+++++++------------------------
Mbrowser/components/tabbrowser/content/tabbrowser.js | 83+++++++++++++++----------------------------------------------------------------
Mbrowser/components/tabbrowser/content/tabgroup.js | 9---------
Mbrowser/components/tabbrowser/content/tabs.js | 11++++++-----
Mbrowser/components/tabbrowser/content/tabsplitview.js | 4----
Mbrowser/components/tabbrowser/test/browser/dragdrop/browser.toml | 2--
Dbrowser/components/tabbrowser/test/browser/dragdrop/browser_drag_splitview.js | 138-------------------------------------------------------------------------------
Mbrowser/components/tabbrowser/test/browser/dragdrop/browser_drag_to_pin.js | 19+++++++++++++++++--
Mbrowser/components/tabbrowser/test/browser/dragdrop/head.js | 22----------------------
Mbrowser/themes/shared/tabbrowser/tabs.css | 32+++++++++++++++-----------------
12 files changed, 64 insertions(+), 316 deletions(-)

diff --git a/browser/base/content/browser-init.js b/browser/base/content/browser-init.js @@ -301,13 +301,6 @@ var gBrowserInit = { gBrowser.adoptTabGroup(tabToAdopt, { tabIndex: 0, selectTab: true }); gBrowser.removeTab(tempBlankTab); Glean.tabgroup.groupInteractions.move_window.add(1); - } else if (gBrowser.isSplitViewWrapper(tabToAdopt)) { - let tempBlankTab = gBrowser.selectedTab; - gBrowser.adoptSplitView(tabToAdopt, { - elementIndex: 0, - selectTab: true, - }); - gBrowser.removeTab(tempBlankTab); } else { if (tabToAdopt.group) { Glean.tabgroup.tabInteractions.remove_new_window.add(); diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js @@ -75,9 +75,6 @@ if (!tab) { return; } - if (tab.splitview) { - tab = tab.splitview; - } this._tabbrowserTabs.previewPanel?.deactivate(null, { force: true }); this.startTabDrag(event, tab); @@ -382,7 +379,6 @@ !shouldCreateGroupOnDrop && !shouldDropIntoCollapsedTabGroup && !isTabGroupLabel(draggedTab) && - !isSplitViewWrapper(draggedTab) && !shouldPin && !shouldUnpin; if (this._isContainerVerticalPinnedGrid(draggedTab)) { @@ -505,10 +501,6 @@ gBrowser.adoptTabGroup(draggedTab.group, { elementIndex: this._getDropIndex(event), }); - } else if (isSplitViewWrapper(draggedTab)) { - gBrowser.adoptSplitView(draggedTab, { - elementIndex: this._getDropIndex(event), - }); } else if (draggedTab) { // Move the tabs into this window. To avoid multiple tab-switches in // the original window, the selected tab should be adopted last. @@ -819,7 +811,7 @@ } /** - * Returns the tab, tab group label or split view wrapper where an event happened, + * Returns the tab or tab group label where an event happened, or null if * it didn't occur on a tab or tab group label. * * @param {Event} event @@ -833,11 +825,7 @@ _getDragTarget(event, { ignoreSides = false } = {}) { let { target } = event; while (target) { - if ( - isTab(target) || - isTabGroupLabel(target) || - isSplitViewWrapper(target) - ) { + if (isTab(target) || isTabGroupLabel(target)) { break; } target = target.parentNode; @@ -996,7 +984,7 @@ } let dataTransferOrderedTabs; - if (fromTabList || isTabGroupLabel(tab) || isSplitViewWrapper(tab)) { + if (fromTabList || isTabGroupLabel(tab)) { // Dragging a group label or an item in the all tabs menu doesn't // change the currently selected tabs, and it's not possible to select // multiple tabs from the list, thus handle only the dragged tab in @@ -2536,9 +2524,7 @@ if (isMovingTab) { let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0); if ( - (isTab(sourceNode) || - isTabGroupLabel(sourceNode) || - isSplitViewWrapper(sourceNode)) && + (isTab(sourceNode) || isTabGroupLabel(sourceNode)) && sourceNode.ownerGlobal.isChromeWindow && sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" diff --git a/browser/components/tabbrowser/content/tab-stacking.js b/browser/components/tabbrowser/content/tab-stacking.js @@ -202,7 +202,6 @@ !shouldCreateGroupOnDrop && !shouldDropIntoCollapsedTabGroup && !isTabGroupLabel(draggedTab) && - !isSplitViewWrapper(draggedTab) && !shouldPin && !shouldUnpin; if (this._isContainerVerticalPinnedGrid(draggedTab)) { @@ -325,10 +324,6 @@ gBrowser.adoptTabGroup(draggedTab.group, { elementIndex: this._getDropIndex(event), }); - } else if (isSplitViewWrapper(draggedTab)) { - gBrowser.adoptSplitView(draggedTab, { - elementIndex: this._getDropIndex(event), - }); } else if (draggedTab) { // Move the tabs into this window. To avoid multiple tab-switches in // the original window, the selected tab should be adopted last. @@ -731,7 +726,7 @@ }); } - // Use .tab-group-label-container, tab-split-view-wrapper or .tabbrowser-tab for size/position + // Use .tab-group-label-container or .tabbrowser-tab for size/position // calculations. let rect = window.windowUtils.getBoundsWithoutFlushing(tabStripItemElement); @@ -1247,8 +1242,9 @@ dropElement?.currentIndex ?? dropElement.elementIndex; } else { dropBefore = false; - let lastVisibleTabInGroup = - overlappedGroup.tabsAndSplitViews.findLast(ele => ele.visible); + let lastVisibleTabInGroup = overlappedGroup.tabs.findLast( + tab => tab.visible + ); newDropElementIndex = (lastVisibleTabInGroup?.currentIndex ?? lastVisibleTabInGroup.elementIndex) + 1; @@ -1577,11 +1573,9 @@ let pinnedDropIndicator = draggedTabDocument.getElementById( "pinned-drop-indicator" ); - let draggedTabContainer = - draggedTabDocument.ownerGlobal.gBrowser.tabContainer; pinnedDropIndicator.removeAttribute("visible"); pinnedDropIndicator.removeAttribute("interactive"); - draggedTabContainer.style.maxWidth = ""; + draggedTabDocument.ownerGlobal.gBrowser.tabContainer.style.maxWidth = ""; let allTabs = draggedTabDocument.getElementsByClassName("tabbrowser-tab"); for (let tab of allTabs) { tab.style.width = ""; @@ -1604,7 +1598,7 @@ label.style.pointerEvents = ""; label.removeAttribute("dragtarget"); } - for (let label of draggedTabContainer.getElementsByClassName( + for (let label of draggedTabDocument.getElementsByClassName( "tab-group-label" )) { delete label.currentIndex; @@ -1633,23 +1627,12 @@ ); arrowScrollbox.scrollbox.style.height = ""; arrowScrollbox.scrollbox.style.width = ""; - for (let groupLabel of draggedTabContainer.getElementsByClassName( + for (let groupLabel of draggedTabDocument.getElementsByClassName( "tab-group-label-container" )) { groupLabel.style.left = ""; groupLabel.style.top = ""; } - for (let splitviewWrapper of draggedTabContainer.getElementsByTagName( - "tab-split-view-wrapper" - )) { - splitviewWrapper.style.width = ""; - splitviewWrapper.style.maxWidth = ""; - splitviewWrapper.style.height = ""; - splitviewWrapper.style.left = ""; - splitviewWrapper.style.top = ""; - splitviewWrapper.style.pointerEvents = ""; - splitviewWrapper.removeAttribute("dragtarget"); - } } }; } diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js @@ -3207,9 +3207,6 @@ if (this.isTabGroupLabel(element)) { element = element.group.tabs[0]; } - if (this.isSplitViewWrapper(element)) { - element = element.tabs[0]; - } return element._tPos; } @@ -3608,8 +3605,6 @@ let oldSelectedTab = selectTab && group.ownerGlobal.gBrowser.selectedTab; let newTabs = []; - let adoptedTab; - let splitview; // bug1969925 adopting a tab group will cause the window to close if it // is the only thing on the tab strip @@ -3618,79 +3613,32 @@ t => t.group == group ); - // We dispatch this event in a separate for loop because the tab extension API - // expects event.detail to be a tab. - if (noOtherTabsInWindow) { - for (let element of group.tabs) { + for (let tab of group.tabs) { + if (noOtherTabsInWindow) { group.dispatchEvent( new CustomEvent("TabUngrouped", { bubbles: true, - detail: element, + detail: tab, }) ); } - } - - for (let element of group.tabsAndSplitViews) { - if (element.tagName == "tab-split-view-wrapper") { - splitview = this.adoptSplitView(element, { - elementIndex, - tabIndex, - }); - newTabs.push(splitview); - tabIndex = splitview.tabs[0]._tPos + splitview.tabs.length; - } else { - adoptedTab = this.adoptTab(element, { - elementIndex, - tabIndex, - selectTab: element === oldSelectedTab, - }); - newTabs.push(adoptedTab); - // Put next tab after current one. - elementIndex = undefined; - tabIndex = adoptedTab._tPos + 1; - } - } - - return this.addTabGroup(newTabs, { - id: group.id, - label: group.label, - color: group.color, - insertBefore: newTabs[0], - isAdoptingGroup: true, - }); - } - - /** - * @param {MozSplitViewWrapper} container - * @param {object} [options] - * @param {number} [options.elementIndex] - * @param {number} [options.tabIndex] - * @param {boolean} [options.selectTab] - * @returns {MozSplitViewWrapper} - */ - adoptSplitView(container, { elementIndex, tabIndex } = {}) { - if (container.ownerDocument == document) { - return container; - } - - let newTabs = []; - - if (!tabIndex) { - tabIndex = this.#elementIndexToTabIndex(elementIndex); - } - - for (let tab of container.tabs) { let adoptedTab = this.adoptTab(tab, { + elementIndex, tabIndex, + selectTab: tab === oldSelectedTab, }); newTabs.push(adoptedTab); + // Put next tab after current one. + elementIndex = undefined; tabIndex = adoptedTab._tPos + 1; } - return this.addTabSplitView(newTabs, { - id: container.splitViewId, + return this.addTabGroup(newTabs, { + id: group.id, + label: group.label, + color: group.color, insertBefore: newTabs[0], + isAdoptingGroup: true, }); } @@ -6869,9 +6817,6 @@ if (tab.group) { state.tabGroupId = tab.group.id; } - if (tab.splitview) { - state.splitViewId = tab.splitview.splitViewId; - } return state; } @@ -6917,7 +6862,9 @@ let tabs; if (this.isTab(element)) { tabs = [element]; - } else if (this.isTabGroup(element) || this.isSplitViewWrapper(element)) { + } else if (this.isTabGroup(element)) { + tabs = element.tabs; + } else if (this.isSplitViewWrapper(element)) { tabs = element.tabs; } else { throw new Error( diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js @@ -476,15 +476,6 @@ } /** - * @returns {MozTabbrowserTab|MozTabSplitViewWrapper[]} - */ - get tabsAndSplitViews() { - return Array.from(this.children).filter( - node => node.matches("tab") || node.tagName == "tab-split-view-wrapper" - ); - } - - /** * @param {MozTabbrowserTab} tab * @returns {boolean} */ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js @@ -1003,13 +1003,14 @@ child.labelElement.elementIndex = elementIndex++; dragAndDropElements.push(child.labelElement); - let tabsAndSplitViews = child.tabsAndSplitViews.filter( - node => node.visible + let visibleChildren = Array.from(child.children).filter( + ele => ele.visible || ele.tagName == "tab-split-view-wrapper" ); - tabsAndSplitViews.forEach(ele => { - ele.elementIndex = elementIndex++; + + visibleChildren.forEach(tab => { + tab.elementIndex = elementIndex++; }); - dragAndDropElements.push(...tabsAndSplitViews); + dragAndDropElements.push(...visibleChildren); } else { child.elementIndex = elementIndex++; dragAndDropElements.push(child); diff --git a/browser/components/tabbrowser/content/tabsplitview.js b/browser/components/tabbrowser/content/tabsplitview.js @@ -145,10 +145,6 @@ return Array.from(this.children).filter(node => node.matches("tab")); } - get visible() { - return this.tabs.every(tab => tab.visible); - } - /** * Get the list of tab panels from this split view. * diff --git a/browser/components/tabbrowser/test/browser/dragdrop/browser.toml b/browser/components/tabbrowser/test/browser/dragdrop/browser.toml @@ -3,8 +3,6 @@ support-files = [ "head.js" ] -["browser_drag_splitview.js"] - ["browser_drag_to_pin.js"] ["browser_move_unpinned_not_overflowing.js"] diff --git a/browser/components/tabbrowser/test/browser/dragdrop/browser_drag_splitview.js b/browser/components/tabbrowser/test/browser/dragdrop/browser_drag_splitview.js @@ -1,138 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -let currentReduceMotionOverride; - -add_setup(() => { - currentReduceMotionOverride = gReduceMotionOverride; - // Disable tab animations - gReduceMotionOverride = true; -}); - -add_task(async function test_drag_splitview_tab() { - let [tab1, tab2, tab3] = await Promise.all( - Array.from({ length: 3 }).map((_, index) => - addTab(`data:text/plain,tab${index + 1}`) - ) - ); - - const startingTab = gBrowser.tabs[0]; - let splitview = gBrowser.addTabSplitView([tab2, tab3]); - Assert.equal(splitview.tabs.length, 2, "Split view has 2 tabs"); - - Assert.deepEqual( - gBrowser.tabs, - [startingTab, tab1, tab2, tab3], - "confirm tabs' starting order" - ); - try { - info("Drag a splitview tab"); - await customDragAndDrop(tab3, tab1, null, null, waitForTabMove(tab3)); - - Assert.deepEqual( - gBrowser.tabs, - [startingTab, tab2, tab3, tab1], - "Confirm that tab3 and tab2 in a splitview move together before tab1" - ); - - info("Drag a tab in between a splitview"); - await customDragAndDrop(tab1, tab2, null, null, waitForTabMove(tab1)); - - Assert.deepEqual( - gBrowser.tabs, - [startingTab, tab1, tab2, tab3], - "Confirm that tab1 cannot be dragged in between splitview tabs" - ); - - let group = gBrowser.addTabGroup([tab1, splitview]); - Assert.equal(group.tabs.length, 3, "group has 3 tabs"); - - Assert.deepEqual( - gBrowser.tabs, - [startingTab, tab1, tab2, tab3], - "Confirm that splitview tabs can be reordered within a tab group" - ); - // ensure we drag before tab 1, not after - let event = getDragEvent(); - info("Drag splitview tabs within a tab group"); - await customDragAndDrop(tab2, tab1, null, null, event); - - Assert.deepEqual( - gBrowser.tabs, - [startingTab, tab2, tab3, tab1], - "Confirm that splitview tabs can be reordered within a tab group" - ); - } finally { - BrowserTestUtils.removeTab(tab1); - BrowserTestUtils.removeTab(tab2); - BrowserTestUtils.removeTab(tab3); - } -}); - -add_task(async function test_dragging_splitview_second_window() { - let win2 = await BrowserTestUtils.openNewBrowserWindow(); - let [tab1, tab2] = await Promise.all( - Array.from({ length: 2 }).map((_, index) => - addTab(`data:text/plain,tab${index + 1}`) - ) - ); - - let splitview = window.gBrowser.addTabSplitView([tab1, tab2]); - Assert.equal(splitview.tabs.length, 2, "Split view has 2 tabs"); - - let secondWindowTab1 = win2.gBrowser.tabs[0]; - let secondWindowTab2 = BrowserTestUtils.addTab( - win2.gBrowser, - "data:text/plain,tab4" - ); - - is(win2.gBrowser.tabs.length, 2, "win2 contains 2 tabs"); - - let awaitCloseEvent = BrowserTestUtils.waitForEvent(tab1, "TabClose"); - let awaitOpenEvent = BrowserTestUtils.waitForEvent(win2, "TabOpen"); - - let effect = EventUtils.synthesizeDrop( - tab1, - secondWindowTab1, - [[{ type: TAB_DROP_TYPE, data: tab1 }]], - null, - window, - win2 - ); - is(effect, "move", "Tabs should be moved from win1 to win2."); - - let closeEvent = await awaitCloseEvent; - let openEvent = await awaitOpenEvent; - - is(openEvent.detail.adoptedTab, tab1, "New tab adopted old tab"); - - is( - closeEvent.detail.adoptedBy, - openEvent.target, - "Old tab adopted by new tab" - ); - - is( - win2.gBrowser.tabs.length, - 4, - "win2 contains 2 new tabs, for a total of 4" - ); - - let [secondWindowTab3, secondWindowTab4] = win2.gBrowser.tabs.slice(1, 3); - - Assert.deepEqual( - win2.gBrowser.tabs, - [secondWindowTab1, secondWindowTab3, secondWindowTab4, secondWindowTab2], - "Two new tabs were inserted in the correct position in the second window" - ); - - ok( - secondWindowTab3.splitview && secondWindowTab4.splitview, - "Two new tabs in second window are splitview tabs" - ); - - await BrowserTestUtils.closeWindow(win2); -}); diff --git a/browser/components/tabbrowser/test/browser/dragdrop/browser_drag_to_pin.js b/browser/components/tabbrowser/test/browser/dragdrop/browser_drag_to_pin.js @@ -25,6 +25,21 @@ registerCleanupFunction(() => { CustomizableUI.reset(); }); +function getDragEvent(win, isVertical = false) { + let tabContainer = win.document.getElementById("tabbrowser-tabs"); + let tabContainerRect = win.windowUtils.getBoundsWithoutFlushing(tabContainer); + // Drag to the starting edge of the tab container + return { + clientX: isVertical + ? tabContainerRect.x + tabContainerRect.width / 2 + : tabContainerRect.x + 1, + clientY: isVertical + ? tabContainerRect.y + 1 + : tabContainerRect.y + tabContainerRect.height / 2, + dropEffect: "move", + }; +} + async function pinIndicatorDragCond(pinnedDropIndicator) { info("Wait for interaction cue"); await BrowserTestUtils.waitForMutationCondition( @@ -46,7 +61,7 @@ add_task(async function test_pin_to_pinned_drop_indicator_horizontal() { let unpinnedTabsContainer = document.getElementById( "tabbrowser-arrowscrollbox" ); - let dragEvent = getDragEvent(); + let dragEvent = getDragEvent(window); info("Drag to pin to the interaction cue"); await customDragAndDrop( @@ -140,7 +155,7 @@ add_task(async function test_pin_to_promo_card_vertical() { let initialTab = gBrowser.tabs[0]; let tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); let promoCard = document.getElementById("drag-to-pin-promo-card"); - let dragEvent = getDragEvent(true); + let dragEvent = getDragEvent(window, true); async function promoPinDragCond() { info("Wait for promo card"); diff --git a/browser/components/tabbrowser/test/browser/dragdrop/head.js b/browser/components/tabbrowser/test/browser/dragdrop/head.js @@ -141,25 +141,3 @@ function waitForTabMove(tab) { "Tab did not change position after a drop" ); } - -/** - * @param {boolean} Optional - * Whether to apply to vertical or horizontal tabs - * @returns {object} - * Returns properties used to emulate a drag event. - */ -function getDragEvent(isVertical = false) { - let tabContainerRect = window.windowUtils.getBoundsWithoutFlushing( - gBrowser.tabContainer - ); - // Drag to the starting edge of the tab container - return { - clientX: isVertical - ? tabContainerRect.x + tabContainerRect.width / 2 - : tabContainerRect.x + 1, - clientY: isVertical - ? tabContainerRect.y + 1 - : tabContainerRect.y + tabContainerRect.height / 2, - dropEffect: "move", - }; -} diff --git a/browser/themes/shared/tabbrowser/tabs.css b/browser/themes/shared/tabbrowser/tabs.css @@ -188,22 +188,6 @@ position: relative; } -.tabbrowser-tab[dragtarget], -tab-split-view-wrapper[dragtarget] { - /* Margin needs to be at least 4px to not clip multiselect stacking effect */ - overflow-clip-margin: 4px; - z-index: 3 !important; - position: absolute !important; - pointer-events: none; /* avoid blocking dragover events on scroll buttons */ - - /* stylelint-disable-next-line media-query-no-invalid */ - @media -moz-pref("browser.tabs.dragDrop.multiselectStacking") { - &[multiselected]:not([small-stack], [big-stack]) { - visibility: hidden; - } - } -} - .tabbrowser-tab { --tab-label-mask-size: 1em; @@ -249,6 +233,21 @@ tab-split-view-wrapper[dragtarget] { } } + &[dragtarget] { + /* Margin needs to be at least 4px to not clip multiselect stacking effect */ + overflow-clip-margin: 4px; + z-index: 3 !important; + position: absolute !important; + pointer-events: none; /* avoid blocking dragover events on scroll buttons */ + + /* stylelint-disable-next-line media-query-no-invalid */ + @media -moz-pref("browser.tabs.dragDrop.multiselectStacking") { + &[multiselected]:not([small-stack], [big-stack]) { + visibility: hidden; + } + } + } + #tabbrowser-tabs[movingtab] & { position: relative; @@ -1324,7 +1323,6 @@ tab-group > tab-split-view-wrapper { margin-inline: var(--space-small); padding: var(--space-xsmall); border-radius: var(--tab-border-radius); - position: relative; /* prevents splitview wrappers from shifting during other drag events*/ &[hasactivetab] { background-color: var(--tab-hover-background-color);