Bug 1542756 - Bug 1543128 - Add option to only return visible nodes from nsIDOMWindowUtils.nodesFromRect. r=emilio
authorMike Conley <mconley@mozilla.com>
Mon, 15 Apr 2019 01:08:12 +0000
changeset 469459 7900dcbab822a5078491838b5fae04d66c20e975
parent 469458 bd90178236758c38c1a9ed11b753d3c2eee25c1b
child 469460 15eaea4c4c08bf3bc74f0bf45b97bb1bbf585deb
push id112792
push userncsoregi@mozilla.com
push dateMon, 15 Apr 2019 09:49:11 +0000
treeherdermozilla-inbound@a57f27d3ccd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1542756, 1543128
milestone68.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 1542756 - Bug 1543128 - Add option to only return visible nodes from nsIDOMWindowUtils.nodesFromRect. r=emilio Depends on D26778 Differential Revision: https://phabricator.services.mozilla.com/D26809
browser/components/downloads/content/allDownloadsView.js
dom/base/DocumentOrShadowRoot.cpp
dom/base/DocumentOrShadowRoot.h
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/tests/mochitest/chrome/489127.html
toolkit/actors/PictureInPictureChild.jsm
--- a/browser/components/downloads/content/allDownloadsView.js
+++ b/browser/components/downloads/content/allDownloadsView.js
@@ -243,17 +243,17 @@ DownloadsPlacesView.prototype = {
       if (!this._richlistbox.firstChild) {
         return;
       }
 
       let rlbRect = this._richlistbox.getBoundingClientRect();
       let winUtils = window.windowUtils;
       let nodes = winUtils.nodesFromRect(rlbRect.left, rlbRect.top,
                                          0, rlbRect.width, rlbRect.height, 0,
-                                         true, false);
+                                         true, false, false);
       // nodesFromRect returns nodes in z-index order, and for the same z-index
       // sorts them in inverted DOM order, thus starting from the one that would
       // be on top.
       let firstVisibleNode, lastVisibleNode;
       for (let node of nodes) {
         if (node.localName === "richlistitem" && node._shell) {
           node._shell.ensureActive();
           // The first visible node is the last match.
--- a/dom/base/DocumentOrShadowRoot.cpp
+++ b/dom/base/DocumentOrShadowRoot.cpp
@@ -357,16 +357,17 @@ Element* DocumentOrShadowRoot::ElementFr
   return elements.SafeElementAt(0);
 }
 
 void DocumentOrShadowRoot::NodesFromRect(float aX, float aY, float aTopSize,
                                          float aRightSize, float aBottomSize,
                                          float aLeftSize,
                                          bool aIgnoreRootScrollFrame,
                                          bool aFlushLayout,
+                                         bool aOnlyVisible,
                                          nsTArray<RefPtr<nsINode>>& aReturn) {
   // Following the same behavior of elementFromPoint,
   // we don't return anything if either coord is negative
   if (!aIgnoreRootScrollFrame && (aX < 0 || aY < 0)) {
     return;
   }
 
   nscoord x = nsPresContext::CSSPixelsToAppUnits(aX - aLeftSize);
@@ -375,16 +376,19 @@ void DocumentOrShadowRoot::NodesFromRect
   nscoord h = nsPresContext::CSSPixelsToAppUnits(aTopSize + aBottomSize) + 1;
 
   nsRect rect(x, y, w, h);
 
   EnumSet<FrameForPointOption> options;
   if (aIgnoreRootScrollFrame) {
     options += FrameForPointOption::IgnoreRootScrollFrame;
   }
+  if (aOnlyVisible) {
+    options += FrameForPointOption::OnlyVisible;
+  }
 
   auto flush = aFlushLayout ? FlushLayout::Yes : FlushLayout::No;
   QueryNodesFromRect(*this, rect, options, flush, Multiple::Yes, aReturn);
 }
 
 Element* DocumentOrShadowRoot::AddIDTargetObserver(nsAtom* aID,
                                                    IDTargetObserver aObserver,
                                                    void* aData,
--- a/dom/base/DocumentOrShadowRoot.h
+++ b/dom/base/DocumentOrShadowRoot.h
@@ -115,17 +115,17 @@ class DocumentOrShadowRoot {
    */
   Element* ElementFromPointHelper(float aX, float aY,
                                   bool aIgnoreRootScrollFrame,
                                   bool aFlushLayout);
 
   void NodesFromRect(float aX, float aY, float aTopSize, float aRightSize,
                      float aBottomSize, float aLeftSize,
                      bool aIgnoreRootScrollFrame, bool aFlushLayout,
-                     nsTArray<RefPtr<nsINode>>&);
+                     bool aOnlyVisible, nsTArray<RefPtr<nsINode>>&);
 
   /**
    * This gets fired when the element that an id refers to changes.
    * This fires at difficult times. It is generally not safe to do anything
    * which could modify the DOM in any way. Use
    * nsContentUtils::AddScriptRunner.
    * @return true to keep the callback in the callback set, false
    * to remove it.
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1150,27 +1150,29 @@ nsDOMWindowUtils::ElementFromPoint(float
   el.forget(aReturn);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::NodesFromRect(float aX, float aY, float aTopSize,
                                 float aRightSize, float aBottomSize,
                                 float aLeftSize, bool aIgnoreRootScrollFrame,
-                                bool aFlushLayout, nsINodeList** aReturn) {
+                                bool aFlushLayout, bool aOnlyVisible,
+                                nsINodeList** aReturn) {
   nsCOMPtr<Document> doc = GetDocument();
   NS_ENSURE_STATE(doc);
 
   nsSimpleContentList* list = new nsSimpleContentList(doc);
   NS_ADDREF(list);
   *aReturn = list;
 
   AutoTArray<RefPtr<nsINode>, 8> nodes;
   doc->NodesFromRect(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
-                     aIgnoreRootScrollFrame, aFlushLayout, nodes);
+                     aIgnoreRootScrollFrame, aFlushLayout, aOnlyVisible,
+                     nodes);
   list->SetCapacity(nodes.Length());
   for (auto& node : nodes) {
     list->AppendElement(node->AsContent());
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -741,25 +741,28 @@ interface nsIDOMWindowUtils : nsISupport
    * @param aTopSize How much to expand up the rectangle
    * @param aRightSize How much to expand right the rectangle
    * @param aBottomSize How much to expand down the rectangle
    * @param aLeftSize How much to expand left the rectangle
    * @param aIgnoreRootScrollFrame whether or not to ignore the root scroll
    *        frame when retrieving the element. If false, this method returns
    *        null for coordinates outside of the viewport.
    * @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
+   * @param aOnlyVisible Set to true if you only want nodes that pass a visibility
+   *        hit test.
    */
   NodeList nodesFromRect(in float aX,
                          in float aY,
                          in float aTopSize,
                          in float aRightSize,
                          in float aBottomSize,
                          in float aLeftSize,
                          in boolean aIgnoreRootScrollFrame,
-                         in boolean aFlushLayout);
+                         in boolean aFlushLayout,
+                         in boolean aOnlyVisible);
 
 
   /**
    * Get a list of nodes that have meaningful textual content to
    * be translated. The implementation of this algorithm is in flux
    * as we experiment and refine which approach works best.
    *
    * This method requires chrome privileges.
--- a/dom/tests/mochitest/chrome/489127.html
+++ b/dom/tests/mochitest/chrome/489127.html
@@ -8,30 +8,18 @@
 
   var SimpleTest = window.opener.SimpleTest;
   function ok() { window.opener.ok.apply(window.opener, arguments); }
   function done() { window.opener.done.apply(window.opener, arguments); }
   let e = {};
 
   let dwu = window.windowUtils;
 
-  /*
-    NodeList nodesFromRect(in float aX,
-                           in float aY,
-                           in float aTopSize, 
-                           in float aRightSize,
-                           in float aBottomSize,
-                           in float aLeftSize,
-                           in boolean aIgnoreRootScrollFrame,
-                           in boolean aFlushLayout);
-
-  */
-
   function check(x, y, top, right, bottom, left, list) {
-    let nodes = dwu.nodesFromRect(x, y, top, right, bottom, left, true, false);
+    let nodes = dwu.nodesFromRect(x, y, top, right, bottom, left, true, false, false);
     
     list.push(e.body);
     list.push(e.html);
 
     if (nodes.length != list.length) {
       ok(false, "Different number of nodes for rect" +
                 "[" + x + "," + y + "], " + 
                 "[" + top + "," + right + "," + bottom + "," + left + "]");
--- a/toolkit/actors/PictureInPictureChild.jsm
+++ b/toolkit/actors/PictureInPictureChild.jsm
@@ -294,17 +294,17 @@ class PictureInPictureToggleChild extend
     let state = this.docState;
     let event = state.lastMouseMoveEvent;
     let { clientX, clientY } = event;
     let winUtils = this.content.windowUtils;
     // We use winUtils.nodesFromRect instead of document.elementsFromPoint,
     // since document.elementsFromPoint always flushes layout. The 1's in that
     // function call are for the size of the rect that we want, which is 1x1.
     let elements = winUtils.nodesFromRect(clientX, clientY, 1, 1, 1, 1, true,
-                                          false);
+                                          false, false);
 
     for (let element of elements) {
       if (state.weakVisibleVideos.has(element) &&
           !element.isCloningElementVisually) {
         this.onMouseOverVideo(element);
         return;
       }
     }