Bug 1093686 - Add some debug logging code for PositionedEventTargeting.cpp. r=roc
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 06 Nov 2014 08:05:51 -0500
changeset 214391 0c95949fef141b5745d06eef4a377e0b774a94ca
parent 214390 b1e482f69d96d2ca59e627eeb101d2f284efecb2
child 214392 f1989cb41965b06f4d3db89764c3606ee136814a
push id27780
push userkwierso@gmail.com
push dateFri, 07 Nov 2014 02:25:05 +0000
treeherdermozilla-central@e6d47abb6a7b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1093686
milestone36.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 1093686 - Add some debug logging code for PositionedEventTargeting.cpp. r=roc
gfx/layers/LayersLogging.cpp
gfx/layers/LayersLogging.h
layout/base/PositionedEventTargeting.cpp
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -63,16 +63,36 @@ AppendToString(std::stringstream& aStrea
   aStream << pfx;
   aStream << nsPrintfCString(
     "rgba(%d, %d, %d, %g)",
     uint8_t(c.r*255.0), uint8_t(c.g*255.0), uint8_t(c.b*255.0), c.a).get();
   aStream << sfx;
 }
 
 void
+AppendToString(std::stringstream& aStream, const nsPoint& p,
+               const char* pfx, const char* sfx)
+{
+  aStream << pfx;
+  aStream << nsPrintfCString("(x=%d, y=%d)", p.x, p.y).get();
+  aStream << sfx;
+}
+
+void
+AppendToString(std::stringstream& aStream, const nsRect& r,
+               const char* pfx, const char* sfx)
+{
+  aStream << pfx;
+  aStream << nsPrintfCString(
+    "(x=%d, y=%d, w=%d, h=%d)",
+    r.x, r.y, r.width, r.height).get();
+  aStream << sfx;
+}
+
+void
 AppendToString(std::stringstream& aStream, const nsIntPoint& p,
                const char* pfx, const char* sfx)
 {
   aStream << pfx;
   aStream << nsPrintfCString("(x=%d, y=%d)", p.x, p.y).get();
   aStream << sfx;
 }
 
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -41,16 +41,24 @@ void
 AppendToString(std::stringstream& aStream, FrameMetrics::ViewID n,
                const char* pfx="", const char* sfx="");
 
 void
 AppendToString(std::stringstream& aStream, const gfxRGBA& c,
                const char* pfx="", const char* sfx="");
 
 void
+AppendToString(std::stringstream& aStream, const nsPoint& p,
+               const char* pfx="", const char* sfx="");
+
+void
+AppendToString(std::stringstream& aStream, const nsRect& r,
+               const char* pfx="", const char* sfx="");
+
+void
 AppendToString(std::stringstream& aStream, const nsIntPoint& p,
                const char* pfx="", const char* sfx="");
 
 template<class T>
 void
 AppendToString(std::stringstream& aStream, const mozilla::gfx::PointTyped<T>& p,
                const char* pfx="", const char* sfx="")
 {
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -11,16 +11,22 @@
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "nsPrintfCString.h"
 #include "mozilla/dom/Element.h"
 #include "nsRegion.h"
 #include "nsDeviceContext.h"
 #include "nsIFrame.h"
 #include <algorithm>
+#include "LayersLogging.h"
+
+// If debugging this code you may wish to enable this logging, and also
+// uncomment the DumpFrameTree call near the bottom of the file.
+#define PET_LOG(...)
+// #define PET_LOG(...) printf_stderr("PET: " __VA_ARGS__);
 
 namespace mozilla {
 
 /*
  * The basic goal of FindFrameTargetedByInputEvent() is to find a good
  * target element that can respond to mouse events. Both mouse events and touch
  * events are targeted at this element. Note that even for touch events, we
  * check responsiveness to mouse events. We assume Web authors
@@ -313,54 +319,60 @@ GetClosest(nsIFrame* aRoot, const nsPoin
            nsIFrame* aRestrictToDescendants, nsTArray<nsIFrame*>& aCandidates)
 {
   nsIFrame* bestTarget = nullptr;
   // Lower is better; distance is in appunits
   float bestDistance = 1e6f;
   nsRegion exposedRegion(aTargetRect);
   for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
     nsIFrame* f = aCandidates[i];
+    PET_LOG("Checking candidate %p\n", f);
 
     bool preservesAxisAlignedRectangles = false;
     nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
         nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
     nsRegion region;
     region.And(exposedRegion, borderBox);
 
     if (region.IsEmpty()) {
+      PET_LOG("  candidate %p had empty hit region\n", f);
       continue;
     }
 
     if (preservesAxisAlignedRectangles) {
       // Subtract from the exposed region if we have a transform that won't make
       // the bounds include a bunch of area that we don't actually cover.
       SubtractFromExposedRegion(&exposedRegion, region);
     }
 
     if (!IsElementClickable(f, nsGkAtoms::body)) {
+      PET_LOG("  candidate %p was not clickable\n", f);
       continue;
     }
     // If our current closest frame is a descendant of 'f', skip 'f' (prefer
     // the nested frame).
     if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
+      PET_LOG("  candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
       continue;
     }
     if (!nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
+      PET_LOG("  candidate %p was not descendant of restrictroot %p\n", f, aRestrictToDescendants);
       continue;
     }
 
     // distance is in appunits
     float distance = ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
     nsIContent* content = f->GetContent();
     if (content && content->IsElement() &&
         content->AsElement()->State().HasState(
                                         EventStates(NS_EVENT_STATE_VISITED))) {
       distance *= aPrefs->mVisitedWeight / 100.0f;
     }
     if (distance < bestDistance) {
+      PET_LOG("  candidate %p is the new best\n", f);
       bestDistance = distance;
       bestTarget = f;
     }
   }
   return bestTarget;
 }
 
 nsIFrame*
@@ -368,53 +380,67 @@ FindFrameTargetedByInputEvent(WidgetGUIE
                               nsIFrame* aRootFrame,
                               const nsPoint& aPointRelativeToRootFrame,
                               uint32_t aFlags)
 {
   uint32_t flags = (aFlags & INPUT_IGNORE_ROOT_SCROLL_FRAME) ?
      nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME : 0;
   nsIFrame* target =
     nsLayoutUtils::GetFrameForPoint(aRootFrame, aPointRelativeToRootFrame, flags);
+  PET_LOG("Found initial target %p for event class %s point %s relative to root frame %p\n",
+    target, (aEvent->mClass == eMouseEventClass ? "mouse" :
+             (aEvent->mClass == eTouchEventClass ? "touch" : "other")),
+    mozilla::layers::Stringify(aPointRelativeToRootFrame).c_str(), aRootFrame);
 
   const EventRadiusPrefs* prefs = GetPrefsFor(aEvent->mClass);
   if (!prefs || !prefs->mEnabled || (target && IsElementClickable(target, nsGkAtoms::body))) {
+    PET_LOG("Retargeting disabled or target %p is clickable\n", target);
     return target;
   }
 
   // Do not modify targeting for actual mouse hardware; only for mouse
   // events generated by touch-screen hardware.
   if (aEvent->mClass == eMouseEventClass &&
       prefs->mTouchOnly &&
       aEvent->AsMouseEvent()->inputSource !=
         nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
+    PET_LOG("Mouse input event is not from a touch source\n");
     return target;
   }
 
   // If the exact target is non-null, only consider candidate targets in the same
   // 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, aFlags);
+  PET_LOG("Expanded point to target rect %s\n",
+    mozilla::layers::Stringify(targetRect).c_str());
   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,
                restrictToDescendants, candidates);
   if (closestClickable) {
     target = closestClickable;
   }
+  PET_LOG("Final target is %p\n", target);
+
+  // Uncomment this to dump the frame tree to help with debugging.
+  // Note that dumping the frame tree at the top of the function may flood
+  // logcat on Android devices and cause the PET_LOGs to get dropped.
+  // aRootFrame->DumpFrameTree();
 
   if (!target || !prefs->mRepositionEventCoords) {
     // No repositioning required for this event
     return target;
   }
 
   // Take the point relative to the root frame, make it relative to the target,
   // clamp it to the bounds, and then make it relative to the root frame again.