Bug 1071635 - Get rid of uninterruptible reflows caused by checkSizing() and onPageFirstSized() r=adw
authorTim Taubert <ttaubert@mozilla.com>
Tue, 23 Sep 2014 19:08:56 +0200
changeset 230453 f191b431571c54d96c8ba73ea51ac02c14095e7f
parent 230415 d90133c40a646f81103d826d1611164da0f7d949
child 230454 77ae1deb677a891e5a6bec2648e1fd5383cd981a
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw
bugs1071635
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1071635 - Get rid of uninterruptible reflows caused by checkSizing() and onPageFirstSized() r=adw
browser/base/content/newtab/page.js
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -137,16 +137,19 @@ let gPage = {
     }
   },
 
   /**
    * Handles all page events.
    */
   handleEvent: function Page_handleEvent(aEvent) {
     switch (aEvent.type) {
+      case "load":
+        this.onPageVisibleAndLoaded();
+        break;
       case "unload":
         gAllPages.unregister(this);
         break;
       case "click":
         let {button, target} = aEvent;
         // Go up ancestors until we find a Site or not
         while (target) {
           if (target.hasOwnProperty("_newtabSite")) {
@@ -178,44 +181,46 @@ let gPage = {
     Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
 
     for (let site of gGrid.sites) {
       if (site) {
         site.captureIfMissing();
       }
     }
 
-    // Allow the document to reflow so the page has sizing info
-    let i = 0;
-    let checkSizing = _ => setTimeout(_ => {
-      if (document.documentElement.clientWidth == 0) {
-        checkSizing();
-      }
-      else {
-        this.onPageFirstSized();
-      }
-    });
-    checkSizing();
+    if (document.readyState == "complete") {
+      this.onPageVisibleAndLoaded();
+    } else {
+      addEventListener("load", this);
+    }
+  },
+
+  onPageVisibleAndLoaded() {
+    // Send the index of the last visible tile.
+    this.reportLastVisibleTileIndex();
+
+    // Show the panel now that anchors are sized
+    gIntro.showIfNecessary();
   },
 
-  onPageFirstSized: function() {
-    // Work backwards to find the first visible site from the end
-    let {sites} = gGrid;
-    let lastIndex = sites.length;
-    while (lastIndex-- > 0) {
-      let site = sites[lastIndex];
-      if (site) {
-        let {node} = site;
-        let rect = node.getBoundingClientRect();
-        let target = document.elementFromPoint(rect.x + rect.width / 2,
-                                               rect.y + rect.height / 2);
-        if (node.contains(target)) {
-          break;
+  reportLastVisibleTileIndex() {
+    let cwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                    .getInterface(Ci.nsIDOMWindowUtils);
+
+    let rect = cwu.getBoundsWithoutFlushing(gGrid.node);
+    let nodes = cwu.nodesFromRect(rect.left, rect.top, 0, rect.width,
+                                  rect.height, 0, true, false);
+
+    let i = -1;
+    let lastIndex = -1;
+    let sites = gGrid.sites;
+
+    for (let node of nodes) {
+      if (node.classList && node.classList.contains("newtab-cell")) {
+        if (sites[++i]) {
+          lastIndex = i;
         }
       }
     }
 
-    DirectoryLinksProvider.reportSitesAction(gGrid.sites, "view", lastIndex);
-
-    // Show the panel now that anchors are sized
-    gIntro.showIfNecessary();
+    DirectoryLinksProvider.reportSitesAction(sites, "view", lastIndex);
   }
 };