Bug 1302470 Part 4: Augment the IsRangeVisible function to test for opaque overdraw. r?mstange draft
authorBrad Werth <bwerth@mozilla.com>
Wed, 30 Nov 2016 17:03:27 -0800
changeset 446636 5441d62c0960cb1746d7c93935708876def0185f
parent 446635 b5d179ea95f3c266862eb0d238b5ee8de25edd59
child 446637 78fbc4487a0d53812f474bc780e15d04b098d42f
push id37835
push userbwerth@mozilla.com
push dateThu, 01 Dec 2016 17:09:39 +0000
reviewersmstange
bugs1302470
milestone53.0a1
Bug 1302470 Part 4: Augment the IsRangeVisible function to test for opaque overdraw. r?mstange MozReview-Commit-ID: F2qbu0WLl9O
toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
--- a/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
+++ b/toolkit/components/typeaheadfind/nsTypeAheadFind.cpp
@@ -1187,53 +1187,79 @@ nsTypeAheadFind::IsRangeVisible(nsIPresS
                                 nsIDOMRange *aRange,
                                 bool aFlushLayout,
                                 nsIDOMRange **aFirstVisibleRange,
                                 bool *aUsesIndependentSelection)
 {
   NS_ASSERTION(aPresShell && aPresContext && aRange && aFirstVisibleRange, 
                "params are invalid");
 
-  // We need to know if the range start is visible.
-  // Otherwise, return the first visible range start 
-  // in aFirstVisibleRange
+  // We need to know if the range start and end are both visible.
+  // In all cases, return the first visible range in aFirstVisibleRange.
   aRange->CloneRange(aFirstVisibleRange);
 
   if (aFlushLayout) {
     aPresShell->FlushPendingNotifications(Flush_Layout);
   }
 
   nsCOMPtr<nsIDOMNode> node;
-  aRange->GetStartContainer(getter_AddRefs(node));
+  aRange->GetCommonAncestorContainer(getter_AddRefs(node));
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(node));
-  if (!content)
+  if (!content) {
     return false;
+  }
 
   nsIFrame *frame = content->GetPrimaryFrame();
-  if (!frame)
+  if (!frame) {
     return false;  // No frame! Not visible then.
+  }
 
   // Having a primary frame doesn't mean that the range is visible inside the
   // viewport. Do a hit-test to determine that quickly and properly.
+  bool foundContent = false;
   AutoTArray<nsIFrame*,8> frames;
   nsIFrame *rootFrame = aPresShell->GetRootFrame();
   RefPtr<nsRange> range = static_cast<nsRange*>(aRange);
   RefPtr<mozilla::dom::DOMRectList> rects = range->GetClientRects(true, false);
   for (uint32_t i = 0; i < rects->Length(); ++i) {
     RefPtr<mozilla::dom::DOMRect> rect = rects->Item(i);
     nsRect r(nsPresContext::CSSPixelsToAppUnits((float)rect->X()),
              nsPresContext::CSSPixelsToAppUnits((float)rect->Y()),
              nsPresContext::CSSPixelsToAppUnits((float)rect->Width()),
              nsPresContext::CSSPixelsToAppUnits((float)rect->Height()));
+    // Append visible frames to frames array.
     nsLayoutUtils::GetFramesForArea(rootFrame, r, frames,
-      nsLayoutUtils::IGNORE_PAINT_SUPPRESSION | nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
+      nsLayoutUtils::IGNORE_PAINT_SUPPRESSION |
+      nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME |
+      nsLayoutUtils::ONLY_VISIBLE);
+
+    // See if any of the frames contain the content. If they do, then the range
+    // is visible. We search for the content rather than the original frame,
+    // because nsTextContinuation frames might be returned instead of the
+    // original frame.
+    for (const auto &f: frames) {
+      if (f->GetContent() == content) {
+        foundContent = true;
+        break;
+      }
+    }
+
+    if (foundContent) {
+      break;
+    }
+
+    frames.ClearAndRetainStorage();
   }
-  if (!frames.Length())
+
+  // Test that content appears in the list of framesForArea. If it does, then
+  // that means that content is at least partly visible.
+  if (!foundContent) {
     return false;
+  }
 
   // Detect if we are _inside_ a text control, or something else with its own
   // selection controller.
   if (aUsesIndependentSelection) {
     *aUsesIndependentSelection = 
       (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
   }