Bug 1334642 - Cache luminance values for each toolbar in ToolbarIconColor. r?dao draft
authorSam Foster <sfoster@mozilla.com>
Thu, 30 Mar 2017 17:02:25 -0700
changeset 553911 02163c09163824b79a655cb689fd439d3a2f1780
parent 553910 4b9d207f8121325dd03826cafd9d75f2d31b0655
child 622235 110462f4d4577b1685fa1d08d99cedd28fc9bc9c
push id51821
push userbmo:sfoster@mozilla.com
push dateFri, 31 Mar 2017 00:07:56 +0000
reviewersdao
bugs1334642
milestone55.0a1
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
browser/base/content/browser-fullScreenAndPointerLock.js
browser/base/content/browser-tabsintitlebar.js
browser/base/content/browser.js
--- 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