Bug 1387059 - When checking if nsDisplayPerspective participates in preserve-3d, check the underlying transformed frame. r=mstange, a=gchang
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 25 Aug 2017 11:51:37 +0200
changeset 423935 c141e8fe733b1841f9fb1233eda37e01d9e88cb7
parent 423934 83a250a0a345c83cac9a46c27f7a8c9dd77e264a
child 423936 f2654ea508ece686ba9503438d8729cadc0ec45b
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, gchang
bugs1387059
milestone56.0
Bug 1387059 - When checking if nsDisplayPerspective participates in preserve-3d, check the underlying transformed frame. r=mstange, a=gchang
dom/tests/mochitest/general/mochitest.ini
dom/tests/mochitest/general/test_pointerPreserves3DPerspective.html
layout/generic/nsIFrame.h
layout/painting/nsDisplayList.cpp
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -112,16 +112,17 @@ support-files = test_offsets.js
 [test_outerHTML.xhtml]
 [test_paste_selection.html]
 [test_performance_now.html]
 [test_performance_timeline.html]
 [test_picture_apng.html]
 [test_picture_mutations.html]
 [test_pointerPreserves3D.html]
 [test_pointerPreserves3DClip.html]
+[test_pointerPreserves3DPerspective.html]
 [test_resource_timing.html]
 [test_resource_timing_cross_origin.html]
 [test_resource_timing_frameset.html]
 [test_selectevents.html]
 skip-if = toolkit == 'android' # bug 1230232 - Mouse doesn't select in the same way
 [test_showModalDialog.html]
 skip-if = e10s || toolkit == 'android' #Don't run modal tests on Android
 [test_showModalDialog_removed.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/general/test_pointerPreserves3DPerspective.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for pointer events with preserve-3d</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div>
+  <div>
+    <div style="perspective: 100px; transform-style:preserve-3d; transform: translateX(100px)">
+      <div style="display:inline">
+        <div id="color" style="transform-style:flat; transform: translateX(-100px); display: block; background-color: blue; width: 200px; height: 200px;"></div>
+      </div>
+    </div>
+  </div>
+</div>
+<script class="testbody" type="text/javascript">
+function runTest() {
+    var target = document.elementFromPoint(200, 200);
+    ok(target == document.getElementById("color"), "Find the right target.");
+    var target = document.elementFromPoint(16, 16);
+    ok(target == document.getElementById("color"), "Find the right target.");
+}
+
+runTest();
+</script>
+</body>
+</html>
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -856,17 +856,17 @@ public:
    * out-of-flow frames.
    */
   inline nsContainerFrame* GetInFlowParent();
 
   /**
    * Gets the primary frame of the Content's flattened tree
    * parent, if one exists.
    */
-  inline nsIFrame* GetFlattenedTreeParentPrimaryFrame() const;
+  nsIFrame* GetFlattenedTreeParentPrimaryFrame() const;
 
   /**
    * Return the placeholder for this frame (which must be out-of-flow).
    * @note this will only return non-null if |this| is the first-in-flow
    * although we don't assert that here for legacy reasons.
    */
   inline nsPlaceholderFrame* GetPlaceholderFrame() const {
     MOZ_ASSERT(HasAnyStateBits(NS_FRAME_OUT_OF_FLOW));
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2482,17 +2482,17 @@ void nsDisplayList::HitTest(nsDisplayLis
 
     bool snap;
     nsRect r = item->GetBounds(aBuilder, &snap).Intersect(aRect);
     auto itemType = item->GetType();
     bool same3DContext =
       (itemType == nsDisplayItem::TYPE_TRANSFORM &&
        static_cast<nsDisplayTransform*>(item)->IsParticipating3DContext()) ||
       (itemType == nsDisplayItem::TYPE_PERSPECTIVE &&
-       item->Frame()->Extend3DContext());
+       static_cast<nsDisplayPerspective*>(item)->TransformFrame()->Extend3DContext());
     if (same3DContext &&
         (itemType != nsDisplayItem::TYPE_TRANSFORM ||
          !static_cast<nsDisplayTransform*>(item)->IsLeafOf3DContext())) {
       if (!item->GetClip().MayIntersect(aRect)) {
         continue;
       }
       AutoTArray<nsIFrame*, 1> neverUsed;
       // Start gethering leaves of the 3D rendering context, and
@@ -7450,21 +7450,21 @@ nsDisplayTransform::GetResultingTransfor
     if (ComputePerspectiveMatrix(frame, aAppUnitsPerPixel, perspectiveMatrix)) {
       result *= perspectiveMatrix;
     }
   }
 
   if ((aFlags & INCLUDE_PRESERVE3D_ANCESTORS) &&
       frame && frame->Combines3DTransformWithAncestors()) {
     // Include the transform set on our parent
-    NS_ASSERTION(frame->GetParent() &&
-                 frame->GetParent()->IsTransformed() &&
-                 frame->GetParent()->Extend3DContext(),
+    nsIFrame* parentFrame = frame->GetFlattenedTreeParentPrimaryFrame();
+    NS_ASSERTION(parentFrame && parentFrame->IsTransformed() &&
+                 parentFrame->Extend3DContext(),
                  "Preserve3D mismatch!");
-    FrameTransformProperties props(frame->GetParent(),
+    FrameTransformProperties props(parentFrame,
                                    aAppUnitsPerPixel,
                                    nullptr);
 
     uint32_t flags = aFlags & (INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE);
 
     // If this frame isn't transformed (but we exist for backface-visibility),
     // then we're not a reference frame so no offset to origin will be added.
     // Otherwise we need to manually translate into our parent's coordinate
@@ -7699,17 +7699,17 @@ nsDisplayTransform::GetAccumulatedPreser
     if (!IsLeafOf3DContext()) {
       mTransformPreserves3D = GetTransform();
       return mTransformPreserves3D;
     }
 
     const nsIFrame* establisher; // Establisher of the 3D rendering context.
     for (establisher = mFrame;
          establisher && establisher->Combines3DTransformWithAncestors();
-         establisher = nsLayoutUtils::GetCrossDocParentFrame(establisher)) {
+         establisher = establisher->GetFlattenedTreeParentPrimaryFrame()) {
     }
     const nsIFrame* establisherReference =
       aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetCrossDocParentFrame(establisher));
 
     nsPoint offset = establisher->GetOffsetToCrossDoc(establisherReference);
     float scale = mFrame->PresContext()->AppUnitsPerDevPixel();
     uint32_t flags = INCLUDE_PRESERVE3D_ANCESTORS|INCLUDE_PERSPECTIVE|OFFSET_BY_ORIGIN;
     mTransformPreserves3D =