Bug 1261671 ContentEventHandler::ConvertToRootRelativeOffset() should resolve CSS transform per same FullZoom level documents WIP draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 09 Apr 2016 13:32:43 +0900
changeset 349126 88fb62b131c87c2eb3b66a4a67e37942d765995c
parent 349125 0743f3c2cc9e073d27622eb0fa47dd19a05cb59f
child 518015 a7cd1265a840fdec0c6f49183c1f7546335e71f0
push id14997
push usermasayuki@d-toybox.com
push dateSat, 09 Apr 2016 04:33:22 +0000
bugs1261671
milestone48.0a1
Bug 1261671 ContentEventHandler::ConvertToRootRelativeOffset() should resolve CSS transform per same FullZoom level documents WIP MozReview-Commit-ID: 6PuVtyJYfWz
dom/events/ContentEventHandler.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -1904,26 +1904,46 @@ ContentEventHandler::GetStartFrameAndOff
 }
 
 nsresult
 ContentEventHandler::ConvertToRootRelativeOffset(nsIFrame* aFrame,
                                                  nsRect& aRect)
 {
   NS_ASSERTION(aFrame, "aFrame must not be null");
 
-  nsPresContext* rootPresContext = aFrame->PresContext()->GetRootPresContext();
-  if (NS_WARN_IF(!rootPresContext)) {
-    return NS_ERROR_FAILURE;
+  nsIFrame* frame = aFrame;
+  for (;;) {
+    nsPresContext* ancestor =
+      frame->PresContext()->GetTopLevelSameAppUnitsPerDevPixelPresContext();
+    nsIFrame* ancestorRootFrame = ancestor->PresShell()->GetRootFrame();
+    if (NS_WARN_IF(!ancestorRootFrame)) {
+      return NS_ERROR_FAILURE;
+    }
+    MOZ_ASSERT(ancestorRootFrame->GetPosition() == nsPoint(0, 0));
+    MOZ_ASSERT(ancestorRootFrame->PresContext() == ancestor);
+    printf("aRect={ x=%d, y=%d, width=%d, height=%d\n", aRect.x, aRect.y, aRect.width, aRect.height);
+    aRect = nsLayoutUtils::TransformFrameRectToAncestor(frame, aRect,
+                                                        ancestorRootFrame);
+    if (ancestor->IsRoot()) {
+      break;
+    }
+    frame = ancestorRootFrame->GetParent();
+    if (frame) {
+      MOZ_ASSERT(ancestorRootFrame->PresContext() != frame->PresContext());
+      MOZ_ASSERT(ancestorRootFrame->GetSize() == frame->GetSize());
+    } else {
+      nsPoint pt;
+      frame = nsLayoutUtils::GetCrossDocParentFrame(ancestorRootFrame, &pt);
+      if (NS_WARN_IF(!frame)) {
+        return NS_ERROR_FAILURE;
+      }
+      aRect.MoveBy(pt);
+    }
   }
-  nsIFrame* rootFrame = rootPresContext->PresShell()->GetRootFrame();
-  if (NS_WARN_IF(!rootFrame)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  aRect = nsLayoutUtils::TransformFrameRectToAncestor(aFrame, aRect, rootFrame);
+  printf("aRect={ x=%d, y=%d, width=%d, height=%d\n\n\n", aRect.x, aRect.y, aRect.width, aRect.height);
   return NS_OK;
 }
 
 static void AdjustRangeForSelection(nsIContent* aRoot,
                                     nsINode** aNode,
                                     int32_t* aNodeOffset)
 {
   nsINode* node = *aNode;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1046,17 +1046,17 @@ nsPresContext::Observe(nsISupports* aSub
     return NS_DispatchToCurrentThread(runnable);
   }
 
   NS_WARNING("unrecognized topic in nsPresContext::Observe");
   return NS_ERROR_FAILURE;
 }
 
 nsPresContext*
-nsPresContext::GetParentPresContext()
+nsPresContext::GetParentPresContext() const
 {
   nsIPresShell* shell = GetPresShell();
   if (shell) {
     nsViewManager* viewManager = shell->GetViewManager();
     if (viewManager) {
       nsView* view = viewManager->GetRootView();
       if (view) {
         view = view->GetParent(); // anonymous inner view
@@ -1084,16 +1084,31 @@ nsPresContext::GetToplevelContentDocumen
   for (;;) {
     nsPresContext* parent = pc->GetParentPresContext();
     if (!parent || parent->IsChrome())
       return pc;
     pc = parent;
   }
 }
 
+nsPresContext*
+nsPresContext::GetTopLevelSameAppUnitsPerDevPixelPresContext() const
+{
+  nsPresContext* pc = const_cast<nsPresContext*>(this);
+  int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel();
+  for (;;) {
+    nsPresContext* parent = pc->GetParentPresContext();
+    if (!parent || parent->AppUnitsPerDevPixel() != appUnitsPerDevPixel) {
+      break;
+    }
+    pc = parent;
+  }
+  return pc;
+}
+
 nsIWidget*
 nsPresContext::GetNearestWidget(nsPoint* aOffset)
 {
   NS_ENSURE_TRUE(mShell, nullptr);
   nsIFrame* frame = mShell->GetRootFrame();
   NS_ENSURE_TRUE(frame, nullptr);
   return frame->GetView()->GetNearestWidget(aOffset);
 }
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -178,25 +178,32 @@ public:
   }
 
   nsIPresShell* GetPresShell() const { return mShell; }
 
   /**
    * Returns the parent prescontext for this one. Returns null if this is a
    * root.
    */
-  nsPresContext* GetParentPresContext();
+  nsPresContext* GetParentPresContext() const;
 
   /**
    * Returns the prescontext of the toplevel content document that contains
    * this presentation, or null if there isn't one.
    */
   nsPresContext* GetToplevelContentDocumentPresContext();
 
   /**
+   * Returns an ancestor presentation context whose app units per device pixel
+   * is same as the instance's.  If the parent presentation context has
+   * different value, this returns itself.
+   */
+  nsPresContext* GetTopLevelSameAppUnitsPerDevPixelPresContext() const;
+
+  /**
    * Returns the nearest widget for the root frame of this.
    *
    * @param aOffset     If non-null the offset from the origin of the root
    *                    frame's view to the widget's origin (usually positive)
    *                    expressed in appunits of this will be returned in
    *                    aOffset.
    */
   nsIWidget* GetNearestWidget(nsPoint* aOffset = nullptr);
@@ -588,17 +595,17 @@ public:
     if (HasCachedStyleData()) {
       // Media queries could have changed, since we changed the meaning
       // of 'em' units in them.
       MediaFeatureValuesChanged(eRestyle_ForceDescendants,
                                 NS_STYLE_HINT_REFLOW);
     }
   }
 
-  float GetFullZoom() { return mFullZoom; }
+  float GetFullZoom() const { return mFullZoom; }
   void SetFullZoom(float aZoom);
 
   nscoord GetAutoQualityMinFontSize() {
     return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
   }
 
   /**
    * Return the device's screen size in inches, for font size