Bug 1092139 - Make the PositionedEventTargeting code respect the flag to ignore root scroll frames. r=roc, a=lsblakk
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 03 Nov 2014 09:43:52 -0500
changeset 225890 026779067a2f91136f4350381680029917c0aa3b
parent 225889 a361f7b596861387402ae3a403115ce23ff53259
child 225891 534a884c70026fef2e029766f2fe15b014de7883
push id7219
push userryanvm@gmail.com
push dateThu, 06 Nov 2014 01:17:09 +0000
treeherdermozilla-aurora@29c0cc65eafc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, lsblakk
bugs1092139
milestone35.0a2
Bug 1092139 - Make the PositionedEventTargeting code respect the flag to ignore root scroll frames. r=roc, a=lsblakk The ignore-root-scroll-frame flag is used on mobile platforms in order to allow hit-testing outside the viewport area. This is needed because the user can zoom out and make visible an area larger than the viewport (i.e. the displayport) but layout generally restricts hit-testing to the viewport. The code to retarget events to nearby clickable elements also needs to respect this flag, otherwise the retargeting fails to work outside the viewport area.
layout/base/PositionedEventTargeting.cpp
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -238,25 +238,32 @@ ClipToFrame(nsIFrame* aRootFrame, nsIFra
   nsRect bound = nsLayoutUtils::TransformFrameRectToAncestor(
     aFrame, nsRect(nsPoint(0, 0), aFrame->GetSize()), aRootFrame);
   nsRect result = bound.Intersect(aRect);
   return result;
 }
 
 static nsRect
 GetTargetRect(nsIFrame* aRootFrame, const nsPoint& aPointRelativeToRootFrame,
-              nsIFrame* aRestrictToDescendants, const EventRadiusPrefs* aPrefs)
+              nsIFrame* aRestrictToDescendants, const EventRadiusPrefs* aPrefs,
+              uint32_t aFlags)
 {
   nsMargin m(AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[0], true),
              AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[1], false),
              AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[2], true),
              AppUnitsFromMM(aRootFrame, aPrefs->mSideRadii[3], false));
   nsRect r(aPointRelativeToRootFrame, nsSize(0,0));
   r.Inflate(m);
-  return ClipToFrame(aRootFrame, aRestrictToDescendants, r);
+  if (!(aFlags & INPUT_IGNORE_ROOT_SCROLL_FRAME)) {
+    // Don't clip this rect to the root scroll frame if the flag to ignore the
+    // root scroll frame is set. Note that the GetClosest code will still enforce
+    // that the target found is a descendant of aRestrictToDescendants.
+    r = ClipToFrame(aRootFrame, aRestrictToDescendants, r);
+  }
+  return r;
 }
 
 static float
 ComputeDistanceFromRect(const nsPoint& aPoint, const nsRect& aRect)
 {
   nscoord dx = std::max(0, std::max(aRect.x - aPoint.x, aPoint.x - aRect.XMost()));
   nscoord dy = std::max(0, std::max(aRect.y - aPoint.y, aPoint.y - aRect.YMost()));
   return float(NS_hypot(dx, dy));
@@ -381,17 +388,17 @@ FindFrameTargetedByInputEvent(const Widg
   // document as the exact target. Otherwise, if an ancestor document has
   // a mouse event handler for example, targets that are !IsElementClickable can
   // never be targeted --- something nsSubDocumentFrame in an ancestor document
   // would be targeted instead.
   nsIFrame* restrictToDescendants = target ?
     target->PresContext()->PresShell()->GetRootFrame() : aRootFrame;
 
   nsRect targetRect = GetTargetRect(aRootFrame, aPointRelativeToRootFrame,
-                                    restrictToDescendants, prefs);
+                                    restrictToDescendants, prefs, aFlags);
   nsAutoTArray<nsIFrame*,8> candidates;
   nsresult rv = nsLayoutUtils::GetFramesForArea(aRootFrame, targetRect, candidates, flags);
   if (NS_FAILED(rv)) {
     return target;
   }
 
   nsIFrame* closestClickable =
     GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs,