Bug 559829 - Click on an entry in search suggestions drop-down activates a link underneath (the list is click-transparent) [r=mfinkle]
authorVivien Nicolas <21@vingtetun.org>
Tue, 04 May 2010 11:15:57 -0400
changeset 66202 e3a2a34f96be56c6626bf9b5f39b0ce9cb60e3e0
parent 66201 0d3d8b7501694421a8e1c981cc149e2f17e0a46f
child 66203 2f699b1988bebfa236f8ad205066bce390fb79fe
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs559829
Bug 559829 - Click on an entry in search suggestions drop-down activates a link underneath (the list is click-transparent) [r=mfinkle]
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1155,22 +1155,20 @@ var Browser = {
     let zoomRect = null;
     let element = this.elementFromPoint(elementX, elementY);
     let bv = this._browserView;
     if (element)
       zoomRect = this._getZoomRectForElement(element, elementY);
     if (!zoomRect && bv.isDefaultZoom())
       zoomRect = this._getZoomRectForPoint(elementX, elementY, bv.getZoomLevel() * 2);
 
-    if (zoomRect) {
+    if (zoomRect)
       this.setVisibleRect(zoomRect);
-      return true;
-    } else {
-      return false;
-    }
+
+    return zoomRect;
   },
 
   zoomFromPoint: function zoomFromPoint(cX, cY) {
     let bv = this._browserView;
     if (!bv.isDefaultZoom()) {
       let zoomLevel = bv.getDefaultZoomLevel();
       let [elementX, elementY] = this.transformClientToBrowser(cX, cY);
       let zoomRect = this._getZoomRectForPoint(elementX, elementY, zoomLevel);
@@ -1945,25 +1943,25 @@ const ElementTouchHelper = {
   },
 
   /* Retrieve the closest element to a point by looking at borders position */
   getClosest: function getClosest(aWindowUtils, aX, aY) {
     let target = aWindowUtils.elementFromPoint(aX, aY,
                                                true,   /* ignore root scroll frame*/
                                                false); /* don't flush layout */
 
-    // return early if the click is just over a clickable element
-    if (this._isElementClickable(target))
-      return target;
-
     let nodes = aWindowUtils.nodesFromRect(aX, aY, this.radius.bottom,
                                                    this.radius.right,
                                                    this.radius.top,
                                                    this.radius.left, true, false);
 
+    // return early if the click is just over a clickable element
+    if (this._isElementClickable(target, nodes))
+      return target;
+
     let threshold = Number.POSITIVE_INFINITY;
     for (let i = 0; i < nodes.length; i++) {
       let current = nodes[i];
       if (!current.mozMatchesSelector || !this._isElementClickable(current))
         continue;
 
       let rect = current.getBoundingClientRect();
       let distance = this._computeDistanceFromRect(aX, aY, rect);
@@ -1976,18 +1974,47 @@ const ElementTouchHelper = {
         target = current;
         threshold = distance;
       }
     }
 
     return target;
   },
 
-  _isElementClickable: function _isElementClickable(aElement) {
-    return aElement && aElement.mozMatchesSelector("*:link,*:visited,*[role=button],button,input,select,label");
+  _els: Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService),
+  _clickableEvents: ["mousedown", "mouseup", "click"],
+  _hasMouseListener: function _hasMouseListener(aElement) {
+    let els = this._els;
+    let listeners = els.getListenerInfoFor(aElement, {});
+    for (let i = 0; i < listeners.length; i++) {
+      if (this._clickableEvents.indexOf(listeners[i].type) != -1)
+        return true;
+    }
+  },
+
+  _isElementClickable: function _isElementClickable(aElement, aElementsInRect) {
+    let isClickable = this._hasMouseListener(aElement);
+
+    // If possible looks in the parents node to find a target
+    if (!isClickable && aElementsInRect) {
+      let parentNode = aElement.parentNode;
+      let count = aElementsInRect.length;
+      for (let i = 0; i < count && parentNode; i++) {
+        if (aElementsInRect[i] != parentNode)
+          continue;
+
+        isClickable = this._hasMouseListener(parentNode);
+        if (isClickable)
+          break;
+
+        parentNode = parentNode.parentNode;
+      }
+    }
+
+    return aElement && (isClickable || aElement.mozMatchesSelector("*:link,*:visited,*[role=button],button,input,select,label"));
   },
 
   _computeDistanceFromRect: function _computeDistanceFromRect(aX, aY, aRect) {
     let x = 0, y = 0;
     let xmost = aRect.left + aRect.width;
     let ymost = aRect.top + aRect.height;
 
     // compute horizontal distance from left/right border depending if X is