From 50ed1f0a64c5f9bd9ee9c17e6e632906cc5afe73 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Thu, 22 May 2025 10:23:52 +0200 Subject: [PATCH 1/4] feat: Wait for a new frame before animating workspace backgrounds, b=(no-bug), c=workspaces --- src/zen/workspaces/ZenWorkspaces.mjs | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/zen/workspaces/ZenWorkspaces.mjs b/src/zen/workspaces/ZenWorkspaces.mjs index af67474e3..37891b3e4 100644 --- a/src/zen/workspaces/ZenWorkspaces.mjs +++ b/src/zen/workspaces/ZenWorkspaces.mjs @@ -2098,7 +2098,7 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { } } document.documentElement.setAttribute('animating-background', 'true'); - if (shouldAnimate) { + if (shouldAnimate && previousWorkspace) { let previousBackgroundOpacity = document.documentElement.style.getPropertyValue( '--zen-background-opacity' ); @@ -2114,19 +2114,24 @@ var gZenWorkspaces = new (class extends ZenMultiWindowFeature { previousBackgroundOpacity = 0; } gZenThemePicker.previousBackgroundOpacity = previousBackgroundOpacity; - animations.push( - gZenUIManager.motion.animate( - document.documentElement, - { - '--zen-background-opacity': [previousBackgroundOpacity, 1], - }, - { - type: 'spring', - bounce: 0, - duration: kGlobalAnimationDuration, - } - ) - ); + await new Promise((resolve) => { + requestAnimationFrame(() => { + animations.push( + gZenUIManager.motion.animate( + document.documentElement, + { + '--zen-background-opacity': [previousBackgroundOpacity, 1], + }, + { + type: 'spring', + bounce: 0, + duration: kGlobalAnimationDuration, + } + ) + ); + resolve(); + }); + }); } for (const element of document.querySelectorAll('zen-workspace')) { if (element.classList.contains('zen-essentials-container')) { From b6fc0e4db7b4f7b30b5518a810ded3ee31aa6d29 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Thu, 22 May 2025 11:26:13 +0200 Subject: [PATCH 2/4] feat: Added support to drag-and-drop split views into glance, b=(no-bug), c=tabs, common, glance, split-view --- .../tabbrowser/content/tabs-js.patch | 70 ++++++++++--------- src/toolkit/content/widgets/tabbox-js.patch | 4 +- .../common/styles/zen-browser-container.css | 14 ++-- src/zen/glance/ZenGlanceManager.mjs | 21 ++++++ src/zen/split-view/ZenViewSplitter.mjs | 10 ++- surfer.json | 2 +- 6 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index 4a769b122..0298d2580 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 ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bffdf463489 100644 +index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..b413b4bc9d86726b0f8936a3422636ed3ca882e1 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -83,7 +83,7 @@ @@ -136,7 +136,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } get verticalMode() { -@@ -1606,29 +1636,53 @@ +@@ -1606,29 +1636,55 @@ if (this.#allTabs) { return this.#allTabs; } @@ -173,19 +173,21 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff ...children, ]; + const lastPinnedTabIdx = pinnedTabs.length - 1; -+ for (let i = 0; i < allTabs.length; i++) { ++ let i = 0; ++ for (const tab of allTabs) { + // add glance tabs (tabs inside tabs) to the list -+ const glanceTab = allTabs[i].glanceTab; ++ const glanceTab = tab.glanceTab; + if (glanceTab) { + // insert right after the parent tab. note: it must be inserted before + // the last pinned tab so it can be inserted in the correct order + allTabs.splice(Math.max(i + 1, lastPinnedTabIdx), 0, glanceTab); + i++; -+ } else if (allTabs[i].classList.contains("vertical-pinned-tabs-container-separator")) { ++ } else if (tab.classList.contains("vertical-pinned-tabs-container-separator")) { + // remove the separator from the list + allTabs.splice(i, 1); + i--; + } ++ i++; + } + this.#allTabs = allTabs; return this.#allTabs; @@ -198,7 +200,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } /** -@@ -1648,7 +1702,7 @@ +@@ -1648,7 +1704,7 @@ */ get visibleTabs() { if (!this.#visibleTabs) { @@ -207,7 +209,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } return this.#visibleTabs; } -@@ -1683,36 +1737,40 @@ +@@ -1683,36 +1739,40 @@ } let elementIndex = 0; @@ -261,7 +263,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff return this.#focusableItems; } -@@ -1720,6 +1778,7 @@ +@@ -1720,6 +1780,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -269,7 +271,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } _invalidateCachedVisibleTabs() { -@@ -1734,8 +1793,8 @@ +@@ -1734,8 +1795,8 @@ #isContainerVerticalPinnedGrid(tab) { return ( this.verticalMode && @@ -280,7 +282,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff !this.expandOnHover ); } -@@ -1751,7 +1810,7 @@ +@@ -1751,7 +1812,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -289,7 +291,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } node.before(tab); -@@ -1846,7 +1905,7 @@ +@@ -1846,7 +1907,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. @@ -298,7 +300,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -1941,10 +2000,12 @@ +@@ -1941,10 +2002,12 @@ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -311,7 +313,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff selectedTab._notselectedsinceload = false; } -@@ -2085,16 +2146,15 @@ +@@ -2085,16 +2148,15 @@ // Move pinned tabs to another container when the tabstrip is toggled to vertical // and when session restore code calls _positionPinnedTabs; update styling whenever // the number of pinned tabs changes. @@ -334,7 +336,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } } -@@ -2102,9 +2162,7 @@ +@@ -2102,9 +2164,7 @@ } _resetVerticalPinnedTabs() { @@ -345,7 +347,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff if (!verticalTabsContainer.children.length) { return; -@@ -2117,7 +2175,7 @@ +@@ -2117,7 +2177,7 @@ } _positionPinnedTabs() { @@ -354,7 +356,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let numPinned = gBrowser.pinnedTabCount; let absPositionHorizontalTabs = this.overflowing && tabs.length > numPinned && numPinned > 0; -@@ -2127,7 +2185,7 @@ +@@ -2127,7 +2187,7 @@ if (this.verticalMode) { this._updateVerticalPinnedTabs(); @@ -363,7 +365,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let layoutData = this._pinnedTabsLayoutCache; let uiDensity = document.documentElement.getAttribute("uidensity"); if (!layoutData || layoutData.uiDensity != uiDensity) { -@@ -2191,7 +2249,7 @@ +@@ -2191,7 +2251,7 @@ return; } @@ -372,7 +374,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2199,7 +2257,7 @@ +@@ -2199,7 +2259,7 @@ dragData.animLastScreenX = screenX; let { width: tabWidth, height: tabHeight } = @@ -381,7 +383,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2262,7 +2320,7 @@ +@@ -2262,7 +2322,7 @@ // * We're doing a binary search in order to reduce the amount of // tabs we need to check. @@ -390,7 +392,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let firstTabCenterX = firstMovingTabScreenX + translateX + tabWidth / 2; let lastTabCenterX = lastMovingTabScreenX + translateX + tabWidth / 2; let tabCenterX = directionX ? lastTabCenterX : firstTabCenterX; -@@ -2374,12 +2432,16 @@ +@@ -2374,12 +2434,16 @@ this.#clearDragOverCreateGroupTimer(); @@ -412,7 +414,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff if (this.#rtlMode) { tabs.reverse(); -@@ -2393,7 +2455,7 @@ +@@ -2393,7 +2457,7 @@ let size = this.verticalMode ? "height" : "width"; let translateAxis = this.verticalMode ? "translateY" : "translateX"; let scrollDirection = this.verticalMode ? "scrollTop" : "scrollLeft"; @@ -421,7 +423,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let translateX = event.screenX - dragData.screenX; let translateY = event.screenY - dragData.screenY; -@@ -2407,12 +2469,21 @@ +@@ -2407,12 +2471,21 @@ let lastTab = tabs.at(-1); let lastMovingTab = movingTabs.at(-1); let firstMovingTab = movingTabs[0]; @@ -444,7 +446,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff translate += this.arrowScrollbox.scrollbox[scrollDirection] - dragData.scrollPos; } else if (isPinned && this.verticalMode) { -@@ -2431,12 +2502,15 @@ +@@ -2431,12 +2504,15 @@ // Shift the `.tab-group-label-container` to shift the label element. item = item.parentElement; } @@ -461,7 +463,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff /** * When the `draggedTab` is just starting to move, the `draggedTab` is in -@@ -2568,6 +2642,9 @@ +@@ -2568,6 +2644,9 @@ break; } let element = tabs[mid]; @@ -471,7 +473,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff let elementForSize = isTabGroupLabel(element) ? element.parentElement : element; -@@ -2588,7 +2665,11 @@ +@@ -2588,7 +2667,11 @@ let dropElement = getOverlappedElement(); if (!dropElement) { @@ -484,7 +486,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } let newDropElementIndex = dropElement ? dropElement.elementIndex -@@ -2598,7 +2679,7 @@ +@@ -2598,7 +2681,7 @@ let shouldCreateGroupOnDrop; let dropBefore; if (dropElement) { @@ -493,7 +495,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff ? dropElement.parentElement : dropElement; -@@ -2660,12 +2741,12 @@ +@@ -2660,12 +2743,12 @@ } } @@ -508,7 +510,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff dropElement != draggedTab && isTab(dropElement) && !dropElement?.group && -@@ -2735,7 +2816,7 @@ +@@ -2735,7 +2818,7 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let item of tabs) { @@ -517,7 +519,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff continue; } -@@ -2744,6 +2825,9 @@ +@@ -2744,6 +2827,9 @@ if (isTabGroupLabel(item)) { // Shift the `.tab-group-label-container` to shift the label element. item = item.parentElement; @@ -527,7 +529,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff } item.style.transform = transform; } -@@ -2796,8 +2880,9 @@ +@@ -2796,8 +2882,9 @@ ); } @@ -539,7 +541,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff return; } -@@ -2809,6 +2894,12 @@ +@@ -2809,6 +2896,12 @@ item = item.parentElement; } item.style.transform = ""; @@ -552,7 +554,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff item.removeAttribute("dragover-createGroup"); } this.removeAttribute("movingtab-createGroup"); -@@ -2855,7 +2946,7 @@ +@@ -2855,7 +2948,7 @@ let postTransitionCleanup = () => { movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -561,7 +563,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -3028,7 +3119,7 @@ +@@ -3028,7 +3121,7 @@ } _notifyBackgroundTab(aTab) { @@ -570,7 +572,7 @@ index ef9c0389ec926e6bc01c0dc3b883beceaf1f7d43..e8d5dc64609522b440fb01990fb19bff return; } -@@ -3154,6 +3245,9 @@ +@@ -3154,6 +3247,9 @@ return null; } } diff --git a/src/toolkit/content/widgets/tabbox-js.patch b/src/toolkit/content/widgets/tabbox-js.patch index 2f9b4ce79..f38c62061 100644 --- a/src/toolkit/content/widgets/tabbox-js.patch +++ b/src/toolkit/content/widgets/tabbox-js.patch @@ -1,5 +1,5 @@ diff --git a/toolkit/content/widgets/tabbox.js b/toolkit/content/widgets/tabbox.js -index 6775a7635c6cdbb276b3a912d0bba07840acb28f..4ef3eb6a7dbd741cf432668c2ff6e832f5bb97e7 100644 +index 6775a7635c6cdbb276b3a912d0bba07840acb28f..861640d12c6118e11acb3f51723a79098dbbba10 100644 --- a/toolkit/content/widgets/tabbox.js +++ b/toolkit/content/widgets/tabbox.js @@ -213,7 +213,7 @@ @@ -7,7 +7,7 @@ index 6775a7635c6cdbb276b3a912d0bba07840acb28f..4ef3eb6a7dbd741cf432668c2ff6e832 this._inAsyncOperation = false; if (oldPanel != this._selectedPanel) { - oldPanel?.classList.remove("deck-selected"); -+ if (!oldPanel?.classList.contains("zen-glance-background")) oldPanel?.classList.remove("deck-selected"); ++ if (!(window.gZenGlanceManager && gZenGlanceManager.shouldShowDeckSelected(this._selectedPanel, oldPanel))) oldPanel?.classList.remove("deck-selected"); this._selectedPanel?.classList.add("deck-selected"); } this.setAttribute("selectedIndex", val); diff --git a/src/zen/common/styles/zen-browser-container.css b/src/zen/common/styles/zen-browser-container.css index 003f52714..fe92eeb85 100644 --- a/src/zen/common/styles/zen-browser-container.css +++ b/src/zen/common/styles/zen-browser-container.css @@ -10,13 +10,15 @@ position: relative; overflow: hidden; - :root:not([zen-no-padding='true']) & { - border-radius: var(--zen-native-inner-radius); - box-shadow: var(--zen-big-shadow); - } + &.browserSidebarContainer { + :root:not([zen-no-padding='true']) & { + border-radius: var(--zen-native-inner-radius); + box-shadow: var(--zen-big-shadow); + } - & browser[transparent='true'] { - background: rgba(255, 255, 255, 0.1); + & browser[transparent='true'] { + background: rgba(255, 255, 255, 0.1); + } } } diff --git a/src/zen/glance/ZenGlanceManager.mjs b/src/zen/glance/ZenGlanceManager.mjs index 0e3e5e924..01477147e 100644 --- a/src/zen/glance/ZenGlanceManager.mjs +++ b/src/zen/glance/ZenGlanceManager.mjs @@ -720,6 +720,27 @@ } return tab; } + + shouldShowDeckSelected(currentPanel, oldPanel) { + // Dont remove if it's a glance background and current panel corresponds to a glance + const currentBrowser = currentPanel?.querySelector('browser'); + const oldBrowser = oldPanel?.querySelector('browser'); + if (!currentBrowser || !oldBrowser) { + return false; + } + const currentTab = gBrowser.getTabForBrowser(currentBrowser); + const oldTab = gBrowser.getTabForBrowser(oldBrowser); + if (currentTab && oldTab) { + const currentGlanceID = currentTab.getAttribute('glance-id'); + const oldGlanceID = oldTab.getAttribute('glance-id'); + if (currentGlanceID && oldGlanceID) { + return ( + currentGlanceID === oldGlanceID && oldPanel.classList.contains('zen-glance-background') + ); + } + } + return false; + } } window.gZenGlanceManager = new ZenGlanceManager(); diff --git a/src/zen/split-view/ZenViewSplitter.mjs b/src/zen/split-view/ZenViewSplitter.mjs index 136ac90b0..086f83386 100644 --- a/src/zen/split-view/ZenViewSplitter.mjs +++ b/src/zen/split-view/ZenViewSplitter.mjs @@ -335,6 +335,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { ]); if (this._finishAllAnimatingPromise) { this._finishAllAnimatingPromise.then(() => { + draggedTab.linkedBrowser.docShellIsActive = false; + draggedTab.linkedBrowser + .closest('.browserSidebarContainer') + .classList.remove('deck-selected'); this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit); this._canDrop = true; draggedTab._visuallySelected = true; @@ -1630,7 +1634,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { : containerRect.left - padding - 5, event.clientY ); - const browser = dropTarget?.closest('browser'); + const browser = + dropTarget?.closest('browser') ?? + dropTarget?.closest('.browserSidebarContainer')?.querySelector('browser'); if (!browser) { this._maybeRemoveFakeBrowser(false); @@ -1644,7 +1650,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { browserContainer.style.opacity = '0'; } - const droppedOnTab = gBrowser.getTabForBrowser(browser); + const droppedOnTab = gZenGlanceManager.getTabOrGlanceParent(gBrowser.getTabForBrowser(browser)); if (droppedOnTab && droppedOnTab !== draggedTab) { // Calculate which side of the target browser the drop occurred // const browserRect = browser.getBoundingClientRect(); diff --git a/surfer.json b/surfer.json index 2088c338c..494b1a3f6 100644 --- a/surfer.json +++ b/surfer.json @@ -19,7 +19,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.12.7b", + "displayVersion": "1.12.8b", "github": { "repo": "zen-browser/desktop" }, From cce90e6ddcc93b9b8a5b40d235820602f760eb50 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Thu, 22 May 2025 11:26:19 +0200 Subject: [PATCH 3/4] feat: Initially hide essentials that wont be required on the current workspace, b=(no-bug), c=workspaces --- README.md | 1 + src/zen/workspaces/ZenWorkspaces.mjs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/README.md b/README.md index fe060d312..31b1a7b5b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +