2009-03-24 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Mar 2009 21:07:48 +0000 (21:07 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Mar 2009 21:07:48 +0000 (21:07 +0000)
        Reviewed by Dave Hyatt

        https://bugs.webkit.org/show_bug.cgi?id=24659

        When hit-testing 3d-transformed layers, it doesn't make sense to project the hitTestRect
        into the coordinate space of the layer, and doing so can result in pathalogical quads
        that break hit testing. In that case, simply use the same bounds as used for painting,
        which are the composited bounds for this layer.

        Test: transforms/3d/hit-testing/rotated-hit-test.html

        * rendering/RenderLayer.cpp:
        (WebCore::RenderLayer::hitTestLayer):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@41952 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.txt [new file with mode: 0644]
LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/RenderLayer.cpp

index aab1a2e..4fc4ee1 100644 (file)
@@ -1,3 +1,15 @@
+2009-03-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+        
+        https://bugs.webkit.org/show_bug.cgi?id=24659
+        
+        Testcase for hit testing on element that has been rotated to be almost
+        edge-on.
+
+        * platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.txt: Added.
+        * transforms/3d/hit-testing/rotated-hit-test.html: Added.
+
 2009-03-24  David Hyatt  <hyatt@apple.com>
 
         Reviewed by Simon Fraser
diff --git a/LayoutTests/platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.txt b/LayoutTests/platform/mac/transforms/3d/hit-testing/rotated-hit-test-expected.txt
new file mode 100644 (file)
index 0000000..9b70f08
--- /dev/null
@@ -0,0 +1,14 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,202) size 784x18
+        RenderText {#text} at (0,0) size 124x18
+          text run at (0,0) width 124: "Found box1: PASS"
+        RenderBR {BR} at (124,14) size 0x0
+layer at (8,8) size 202x202
+  RenderBlock {DIV} at (0,0) size 202x202 [border: (1px solid #000000)]
+    RenderText {#text} at (0,0) size 0x0
+layer at (9,9) size 200x200
+  RenderBlock {DIV} at (1,1) size 200x200 [bgcolor=#808080]
diff --git a/LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html b/LayoutTests/transforms/3d/hit-testing/rotated-hit-test.html
new file mode 100644 (file)
index 0000000..2ca836a
--- /dev/null
@@ -0,0 +1,60 @@
+<html>
+<head>
+  <title>Hit testing of almost edge-on elements</title>
+  <style type="text/css" media="screen">
+  
+  div:hover {
+    outline: 2px solid orange;
+  }
+    #container {
+      width: 200px;
+      height: 200px;
+      border: 1px solid black;
+      -webkit-perspective: 500;
+    }
+    
+    .box {
+      display: inline-block;
+      width: 200px;
+      height: 200px;
+      background-color: gray;
+      -webkit-transform-origin: 10% 50%;
+      -webkit-transform: rotateY(90deg);
+    }
+    .box:hover {
+      background-color: orange;
+    }
+  </style>
+  <script type="text/javascript" charset="utf-8">
+    function log(s)
+    {
+      var results = document.getElementById('results');
+      results.innerHTML += s + '<br>';
+    }
+
+    function runTest()
+    {
+      var firstHit = document.elementFromPoint(40, 150);
+      
+      var box1 = document.getElementById('box1');
+      var container = document.getElementById('container');
+
+      if (firstHit == box1)
+        log('Found box1: PASS');
+      else
+        log('Found ' + firstHit.id + ' : FAIL');
+    }
+    
+  </script>
+</head>
+<body onload="runTest()">
+
+<div id="container">
+  <div class="box" id="box1"></div>
+</div>
+
+<div id="results">
+</div>
+
+</body>
+</html>
index c52326b..d8ca20e 100644 (file)
@@ -1,6 +1,22 @@
 2009-03-24  Simon Fraser  <simon.fraser@apple.com>
 
         Reviewed by Dave Hyatt
+        
+        https://bugs.webkit.org/show_bug.cgi?id=24659
+        
+        When hit-testing 3d-transformed layers, it doesn't make sense to project the hitTestRect
+        into the coordinate space of the layer, and doing so can result in pathalogical quads
+        that break hit testing. In that case, simply use the same bounds as used for painting,
+        which are the composited bounds for this layer.
+
+        Test: transforms/3d/hit-testing/rotated-hit-test.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::hitTestLayer):
+
+2009-03-24  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
 
         https://bugs.webkit.org/show_bug.cgi?id=24436
         
index 0c47e02..2382921 100644 (file)
@@ -2253,7 +2253,14 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
         // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
         // by our container.
         IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
-        IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
+        IntRect localHitTestRect;
+#if USE(ACCELERATED_COMPOSITING)
+        if (isComposited()) {
+            // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
+            localHitTestRect = compositor()->calculateCompositedBounds(this, this);
+        } else
+#endif
+            localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
 
         // Now do a hit test with the root layer shifted to be us.
         return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset);