Bug 1334642 - Cache luminance values for each toolbar in ToolbarIconColor. r?dao draft
authorSam Foster <sfoster@mozilla.com>
Fri, 10 Mar 2017 14:15:18 -0800
changeset 500752 485c19ab1f389b40823adddfda68ad0e430202da
parent 500751 b7ba1d2827750be9bc599ca5365aa350ae3995d3
child 500753 3718931b7702114e096df97b167c3704853f785a
push id49786
push userbmo:sfoster@mozilla.com
push dateFri, 17 Mar 2017 16:12:29 +0000
reviewersdao
bugs1334642
milestone55.0a1
Bug 1334642 - Cache luminance values for each toolbar in ToolbarIconColor. r?dao * Add ToolbarIconColor.reCalculate to do the inferFromText work from a clear luminance cache * Call reCalculate rather than inferFromText when lw-theme changes, when toolbars are shown/hidden * Track window active/inactive state in ToolbarIconColor and cache luminance values separately for each state MozReview-Commit-ID: 45kufMb7K1x
browser/base/content/browser-tabsintitlebar.js
browser/base/content/browser.js
--- a/browser/base/content/browser-tabsintitlebar.js
+++ b/browser/base/content/browser-tabsintitlebar.js
@@ -242,17 +242,17 @@ 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.reCalculate();
     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
@@ -5355,18 +5355,19 @@ function setToolbarVisibility(toolbar, i
     },
     bubbles: true
   };
   let event = new CustomEvent("toolbarvisibilitychange", eventParams);
   toolbar.dispatchEvent(event);
 
   PlacesToolbarHelper.init();
   BookmarkingUI.onToolbarVisibilityChange();
-  if (isVisible)
-    ToolbarIconColor.inferFromText();
+  if (isVisible) {
+    ToolbarIconColor.reCalculate();
+  }
 }
 
 var TabletModeUpdater = {
   init() {
     if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
       this.update(WindowsUIUtils.inTabletMode);
       Services.obs.addObserver(this, "tablet-mode-change", false);
     }
@@ -8146,78 +8147,108 @@ var MousePosTracker = {
         listener.onMouseEnter();
     } else if (listener.onMouseLeave) {
       listener.onMouseLeave();
     }
   }
 };
 
 var ToolbarIconColor = {
+  _isActiveWindow: false,
   init() {
     this._initialized = true;
 
     window.addEventListener("activate", this);
     window.addEventListener("deactivate", 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.reCalculate();
+    }
   },
 
   uninit() {
     this._initialized = false;
+    this._toolbarLuminances = null;
 
     window.removeEventListener("activate", this);
     window.removeEventListener("deactivate", this);
     Services.obs.removeObserver(this, "lightweight-theme-styling-update");
   },
 
   handleEvent(event) {
     switch (event.type) {
       case "activate":
+        this._isActiveWindow = true;
+        this.inferFromText();
+        break;
       case "deactivate":
+        this._isActiveWindow = false;
         this.inferFromText();
         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(() => {
+          // invalidate the cached luminance values on the toobars
+          this.reCalculate();
+        }, 0);
         break;
     }
   },
 
+  // a cache of luminance values for each toolbar
+  // to avoid unnecessary calls to getComputedStyle
+  _toolbarLuminances: null,
+
+  reCalculate: function() {
+    this._toolbarLuminances = null;
+    this.inferFromText();
+  },
+
   inferFromText() {
     if (!this._initialized)
       return;
 
+    let idSuffix = this._isActiveWindow ? '-active-' : '-inactive';
     function parseRGB(aColorString) {
       let rgb = aColorString.match(/^rgba?\((\d+), (\d+), (\d+)/);
       rgb.shift();
       return rgb.map(x => parseInt(x));
     }
 
     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._toolbarLuminances || (
+      this._toolbarLuminances = new Map());
+    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+idSuffix;
+      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");