Title: [95478] trunk
Revision
95478
Author
rn...@webkit.org
Date
2011-09-19 14:51:44 -0700 (Mon, 19 Sep 2011)

Log Message

Incorrect selection with absolutely positioned div
https://bugs.webkit.org/show_bug.cgi?id=39503

Reviewed by Kenneth Rohde Christiansen.

Source/WebCore: 

The bug was caused by a false assumption in RenderBlock::positionForPoint. Because the last child box
can be positioned, floated, invisible, etc..., we can't always trust last child's logicalTop to tell us
whether a given point is inside or below the last child box.

Fixed the bug by using the last hit-test candidate instead.

Test: editing/selection/block-with-positioned-lastchild.html

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::positionForPoint):

LayoutTests: 

Added a regression test for placing the caret inside a block with multiple logical lines
with an absolutely positioned last child. WebKit should place the caret on the left of the first line
(instead of after the last line) when the user clicks on the left of the first line.

* editing/selection/block-with-positioned-lastchild-expected.txt: Added.
* editing/selection/block-with-positioned-lastchild.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (95477 => 95478)


--- trunk/LayoutTests/ChangeLog	2011-09-19 21:48:27 UTC (rev 95477)
+++ trunk/LayoutTests/ChangeLog	2011-09-19 21:51:44 UTC (rev 95478)
@@ -1,3 +1,17 @@
+2011-09-19  Ryosuke Niwa  <rn...@webkit.org>
+
+        Incorrect selection with absolutely positioned div
+        https://bugs.webkit.org/show_bug.cgi?id=39503
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Added a regression test for placing the caret inside a block with multiple logical lines
+        with an absolutely positioned last child. WebKit should place the caret on the left of the first line
+        (instead of after the last line) when the user clicks on the left of the first line.
+
+        * editing/selection/block-with-positioned-lastchild-expected.txt: Added.
+        * editing/selection/block-with-positioned-lastchild.html: Added.
+
 2011-09-19  Abhishek Arya  <infe...@chromium.org>
 
         Unreviewed. Chromium Rebaselines for r95461.

Added: trunk/LayoutTests/editing/selection/block-with-positioned-lastchild-expected.txt (0 => 95478)


--- trunk/LayoutTests/editing/selection/block-with-positioned-lastchild-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/block-with-positioned-lastchild-expected.txt	2011-09-19 21:51:44 UTC (rev 95478)
@@ -0,0 +1,4 @@
+Click on the left of this line.
+Caret should NOT be placed in this line,
+PASS
+

Added: trunk/LayoutTests/editing/selection/block-with-positioned-lastchild.html (0 => 95478)


--- trunk/LayoutTests/editing/selection/block-with-positioned-lastchild.html	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/block-with-positioned-lastchild.html	2011-09-19 21:51:44 UTC (rev 95478)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div style="padding: 20px;" contenteditable>Click on the left of this line.
+<div>Caret should NOT be placed in this line,</div>
+<div style="position:absolute; top:0px; right:0px;"></div>
+</div>
+<pre><script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+
+    var container = document.body.children[0];
+    eventSender.mouseMoveTo(container.offsetLeft + 5, container.offsetTop + 5);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+
+    if (!getSelection().isCollapsed)
+        document.writeln('FAIL - selection was not collapsed');
+    else if (getSelection().baseNode != container.firstChild)
+        document.writeln('FAIL - caret was not in the first line');
+    else if (getSelection().baseOffset)
+        document.writeln('FAIL - caret was not on the left edge');
+    else
+        document.writeln('PASS');
+}
+
+</script></pre>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (95477 => 95478)


--- trunk/Source/WebCore/ChangeLog	2011-09-19 21:48:27 UTC (rev 95477)
+++ trunk/Source/WebCore/ChangeLog	2011-09-19 21:51:44 UTC (rev 95478)
@@ -1,3 +1,21 @@
+2011-09-19  Ryosuke Niwa  <rn...@webkit.org>
+
+        Incorrect selection with absolutely positioned div
+        https://bugs.webkit.org/show_bug.cgi?id=39503
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        The bug was caused by a false assumption in RenderBlock::positionForPoint. Because the last child box
+        can be positioned, floated, invisible, etc..., we can't always trust last child's logicalTop to tell us
+        whether a given point is inside or below the last child box.
+
+        Fixed the bug by using the last hit-test candidate instead.
+
+        Test: editing/selection/block-with-positioned-lastchild.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::positionForPoint):
+
 2011-09-19  Dmitry Titov  <dim...@chromium.org>
 
         [Chromium] Crash after magic iframe transfer for Pepper/NaCl plugins.

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (95477 => 95478)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-09-19 21:48:27 UTC (rev 95477)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-09-19 21:51:44 UTC (rev 95478)
@@ -4336,12 +4336,14 @@
     if (childrenInline())
         return positionForPointWithInlineChildren(pointInLogicalContents);
 
-    if (lastChildBox() && pointInContents.y() > lastChildBox()->logicalTop()) {
-        for (RenderBox* childBox = lastChildBox(); childBox; childBox = childBox->previousSiblingBox()) {
-            if (isChildHitTestCandidate(childBox))
-                return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
-        }
-    } else {
+    RenderBox* lastCandidateBox = lastChildBox();
+    while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
+        lastCandidateBox = lastCandidateBox->previousSiblingBox();
+
+    if (lastCandidateBox) {
+        if (pointInContents.y() > lastCandidateBox->logicalTop())
+            return positionForPointRespectingEditingBoundaries(this, lastCandidateBox, pointInContents);
+
         for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
             // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
             if (isChildHitTestCandidate(childBox) && pointInContents.y() < childBox->logicalBottom())
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to