From d9c6dcdca475eef77a99be10b3a4904ea6f0a580 Mon Sep 17 00:00:00 2001 From: "mr. m" <91018726+mr-cheffy@users.noreply.github.com> Date: Sat, 9 May 2026 18:20:05 +0200 Subject: [PATCH] no-bug: Improve space swipe performance (gh-13631) --- prefs/zen/workspaces.yaml | 2 +- src/widget/SwipeTracker-cpp.patch | 14 +++++-- src/zen/common/modules/ZenUIManager.mjs | 8 +++- src/zen/common/styles/zen-browser-ui.css | 4 +- src/zen/common/styles/zen-omnibox.css | 1 + src/zen/spaces/ZenSpaceManager.mjs | 53 +++++++++++++++--------- src/zen/spaces/ZenSpacesSwipe.mjs | 19 +-------- src/zen/spaces/zen-workspaces.css | 9 ++-- 8 files changed, 64 insertions(+), 46 deletions(-) diff --git a/prefs/zen/workspaces.yaml b/prefs/zen/workspaces.yaml index aeddd6802..24aaf887c 100644 --- a/prefs/zen/workspaces.yaml +++ b/prefs/zen/workspaces.yaml @@ -18,7 +18,7 @@ value: true - name: zen.workspaces.swipe-actions.delta-multiplier - value: 90 + value: 100 - name: zen.workspaces.switch-animation-duration value: 200 diff --git a/src/widget/SwipeTracker-cpp.patch b/src/widget/SwipeTracker-cpp.patch index 54dd51238..965a670ea 100644 --- a/src/widget/SwipeTracker-cpp.patch +++ b/src/widget/SwipeTracker-cpp.patch @@ -1,5 +1,5 @@ diff --git a/widget/SwipeTracker.cpp b/widget/SwipeTracker.cpp -index 887d06d3bd9cdaa934880e0ae7a11ec8b737fb61..7225d4264c9ec71ef1e5e717a1a62c4ef0aff0b7 100644 +index 887d06d3bd9cdaa934880e0ae7a11ec8b737fb61..979f93ddab0d661ac1a1d73e7a0ba27fa2c8f9b7 100644 --- a/widget/SwipeTracker.cpp +++ b/widget/SwipeTracker.cpp @@ -3,6 +3,7 @@ @@ -20,7 +20,15 @@ index 887d06d3bd9cdaa934880e0ae7a11ec8b737fb61..7225d4264c9ec71ef1e5e717a1a62c4e // gestureAmount needs to stay between -1 and 0 when swiping right and // between 0 and 1 when swiping left. double min = -@@ -90,7 +94,7 @@ bool SwipeTracker::ComputeSwipeSuccess() const { +@@ -84,13 +88,14 @@ bool SwipeTracker::ComputeSwipeSuccess() const { + // If the fingers were moving away from the target direction when they were + // lifted from the touchpad, abort the swipe. + if (mCurrentVelocity * targetValue < +- -StaticPrefs::widget_swipe_velocity_twitch_tolerance()) { ++ -StaticPrefs::widget_swipe_velocity_twitch_tolerance() ++ && !StaticPrefs::zen_swipe_is_fast_swipe()) { + return false; + } return (mGestureAmount * targetValue + mCurrentVelocity * targetValue * @@ -29,7 +37,7 @@ index 887d06d3bd9cdaa934880e0ae7a11ec8b737fb61..7225d4264c9ec71ef1e5e717a1a62c4e kSwipeSuccessThreshold; } -@@ -141,7 +145,8 @@ nsEventStatus SwipeTracker::ProcessEvent( +@@ -141,7 +146,8 @@ nsEventStatus SwipeTracker::ProcessEvent( // display the UI as if we were at the success threshold as that would // give a false indication that navigation would happen. if (!computedSwipeSuccess && (eventAmount >= kSwipeSuccessThreshold || diff --git a/src/zen/common/modules/ZenUIManager.mjs b/src/zen/common/modules/ZenUIManager.mjs index e61847427..541574d77 100644 --- a/src/zen/common/modules/ZenUIManager.mjs +++ b/src/zen/common/modules/ZenUIManager.mjs @@ -698,10 +698,16 @@ window.gZenUIManager = { this.urlbarShowDomainOnly ) { let url = BrowserUIUtils.removeSingleTrailingSlashFromURL(aURL); - requestIdleCallback(() => { + requestAnimationFrame(() => { + const hoverAttr = "zen-has-implicit-hover"; + const hasHover = gNavToolbox.hasAttribute(hoverAttr); + gNavToolbox.removeAttribute(hoverAttr); // Scroll the urlbar all the way to the right so that // the domain is always visible when the url is too long. gURLBar.inputField.scrollLeft = gURLBar.inputField.scrollWidth; + if (hasHover) { + gNavToolbox.setAttribute(hoverAttr, true); + } }); let stripped = url.startsWith("https://") ? url.split("/")[2] : url; if (stripped.startsWith("www.")) { diff --git a/src/zen/common/styles/zen-browser-ui.css b/src/zen/common/styles/zen-browser-ui.css index 6618d653e..42e2afe15 100644 --- a/src/zen/common/styles/zen-browser-ui.css +++ b/src/zen/common/styles/zen-browser-ui.css @@ -45,6 +45,7 @@ body, overflow: clip; isolation: isolate; + contain: content; &::after, &::before { @@ -53,6 +54,7 @@ body, inset: 0; z-index: 0; pointer-events: none; + will-change: background-color; } &::after { @@ -106,8 +108,6 @@ body, } #zen-browser-background { - contain: paint; - /* This is conceptually a background, but putting this on a pseudo-element * avoids it from suppressing the chrome-content separator border, etc. * diff --git a/src/zen/common/styles/zen-omnibox.css b/src/zen/common/styles/zen-omnibox.css index 373598eb2..7a54ffe91 100644 --- a/src/zen/common/styles/zen-omnibox.css +++ b/src/zen/common/styles/zen-omnibox.css @@ -120,6 +120,7 @@ #urlbar .urlbar-input { border-radius: 0 !important; + color: color-mix(in srgb, var(--input-color, FieldText) 70%, transparent); } #urlbar .urlbar-input-box { diff --git a/src/zen/spaces/ZenSpaceManager.mjs b/src/zen/spaces/ZenSpaceManager.mjs index a9585ad00..391a60e1b 100644 --- a/src/zen/spaces/ZenSpaceManager.mjs +++ b/src/zen/spaces/ZenSpaceManager.mjs @@ -1983,26 +1983,41 @@ class nsZenWorkspaces { ); const offset = -(newWorkspaceIndex - elementWorkspaceIndex) * 100; const newTransform = `translateX(${offset}%)`; + // Only animate the workspace that is coming in, to avoid having multiple workspaces + // animating off-screen at the same time which can cause performance issues. With an off + // set of 1 or -1, so we animate the current workspace and the next one. + const goingLeft = newWorkspaceIndex < previousWorkspaceIndex; + const willBeVisible = + (goingLeft && + elementWorkspaceIndex >= newWorkspaceIndex && + elementWorkspaceIndex <= previousWorkspaceIndex) || + (!goingLeft && + elementWorkspaceIndex <= newWorkspaceIndex && + elementWorkspaceIndex >= previousWorkspaceIndex); if (shouldAnimate) { - const existingPaddingTop = element.style.paddingTop; - animations.push( - gZenUIManager.motion.animate( - element, - { - transform: existingTransform - ? [existingTransform, newTransform] - : newTransform, - paddingTop: existingTransform - ? [existingPaddingTop, existingPaddingTop] - : existingPaddingTop, - }, - { - type: "spring", - bounce: 0, - duration: kGlobalAnimationDuration, - } - ) - ); + if (!willBeVisible) { + element.style.transform = newTransform; + } else { + const existingPaddingTop = element.style.paddingTop; + animations.push( + gZenUIManager.motion.animate( + element, + { + transform: existingTransform + ? [existingTransform, newTransform] + : newTransform, + paddingTop: existingTransform + ? [existingPaddingTop, existingPaddingTop] + : existingPaddingTop, + }, + { + type: "spring", + bounce: 0, + duration: kGlobalAnimationDuration, + } + ) + ); + } } element.active = offset === 0; if (offset === 0) { diff --git a/src/zen/spaces/ZenSpacesSwipe.mjs b/src/zen/spaces/ZenSpacesSwipe.mjs index 7576efcc1..eea00519d 100644 --- a/src/zen/spaces/ZenSpacesSwipe.mjs +++ b/src/zen/spaces/ZenSpacesSwipe.mjs @@ -20,22 +20,7 @@ export class ZenSpacesSwipe { }; constructor() { - const elements = [ - gNavToolbox, - // Event handlers do not work on elements inside shadow DOM - // so we need to attach them directly. - document - .getElementById("tabbrowser-arrowscrollbox") - ?.shadowRoot?.querySelector("scrollbox"), - ]; - - for (const element of elements) { - if (!element) { - continue; - } - this._attachWorkspaceSwipeGestures(element); - } - + this.#attachWorkspaceSwipeGestures(gNavToolbox); this._popupOpenHandler = this._popupOpenHandler.bind(this); } @@ -50,7 +35,7 @@ export class ZenSpacesSwipe { ); } - _attachWorkspaceSwipeGestures(element) { + #attachWorkspaceSwipeGestures(element) { element.addEventListener( "MozSwipeGestureMayStart", this._handleSwipeMayStart.bind(this), diff --git a/src/zen/spaces/zen-workspaces.css b/src/zen/spaces/zen-workspaces.css index 56c1c0719..3cfda3ccb 100644 --- a/src/zen/spaces/zen-workspaces.css +++ b/src/zen/spaces/zen-workspaces.css @@ -11,7 +11,6 @@ align-items: center; display: flex; font-size: x-small; - margin: 0 3px; padding: 0; position: relative; @@ -347,8 +346,12 @@ zen-workspace { overflow-y: auto; } - :root[swipe-gesture] &::part(scrollbox) { - scrollbar-width: none; + :root[swipe-gesture] &{ + pointer-events: none; + + &::part(scrollbox) { + scrollbar-width: none; + } } &[overflowing] {