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: 7QV4op8JzQC
--- 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.reCalculate();
+ 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,19 +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);
}
@@ -8201,115 +8198,131 @@ var MousePosTracker = {
listener.onMouseEnter();
} else if (listener.onMouseLeave) {
listener.onMouseLeave();
}
}
};
var ToolbarIconColor = {
- _isActiveWindow: false,
+ _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();
+ this.inferFromText("activate");
}
},
uninit() {
this._initialized = false;
- this._toolbarLuminances = null;
window.removeEventListener("activate", this);
window.removeEventListener("deactivate", this);
+ window.removeEventListener("toolbarvisibilitychange", this);
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
},
handleEvent(event) {
- console.log("ToolbarIconColor.handleEvent: ", event.type);
switch (event.type) {
- case "activate":
- this._isActiveWindow = true;
- this.inferFromText();
+ case "activate": // falls through
+ case "deactivate":
+ this.inferFromText(event.type);
break;
- case "deactivate":
- this._isActiveWindow = false;
- this.inferFromText();
+ 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(() => {
- // invalidate the cached luminance values on the toobars
- this.reCalculate();
+ this.inferFromText(aTopic);
}, 0);
break;
}
},
// a cache of luminance values for each toolbar
// to avoid unnecessary calls to getComputedStyle
- _toolbarLuminances: null,
-
- reCalculate: function() {
- this._toolbarLuminances = null;
- console.log('ToolbarIconColor.reCalculate, flushed _toolbarLuminances cache');
- this.inferFromText();
- },
-
- inferFromText() {
+ 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":
+ if (reasonValue) {
+ // a toolbar was shown, we'll need to recalculate all color values
+ this._toolbarLuminanceCache.clear();
+ }
+ 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 cachedLuminances = this._toolbarLuminances || (
- this._toolbarLuminances = new Map());
+ let cachedLuminances = this._toolbarLuminanceCache;
let luminances = new Map();
for (let toolbar of document.querySelectorAll(toolbarSelector)) {
// toolbars *should* all have ids, but guard anyway to avoid blowing up
- let cacheKey = toolbar.id && JSON.stringify({
- id: toolbar.id,
- active: this._isActiveWindow
- });
+ 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)) {
- console.log("ToolbarIconColor.inferFromText, no cached value for: ", cacheKey);
let [r, g, b] = parseRGB(getComputedStyle(toolbar).color);
luminance = 0.2125 * r + 0.7154 * g + 0.0721 * b;
if (cacheKey) {
- console.log("ToolbarIconColor.inferFromText, caching: ", luminance);
cachedLuminances.set(cacheKey, luminance);
}
- } else {
- console.log("ToolbarIconColor.inferFromText, using cached value for: ", cacheKey);
}
luminances.set(toolbar, luminance);
}
for (let [toolbar, luminance] of luminances) {
if (luminance <= 110)
toolbar.removeAttribute("brighttext");
else