Bug 741228 - Add a small element cache to reduce time spent finding clickable elements. r=wesj
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 09 Apr 2012 12:08:08 -0500
changeset 94565 9a736b04b47fb62fdf549ce697f60d8d65c49a3d
parent 94564 147324800246e0e86db097b4fb0803c3422fef64
child 94566 f5d6cc2e47260ec824438c5a2caae64cd9f5f62e
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswesj
bugs741228
milestone14.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 741228 - Add a small element cache to reduce time spent finding clickable elements. r=wesj
mobile/android/chrome/content/browser.js
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2710,30 +2710,33 @@ const ElementTouchHelper = {
       this.dpiRatio = aWindowUtils.displayDPI / kReferenceDpi;
 
     let dpiRatio = this.dpiRatio;
 
     let target = aWindowUtils.elementFromPoint(aX, aY,
                                                true,   /* ignore root scroll frame*/
                                                false); /* don't flush layout */
 
-    // if this element is clickable we return quickly
-    if (this.isElementClickable(target))
+    // if this element is clickable we return quickly. also, if it isn't,
+    // use a cache to speed up future calls to isElementClickable in the
+    // loop below.
+    let unclickableCache = new Array();
+    if (this.isElementClickable(target, unclickableCache))
       return target;
 
     let target = null;
     let nodes = aWindowUtils.nodesFromRect(aX, aY, this.radius.top * dpiRatio,
                                                    this.radius.right * dpiRatio,
                                                    this.radius.bottom * dpiRatio,
                                                    this.radius.left * dpiRatio, true, false);
 
     let threshold = Number.POSITIVE_INFINITY;
     for (let i = 0; i < nodes.length; i++) {
       let current = nodes[i];
-      if (!current.mozMatchesSelector || !this.isElementClickable(current))
+      if (!current.mozMatchesSelector || !this.isElementClickable(current, unclickableCache))
         continue;
 
       let rect = current.getBoundingClientRect();
       let distance = this._computeDistanceFromRect(aX, aY, rect);
 
       // increase a little bit the weight for already visited items
       if (current && current.mozMatchesSelector("*:visited"))
         distance *= (this.weight.visited / 100);
@@ -2742,23 +2745,27 @@ const ElementTouchHelper = {
         target = current;
         threshold = distance;
       }
     }
 
     return target;
   },
 
-  isElementClickable: function isElementClickable(aElement) {
+  isElementClickable: function isElementClickable(aElement, aUnclickableCache) {
     const selector = "a,:link,:visited,[role=button],button,input,select,textarea,label";
     for (let elem = aElement; elem; elem = elem.parentNode) {
+      if (aUnclickableCache && aUnclickableCache.indexOf(elem) != -1)
+        continue;
       if (this._hasMouseListener(elem))
         return true;
       if (elem.mozMatchesSelector && elem.mozMatchesSelector(selector))
         return true;
+      if (aUnclickableCache)
+        aUnclickableCache.push(elem);
     }
     return false;
   },
 
   _computeDistanceFromRect: function _computeDistanceFromRect(aX, aY, aRect) {
     let x = 0, y = 0;
     let xmost = aRect.left + aRect.width;
     let ymost = aRect.top + aRect.height;