Bug 1334642 - Cache luminance values for each toolbar in ToolbarIconColor. r?dao
* Track window states: active, fullscreen and tabsintitlebar for each window
* Use toolbar.id and window state to store and retrieve values from cache
* Note: As each window has its own ToolbarIconColor object, the cache is not currently shared across windows
* inferFromText callers pass in a reason and associated value, which is used to update the state we track, and potentially clear out the cache
MozReview-Commit-ID: K9SObEhRD5N
--- a/browser/base/content/browser-fullScreenAndPointerLock.js
+++ b/browser/base/content/browser-fullScreenAndPointerLock.js
@@ -623,17 +623,18 @@ var FullScreen = {
if (el.hasAttribute("saved-context")) {
el.setAttribute("context", el.getAttribute("saved-context"));
el.removeAttribute("saved-context");
}
el.removeAttribute("inFullscreen");
}
}
- ToolbarIconColor.inferFromText();
+ ToolbarIconColor.inferFromText("fullscreen", aEnterFS);
+
// For Lion fullscreen, all fullscreen controls are hidden, don't
// bother to touch them. If we don't stop here, the following code
// could cause the native fullscreen button be shown unexpectedly.
// See bug 1165570.
if (this.useLionFullScreen) {
return;
}
--- a/browser/base/content/browser-tabsintitlebar.js
+++ b/browser/base/content/browser-tabsintitlebar.js
@@ -242,17 +242,18 @@ var TabsInTitlebar = {
// Reset the margins and padding that might have been modified:
titlebarContent.style.marginTop = "";
titlebarContent.style.marginBottom = "";
titlebar.style.marginBottom = "";
menubar.style.paddingBottom = "";
}
- ToolbarIconColor.inferFromText();
+ ToolbarIconColor.inferFromText("tabsintitlebar", TabsInTitlebar.enabled);
+
if (CustomizationHandler.isCustomizing()) {
gCustomizeMode.updateLWTStyling();
}
},
_sizePlaceholder(type, width) {
Array.forEach(document.querySelectorAll(".titlebar-placeholder[type='" + type + "']"),
function(node) { node.width = width; });
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5364,18 +5364,16 @@ function setToolbarVisibility(toolbar, i
},
bubbles: true
};
let event = new CustomEvent("toolbarvisibilitychange", eventParams);
toolbar.dispatchEvent(event);
PlacesToolbarHelper.init();
BookmarkingUI.onToolbarVisibilityChange();
- if (isVisible)
- ToolbarIconColor.inferFromText();
}
var TabletModeUpdater = {
init() {
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
this.update(WindowsUIUtils.inTabletMode);
Services.obs.addObserver(this, "tablet-mode-change", false);
}
@@ -8200,78 +8198,129 @@ var MousePosTracker = {
listener.onMouseEnter();
} else if (listener.onMouseLeave) {
listener.onMouseLeave();
}
}
};
var ToolbarIconColor = {
+ _windowState: {
+ "active": false,
+ "fullscreen": false,
+ "tabsintitlebar": false
+ },
init() {
this._initialized = true;
window.addEventListener("activate", this);
window.addEventListener("deactivate", this);
+ window.addEventListener("toolbarvisibilitychange", this);
Services.obs.addObserver(this, "lightweight-theme-styling-update", false);
// If the window isn't active now, we assume that it has never been active
// before and will soon become active such that inferFromText will be
// called from the initial activate event.
- if (Services.focus.activeWindow == window)
- this.inferFromText();
+ if (Services.focus.activeWindow == window) {
+ this.inferFromText("activate");
+ }
},
uninit() {
this._initialized = false;
window.removeEventListener("activate", this);
window.removeEventListener("deactivate", this);
+ window.removeEventListener("toolbarvisibilitychange", this);
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
},
handleEvent(event) {
switch (event.type) {
- case "activate":
+ case "activate": // falls through
case "deactivate":
- this.inferFromText();
+ this.inferFromText(event.type);
+ break;
+ case "toolbarvisibilitychange":
+ this.inferFromText(event.type, event.visible);
break;
}
},
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "lightweight-theme-styling-update":
// inferFromText needs to run after LightweightThemeConsumer.jsm's
// lightweight-theme-styling-update observer.
- setTimeout(() => { this.inferFromText(); }, 0);
+ setTimeout(() => {
+ this.inferFromText(aTopic);
+ }, 0);
break;
}
},
- inferFromText() {
+ // a cache of luminance values for each toolbar
+ // to avoid unnecessary calls to getComputedStyle
+ get _toolbarLuminanceCache() {
+ if (!this._toolbarLuminances) {
+ this._toolbarLuminances = new Map();
+ }
+ return this._toolbarLuminances;
+ },
+
+ inferFromText(reason, reasonValue) {
if (!this._initialized)
return;
function parseRGB(aColorString) {
let rgb = aColorString.match(/^rgba?\((\d+), (\d+), (\d+)/);
rgb.shift();
return rgb.map(x => parseInt(x));
}
+ switch (reason) {
+ case "activate": // falls through
+ case "deactivate":
+ this._windowState.active = (reason === "activate");
+ break;
+ case "fullscreen":
+ this._windowState.fullscreen = reasonValue
+ break;
+ case "lightweight-theme-styling-update":
+ // theme change, we'll need to recalculate all color values
+ this._toolbarLuminanceCache.clear();
+ break;
+ case "toolbarvisibilitychange":
+ // toolbar changes dont require reset of the caches color values
+ break;
+ case "tabsintitlebar":
+ this._windowState.tabsintitlebar = reasonValue;
+ break;
+ }
+
let toolbarSelector = "#navigator-toolbox > toolbar:not([collapsed=true]):not(#addon-bar)";
if (AppConstants.platform == "macosx")
toolbarSelector += ":not([type=menubar])";
// The getComputedStyle calls and setting the brighttext are separated in
// two loops to avoid flushing layout and making it dirty repeatedly.
-
- let luminances = new Map;
+ let cachedLuminances = this._toolbarLuminanceCache;
+ let luminances = new Map();
for (let toolbar of document.querySelectorAll(toolbarSelector)) {
- let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
- let luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
+ // toolbars *should* all have ids, but guard anyway to avoid blowing up
+ let cacheKey = toolbar.id && toolbar.id + JSON.stringify(this._windowState);
+ // lookup cached luminance value for this toolbar in this window state
+ let luminance = cacheKey && cachedLuminances.get(cacheKey);
+ if (isNaN(luminance)) {
+ let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
+ luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
+ if (cacheKey) {
+ cachedLuminances.set(cacheKey, luminance);
+ }
+ }
luminances.set(toolbar, luminance);
}
for (let [toolbar, luminance] of luminances) {
if (luminance <= 110)
toolbar.removeAttribute("brighttext");
else
toolbar.setAttribute("brighttext", "true");