perf: Improved performance when switiching spaces, p=#12698

* perf: Improved performance when switiching spaces, b=no-bug, c=common, compact-mode, workspaces

* chore: format, b=no-bug, c=workspaces
This commit is contained in:
mr. m
2026-03-09 20:16:41 +01:00
committed by GitHub
parent 25c5740331
commit f718d4414e
10 changed files with 121 additions and 78 deletions

View File

@@ -21,7 +21,7 @@
"sync:raw": "surfer update",
"sync:rc": "python3 scripts/update_ff.py --rc",
"sync:l10n": "python3 scripts/update_ff.py --just-l10n",
"lint": "cd engine && ./mach lint zen",
"lint": "cd engine && ./mach lint zen/",
"lint:fix": "npm run lint -- --fix",
"prepare": "husky",
"reset-ff": "surfer reset",

View File

@@ -1,8 +1,18 @@
diff --git a/browser/base/content/browser-box.inc.xhtml b/browser/base/content/browser-box.inc.xhtml
index 2faed30e09511c381051bc40910a883d1d7bc10d..6ba2d0d91235ed33e4b4bad281c974b5960beaa2 100644
index 2faed30e09511c381051bc40910a883d1d7bc10d..3b8c89902502aa384473dd6f43be7ec49bad06ac 100644
--- a/browser/base/content/browser-box.inc.xhtml
+++ b/browser/base/content/browser-box.inc.xhtml
@@ -25,7 +25,13 @@
@@ -3,6 +3,9 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
<hbox flex="1" id="browser">
+ <html:div id="zen-browser-background" class="zen-browser-generic-background">
+ <html:div class="zen-browser-grain" />
+ </html:div>
<box context="sidebar-context-menu" id="sidebar-main" hidden="true">
<html:sidebar-main flex="1">
<box id="vertical-tabs" slot="tabstrip" customizable="true" contextmenu="toolbar-context-menu"></box>
@@ -25,7 +28,13 @@
</stack>
</vbox>
<splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
@@ -16,7 +26,7 @@ index 2faed30e09511c381051bc40910a883d1d7bc10d..6ba2d0d91235ed33e4b4bad281c974b5
<tabpanels id="tabbrowser-tabpanels" flex="1" selectedIndex="0"/>
</tabbox>
<splitter id="ai-window-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="none" resizeafter="sibling" hidden="true"/>
@@ -34,3 +40,5 @@
@@ -34,3 +43,5 @@
</stack>
</vbox>
</hbox>

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385a3bfe223 100644
index 4d4223c508560136aba220adb18528aac913a188..10d4d9cecbb0e7cec9191d78fb81a57376b37ff1 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -2,7 +2,7 @@
@@ -11,7 +11,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
<script src="chrome://browser/content/navigator-toolbox.js" />
<!-- Menu -->
@@ -18,9 +18,9 @@
@@ -18,9 +18,12 @@
#include browser-menubar.inc
</toolbaritem>
<spacer flex="1" skipintoolbarset="true" style="order: 1000;"/>
@@ -19,10 +19,13 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
</toolbar>
+<hbox id="titlebar">
+ <html:div id="zen-toolbar-background" class="zen-toolbar-background zen-browser-generic-background">
+ <html:div class="zen-browser-grain" />
+ </html:div>
<toolbar id="TabsToolbar"
class="browser-toolbar browser-titlebar"
fullscreentoolbar="true"
@@ -62,6 +62,9 @@
@@ -62,6 +65,9 @@
<html:sidebar-pins-promo id="drag-to-pin-promo-card"></html:sidebar-pins-promo>
<arrowscrollbox id="pinned-tabs-container" orient="horizontal" clicktoscroll=""></arrowscrollbox>
<splitter orient="vertical" id="vertical-pinned-tabs-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
@@ -32,7 +35,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
<hbox class="tab-drop-indicator" hidden="true"/>
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" clicktoscroll="" scrolledtostart="" scrolledtoend="">
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
@@ -81,6 +84,7 @@
@@ -81,6 +87,7 @@
tooltip="dynamic-shortcut-tooltip"
data-l10n-id="tabs-toolbar-new-tab"/>
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
@@ -40,7 +43,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
</tabs>
<toolbarbutton id="new-tab-button"
@@ -114,9 +118,10 @@
@@ -114,9 +121,10 @@
<toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/>

View File

@@ -14,7 +14,6 @@ class ZenStartup {
init() {
this.openWatermark();
this.#initBrowserBackground();
this.#changeSidebarLocation();
this.#zenInitBrowserLayout();
}
@@ -26,20 +25,6 @@ class ZenStartup {
);
}
#initBrowserBackground() {
const background = document.createXULElement("box");
background.id = "zen-browser-background";
background.classList.add("zen-browser-generic-background");
const grain = document.createXULElement("box");
grain.classList.add("zen-browser-grain");
background.appendChild(grain);
document.getElementById("browser").prepend(background);
const toolbarBackground = background.cloneNode(true);
toolbarBackground.removeAttribute("id");
toolbarBackground.classList.add("zen-toolbar-background");
document.getElementById("titlebar").prepend(toolbarBackground);
}
#zenInitBrowserLayout() {
if (this.#hasInitializedLayout) {
return;

View File

@@ -221,11 +221,11 @@ window.gZenUIManager = {
const kUrlbarHeight = 335;
gURLBar.style.setProperty(
"--zen-urlbar-top",
`${window.innerHeight / 2 - Math.max(kUrlbarHeight, gURLBar.getBoundingClientRect().height) / 2}px`
`${window.innerHeight / 2 - Math.max(kUrlbarHeight, window.windowUtils.getBoundsWithoutFlushing(gURLBar).height) / 2}px`
);
gURLBar.style.setProperty("--zen-urlbar-width", `${Math.min(window.innerWidth / 2, 750)}px`);
gZenVerticalTabsManager.actualWindowButtons.removeAttribute("zen-has-hover");
gZenVerticalTabsManager.recalculateURLBarHeight();
gZenVerticalTabsManager.recalculateURLBarHeight(true);
if (!this._preventToolbarRebuild) {
setTimeout(() => {
gZenWorkspaces.updateTabsContainers();
@@ -1052,7 +1052,7 @@ window.gZenVerticalTabsManager = {
}
},
recalculateURLBarHeight() {
recalculateURLBarHeight(updateFormat = false) {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
gURLBar.removeAttribute("--urlbar-height");
@@ -1065,7 +1065,9 @@ window.gZenVerticalTabsManager = {
if (typeof height !== "undefined") {
gURLBar.style.setProperty("--urlbar-height", `${height}px`);
}
gURLBar.zenFormatURLValue();
if (updateFormat) {
gURLBar.zenFormatURLValue();
}
});
});
},
@@ -1176,11 +1178,11 @@ window.gZenVerticalTabsManager = {
appContentNavbarContaienr.append(windowButtons);
}
if (isCompactMode) {
titlebar.prepend(navBar);
titlebar.prepend(topButtons);
titlebar.moveBefore(navBar, titlebar.firstChild);
titlebar.moveBefore(topButtons, titlebar.firstChild);
} else {
titlebar.before(topButtons);
titlebar.before(navBar);
titlebar.parentNode.moveBefore(topButtons, titlebar);
titlebar.parentNode.moveBefore(navBar, titlebar);
}
document.documentElement.setAttribute("zen-single-toolbar", true);
this._hasSetSingleToolbar = true;

View File

@@ -187,7 +187,7 @@ window.gZenCompactModeManager = {
// This function is called after exiting DOM fullscreen mode,
// so we do a bit of a hack to re-calculate the URL height
if (aInstant) {
gZenVerticalTabsManager.recalculateURLBarHeight();
gZenVerticalTabsManager.recalculateURLBarHeight(true);
}
if (
!aInstant &&
@@ -330,7 +330,6 @@ window.gZenCompactModeManager = {
await this.animateCompactMode();
this.callAllEventListeners();
}
gZenUIManager.updateTabsToolbar();
if (isUrlbarFocused) {
gURLBar.focus();
}

View File

@@ -654,7 +654,7 @@
}
let tabs = this.originalDragImageArgs[0].children;
const { isDarkMode, isExplicitMode } =
gZenThemePicker.getGradientForWorkspace(spaceChanged);
gZenThemePicker.getGradientForWorkspace(spaceChanged, { getGradient: false });
for (let tab of tabs) {
if (isExplicitMode) {
tab.style.colorScheme = isDarkMode ? "dark" : "light";

View File

@@ -53,6 +53,14 @@ ChromeUtils.defineLazyGetter(lazy, "MIN_OPACITY", () => {
return parseFloat(document.getElementById("PanelUI-zen-gradient-generator-opacity").min);
});
ChromeUtils.defineLazyGetter(lazy, "browserBackgroundElement", () => {
return document.getElementById("zen-browser-background");
});
ChromeUtils.defineLazyGetter(lazy, "toolbarBackgroundElement", () => {
return document.getElementById("zen-toolbar-background");
});
const EXPLICIT_LIGHTNESS_TYPE = "explicit-lightness";
const EXPLICIT_BLACKWHITE_TYPE = "explicit-black-white";
@@ -295,7 +303,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
initTextureInput() {
const wrapper = document.getElementById("PanelUI-zen-gradient-generator-texture-wrapper");
const wrapperWidth = wrapper.getBoundingClientRect().width;
const wrapperWidth = window.windowUtils.getBoundsWithoutFlushing(wrapper).width;
// Add elements in a circular pattern, where the center is the center of the wrapper
for (let i = 0; i < 16; i++) {
const dot = document.createElement("div");
@@ -322,7 +330,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
onTextureMouseMove(event) {
event.preventDefault();
const wrapper = document.getElementById("PanelUI-zen-gradient-generator-texture-wrapper");
const wrapperRect = wrapper.getBoundingClientRect();
const wrapperRect = window.windowUtils.getBoundsWithoutFlushing(wrapper);
// Determine how much rotation there is based on the mouse position and the center of the wrapper
const rotation = Math.atan2(
event.clientY - wrapperRect.top - wrapperRect.height / 2,
@@ -471,7 +479,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
getColorFromPosition(x, y, type = undefined) {
// Return a color as hsl based on the position in the gradient
const gradient = this.panel.querySelector(".zen-theme-picker-gradient");
const rect = gradient.getBoundingClientRect();
const rect = window.windowUtils.getBoundsWithoutFlushing(gradient);
const padding = 30; // each side
const dotHalfSize = 29; // half the size of the dot. -11 for correct centering
x += dotHalfSize;
@@ -747,7 +755,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
const dotPad = this.panel.querySelector(".zen-theme-picker-gradient");
const rect = dotPad.getBoundingClientRect();
const rect = window.windowUtils.getBoundsWithoutFlushing(dotPad);
const padding = 0;
let updatedDots = [...dots];
@@ -927,7 +935,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
const gradient = this.panel.querySelector(".zen-theme-picker-gradient");
const rect = gradient.getBoundingClientRect();
const rect = window.windowUtils.getBoundsWithoutFlushing(gradient);
const padding = 0;
const centerX = rect.left + rect.width / 2 - padding;
@@ -1059,7 +1067,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
onDotMouseMove(event) {
if (this.dragging) {
event.preventDefault();
const rect = this.panel.querySelector(".zen-theme-picker-gradient").getBoundingClientRect();
const rect = window.windowUtils.getBoundsWithoutFlushing(this.panel.querySelector(".zen-theme-picker-gradient"));
const padding = 0; // each side
// do NOT let the ball be draged outside of an imaginary circle. You can drag it anywhere inside the circle
// if the distance between the center of the circle and the dragged ball is bigger than the radius, then the ball
@@ -1354,6 +1362,14 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
return isDarkMode ? [255, 255, 255, opacity] : [0, 0, 0, opacity]; // Default toolbar
}
get browserBackgroundElement() {
return lazy.browserBackgroundElement;
}
get toolbarBackgroundElement() {
return lazy.toolbarBackgroundElement;
}
onWorkspaceChange(workspace, skipUpdate = false, theme = null) {
const uuid = workspace.uuid;
// Use theme from workspace object or passed theme
@@ -1369,16 +1385,16 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
return;
}
if (theme === null) {
browser.gZenThemePicker.invalidateGradientCache();
}
// Do not rebuild if the workspace is not the same as the current one
const windowWorkspace = browser.gZenWorkspaces.getActiveWorkspace();
if (windowWorkspace.uuid !== uuid) {
return;
}
if (theme === null) {
browser.gZenThemePicker.invalidateGradientCache(uuid);
}
// get the theme from the window
workspaceTheme = this.fixTheme(theme || windowWorkspace.theme);
const docElement = browser.document.documentElement;
@@ -1397,18 +1413,22 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
if (!skipUpdate) {
docElement.style.setProperty(
let backgroundElement = browser.gZenThemePicker.browserBackgroundElement;
let toolbarElement = browser.gZenThemePicker.toolbarBackgroundElement;
backgroundElement.style.setProperty(
"--zen-main-browser-background-old",
docElement.style.getPropertyValue("--zen-main-browser-background")
backgroundElement.style.getPropertyValue("--zen-main-browser-background")
);
docElement.style.setProperty(
toolbarElement.style.setProperty(
"--zen-main-browser-background-toolbar-old",
docElement.style.getPropertyValue("--zen-main-browser-background-toolbar")
);
docElement.style.setProperty(
"--zen-background-opacity",
browser.gZenThemePicker.previousBackgroundOpacity ?? 1
toolbarElement.style.getPropertyValue("--zen-main-browser-background-toolbar")
);
[backgroundElement, toolbarElement].forEach((element) => {
element.style.setProperty(
"--zen-background-opacity",
browser.gZenThemePicker.previousBackgroundOpacity ?? 1
);
});
if (browser.gZenThemePicker.previousBackgroundResolve) {
browser.gZenThemePicker.previousBackgroundResolve();
}
@@ -1490,7 +1510,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
const textureSelectWrapper = browser.document.getElementById(
"PanelUI-zen-gradient-generator-texture-wrapper"
);
const textureWrapperWidth = textureSelectWrapper.getBoundingClientRect().width;
const textureWrapperWidth = browser.windowUtils.getBoundsWithoutFlushing(textureSelectWrapper).width;
// Dont show when hidden
if (textureWrapperWidth) {
// rotate and trasnform relative to the wrapper width depending on the texture value
@@ -1532,8 +1552,12 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
}
}
docElement.style.setProperty("--zen-main-browser-background-toolbar", gradientToolbar);
docElement.style.setProperty("--zen-main-browser-background", gradient);
browser.gZenThemePicker.toolbarBackgroundElement
.style
.setProperty("--zen-main-browser-background-toolbar", gradientToolbar);
browser.gZenThemePicker.browserBackgroundElement
.style
.setProperty("--zen-main-browser-background", gradient);
const isDarkModeWindow = browser.gZenThemePicker.isDarkMode;
if (isDefaultTheme) {
docElement.setAttribute("zen-default-theme", "true");
@@ -1588,9 +1612,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
let accentColor = Services.prefs.getStringPref("zen.theme.accent-color");
let rgb;
if (accentColor === "AccentColor") {
const rawRgb = window.getComputedStyle(
document.getElementById("zen-browser-background")
).color;
const rawRgb = window.getComputedStyle(lazy.browserBackgroundElement).color;
rgb = rawRgb.match(/\d+/g).map(Number);
// Match our theme a bit more, since we can't always expect the OS
// to give us a color matching our theme scheme
@@ -1735,23 +1757,28 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
return newPathData.trim();
}
invalidateGradientCache() {
this.#gradientsCache = {};
invalidateGradientCache(uuid) {
delete this.#gradientsCache[uuid];
window.dispatchEvent(new Event("ZenGradientCacheChanged", { bubbles: true }));
}
getGradientForWorkspace(workspace) {
getGradientForWorkspace(workspace, { getGradient = true } = {}) {
const uuid = workspace.uuid;
if (this.#gradientsCache[uuid]) {
return this.#gradientsCache[uuid];
let cachedData = this.#gradientsCache[uuid];
if (cachedData && !(getGradient && !cachedData.gradient)) {
return cachedData;
}
const previousOpacity = this.currentOpacity;
const previousLightness = this.#currentLightness;
const theme = workspace.theme;
this.currentOpacity = theme.opacity ?? 0.5;
this.#currentLightness = theme.lightness ?? 50;
const gradient = this.getGradient(theme.gradientColors);
const toolbarGradient = this.getGradient(theme.gradientColors, true);
let gradient;
let toolbarGradient;
if (getGradient) {
gradient = this.getGradient(theme.gradientColors);
toolbarGradient = this.getGradient(theme.gradientColors, true);
}
let dominantColor = this.getMostDominantColor(theme.gradientColors);
const isDefaultTheme = !dominantColor;
if (isDefaultTheme) {

View File

@@ -361,7 +361,8 @@ export class nsZenWorkspace extends MozXULElement {
#onGradientCacheChanged() {
const { isDarkMode, isExplicitMode, toolbarColor, primaryColor } =
gZenThemePicker.getGradientForWorkspace(
gZenWorkspaces.getWorkspaceFromId(this.workspaceUuid)
gZenWorkspaces.getWorkspaceFromId(this.workspaceUuid),
{ getGradient: false }
);
if (isExplicitMode) {
this.style.colorScheme = isDarkMode ? "dark" : "light";

View File

@@ -12,6 +12,14 @@ ChromeUtils.defineESModuleGetters(lazy, {
ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
});
ChromeUtils.defineLazyGetter(lazy, "browserBackgroundElement", () => {
return document.getElementById("zen-browser-background");
});
ChromeUtils.defineLazyGetter(lazy, "toolbarBackgroundElement", () => {
return document.getElementById("zen-toolbar-background");
});
/**
* Zen Spaces manager. This class is mainly responsible for the UI
* and user interactions but it also contains some logic to manage
@@ -636,7 +644,9 @@ class nsZenWorkspaces {
Services.prefs.setBoolPref("zen.swipe.is-fast-swipe", false);
document.documentElement.removeAttribute("swipe-gesture");
gZenUIManager.tabsWrapper.style.removeProperty("scrollbar-width");
document.documentElement.style.setProperty("--zen-background-opacity", "1");
[lazy.browserBackgroundElement, lazy.toolbarBackgroundElement].forEach((element) => {
element.style.setProperty("--zen-background-opacity", "1");
});
delete this._hasAnimatedBackgrounds;
this.updateTabsContainers();
document.removeEventListener("popupshown", this.popupOpenHandler, { once: true });
@@ -1555,6 +1565,7 @@ class nsZenWorkspaces {
glanceTab.setAttribute("zen-workspace-id", workspaceID);
}
}
gBrowser.tabContainer._invalidateCachedTabs();
return true;
}
@@ -1781,14 +1792,16 @@ class nsZenWorkspaces {
} = gZenThemePicker.getGradientForWorkspace(nextWorkspace);
const existingGrain = gZenThemePicker.getGradientForWorkspace(workspace).grain;
const percentage = Math.abs(offsetPixels) / 200;
document.documentElement.style.setProperty("--zen-background-opacity", 1 - percentage);
[lazy.browserBackgroundElement, lazy.toolbarBackgroundElement].forEach((element) => {
element.style.setProperty("--zen-background-opacity", 1 - percentage);
});
if (!this._hasAnimatedBackgrounds) {
this._hasAnimatedBackgrounds = true;
document.documentElement.style.setProperty(
lazy.browserBackgroundElement.style.setProperty(
"--zen-main-browser-background-old",
nextGradient
);
document.documentElement.style.setProperty(
lazy.toolbarBackgroundElement.style.setProperty(
"--zen-main-browser-background-toolbar-old",
nextToolbarGradient
);
@@ -1885,7 +1898,7 @@ class nsZenWorkspaces {
}
document.documentElement.setAttribute("animating-background", "true");
if (shouldAnimate && previousWorkspace) {
let previousBackgroundOpacity = document.documentElement.style.getPropertyValue(
let previousBackgroundOpacity = lazy.browserBackgroundElement.style.getPropertyValue(
"--zen-background-opacity"
);
try {
@@ -1902,13 +1915,16 @@ class nsZenWorkspaces {
previousBackgroundOpacity = 1 - previousBackgroundOpacity;
}
gZenThemePicker.previousBackgroundOpacity = previousBackgroundOpacity;
document.documentElement.style.setProperty(
"--zen-background-opacity",
previousBackgroundOpacity
);
let elements = [lazy.browserBackgroundElement, lazy.toolbarBackgroundElement];
elements.forEach((element) => {
element.style.setProperty(
"--zen-background-opacity",
previousBackgroundOpacity
);
});
animations.push(
gZenUIManager.motion.animate(
document.documentElement,
elements,
{
"--zen-background-opacity": [previousBackgroundOpacity, 1],
},
@@ -2153,7 +2169,7 @@ class nsZenWorkspaces {
}
_shouldChangeToTab(aTab) {
return !(aTab?.pinned && aTab?.hasAttribute("pending"));
return !(aTab?.pinned && aTab?.hasAttribute("pending")) && !aTab?.closing;
}
async #shouldShowTabInCurrentWorkspace(tab) {