- Revision
- 123980
- Author
- [email protected]
- Date
- 2012-07-29 10:27:35 -0700 (Sun, 29 Jul 2012)
Log Message
In flipped blocks, a point on the top edge of a box is considered outside the box (and vice versa)
https://bugs.webkit.org/show_bug.cgi?id=92593
Reviewed by Simon Fraser.
Source/WebCore:
With respect to hit testing, boxes should always behave as half-open intervals which include
the physical top and left edges and not the bottom and right edges.
RenderBlock::positionForPoint was not adhering to this, since it was comparing flipped
coordinates.
Tests: fast/writing-mode/flipped-blocks-hit-test-box-edges.html
fast/writing-mode/flipped-blocks-hit-test-line-edges.html
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::positionForPointWithInlineChildren): When blocks are flipped, changed
strict inequalities of y coordinates into non-strict ones and non-strict inequalities into
strict ones.
(WebCore::RenderBlock::positionForPoint): Ditto, except for the test for being under the top
of the last candidate box, which was made non-strict in the unflipped case and remained
strict.
LayoutTests:
* fast/writing-mode/flipped-blocks-hit-test-box-edges-expected.txt: Added.
* fast/writing-mode/flipped-blocks-hit-test-box-edges.html: Added.
* fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt: Added.
* fast/writing-mode/flipped-blocks-hit-test-line-edges.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (123979 => 123980)
--- trunk/LayoutTests/ChangeLog 2012-07-29 14:49:07 UTC (rev 123979)
+++ trunk/LayoutTests/ChangeLog 2012-07-29 17:27:35 UTC (rev 123980)
@@ -1,3 +1,15 @@
+2012-07-29 Dan Bernstein <[email protected]>
+
+ In flipped blocks, a point on the top edge of a box is considered outside the box (and vice versa)
+ https://bugs.webkit.org/show_bug.cgi?id=92593
+
+ Reviewed by Simon Fraser.
+
+ * fast/writing-mode/flipped-blocks-hit-test-box-edges-expected.txt: Added.
+ * fast/writing-mode/flipped-blocks-hit-test-box-edges.html: Added.
+ * fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt: Added.
+ * fast/writing-mode/flipped-blocks-hit-test-line-edges.html: Added.
+
2012-07-29 Mike West <[email protected]>
Extend `application/x-webkit-test-netscape` plugins to better support multiple frames.
Added: trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges-expected.txt (0 => 123980)
--- trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges-expected.txt 2012-07-29 17:27:35 UTC (rev 123980)
@@ -0,0 +1,13 @@
+y x element range start container
+25 25 outer after-after
+25 100 after-after after-after
+49 25 outer after
+49 100 after after
+50 25 outer middle
+50 100 middle middle
+149 25 outer middle
+149 100 middle middle
+150 25 outer before
+150 100 before before
+165 25 outer before-before
+165 100 before-before before-before
Added: trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges.html (0 => 123980)
--- trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges.html (rev 0)
+++ trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-box-edges.html 2012-07-29 17:27:35 UTC (rev 123980)
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<style>
+ #outer > div { margin: 0 25px; }
+</style>
+<div id="outer" style="
+ outline: dashed lightblue;
+ width: 150px;
+ padding: 25px;
+ -webkit-writing-mode: horizontal-bt;
+">
+ <div id="before-before" style="
+ background-color: purple;
+ height: 10px;
+ "></div>
+ <div id="before" style="
+ background-color: silver;
+ height: 15px;
+ "></div>
+ <div id="middle" style="
+ background-color: blue;
+ height: 100px;
+ "></div>
+ <div id="after" style="
+ background-color: silver;
+ height: 15px;
+ "></div>
+ <div id="after-after" style="
+ background-color: purple;
+ height: 10px;
+ "></div>
+</div>
+<table id="results">
+ <thead>
+ <tr>
+ <th>y</th>
+ <th>x</th>
+ <th>element</th>
+ <th>range start container</th>
+ </tr>
+ </thead>
+ <tbody id="table-body">
+ </tbody>
+</table>
+<script>
+ if (window.testRunner)
+ testRunner.dumpAsText();
+
+ function addCell(row, text)
+ {
+ row.appendChild(document.createElement("td")).appendChild(document.createTextNode(text));
+ }
+
+ function test(x, y)
+ {
+ var row = document.getElementById("table-body").appendChild(document.createElement("tr"));
+ addCell(row, y);
+ addCell(row, x);
+ addCell(row, document.elementFromPoint(8 + x, 8 + y).id);
+ addCell(row, document.caretRangeFromPoint(8 + x, 8 + y).startContainer.id);
+ }
+
+ test(25, 25);
+ test(100, 25);
+ test(25, 49);
+ test(100, 49);
+ test(25, 50);
+ test(100, 50);
+ test(25, 149);
+ test(100, 149);
+ test(25, 150);
+ test(100, 150);
+ test(25, 165);
+ test(100, 165);
+</script>
Added: trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt (0 => 123980)
--- trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt 2012-07-29 17:27:35 UTC (rev 123980)
@@ -0,0 +1,7 @@
+Lorem ipsum dolor sit amet
+PASS: offset at (160,105) was 5.
+PASS: offset at (160,104) was 11.
+PASS: offset at (160,26) was 26.
+PASS: offset at (160,25) was 26.
+PASS: offset at (160,24) was 26.
+
Added: trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html (0 => 123980)
--- trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html (rev 0)
+++ trunk/LayoutTests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html 2012-07-29 17:27:35 UTC (rev 123980)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<div id="target" style="
+ outline: dashed lightblue;
+ width: 150px;
+ padding: 25px;
+ font: 20px ahem;
+ -webkit-writing-mode: horizontal-bt;
+">Lorem ipsum dolor sit amet</div>
+<pre id="log"></pre>
+<script>
+ if (window.testRunner)
+ testRunner.dumpAsText();
+
+ function log(message)
+ {
+ document.getElementById("log").appendChild(document.createTextNode(message + "\n"));
+ }
+
+ function test(x, y, expectedOffset)
+ {
+ var actualOffset = document.caretRangeFromPoint(8 + x, 8 + y).startOffset;
+ if (actualOffset === expectedOffset)
+ log("PASS: offset at (" + x + "," + y + ") was " + actualOffset + ".");
+ else
+ log("FAIL: offset at (" + x + "," + y + ") was " + actualOffset + ". Expected " + expectedOffset + ".");
+ }
+
+ test(160, 105, 5);
+ test(160, 104, 11);
+ test(160, 26, 26);
+ test(160, 25, 26);
+ test(160, 24, 26);
+</script>
Modified: trunk/Source/WebCore/ChangeLog (123979 => 123980)
--- trunk/Source/WebCore/ChangeLog 2012-07-29 14:49:07 UTC (rev 123979)
+++ trunk/Source/WebCore/ChangeLog 2012-07-29 17:27:35 UTC (rev 123980)
@@ -1,3 +1,26 @@
+2012-07-29 Dan Bernstein <[email protected]>
+
+ In flipped blocks, a point on the top edge of a box is considered outside the box (and vice versa)
+ https://bugs.webkit.org/show_bug.cgi?id=92593
+
+ Reviewed by Simon Fraser.
+
+ With respect to hit testing, boxes should always behave as half-open intervals which include
+ the physical top and left edges and not the bottom and right edges.
+ RenderBlock::positionForPoint was not adhering to this, since it was comparing flipped
+ coordinates.
+
+ Tests: fast/writing-mode/flipped-blocks-hit-test-box-edges.html
+ fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::positionForPointWithInlineChildren): When blocks are flipped, changed
+ strict inequalities of y coordinates into non-strict ones and non-strict inequalities into
+ strict ones.
+ (WebCore::RenderBlock::positionForPoint): Ditto, except for the test for being under the top
+ of the last candidate box, which was made non-strict in the unflipped case and remained
+ strict.
+
2012-07-28 Dan Bernstein <[email protected]>
RenderBlock::offsetForContents() is wrong in flipped blocks writing modes
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (123979 => 123980)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-07-29 14:49:07 UTC (rev 123979)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-07-29 17:27:35 UTC (rev 123980)
@@ -4917,6 +4917,7 @@
return createVisiblePosition(0, DOWNSTREAM);
bool linesAreFlipped = style()->isFlippedLinesWritingMode();
+ bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
// look for the closest line box in the root box which is at the passed-in y coordinate
InlineBox* closestBox = 0;
@@ -4928,19 +4929,21 @@
if (!firstRootBoxWithChildren)
firstRootBoxWithChildren = root;
- if (!linesAreFlipped && root->isFirstAfterPageBreak() && pointInLogicalContents.y() < root->lineTopWithLeading())
+ if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogicalContents.y() < root->lineTopWithLeading()
+ || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopWithLeading())))
break;
lastRootBoxWithChildren = root;
// check if this root line box is located at this y coordinate
- if (pointInLogicalContents.y() < root->selectionBottom()) {
+ if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFlipped && pointInLogicalContents.y() == root->selectionBottom())) {
if (linesAreFlipped) {
RootInlineBox* nextRootBoxWithChildren = root->nextRootBox();
while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firstLeafChild())
nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootBox();
- if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstAfterPageBreak() && pointInLogicalContents.y() >= nextRootBoxWithChildren->lineTopWithLeading())
+ if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstAfterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTopWithLeading()
+ || (!blocksAreFlipped && pointInLogicalContents.y() == nextRootBoxWithChildren->lineTopWithLeading())))
continue;
}
closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
@@ -4957,15 +4960,18 @@
}
if (closestBox) {
- if (moveCaretToBoundary && pointInLogicalContents.y() < firstRootBoxWithChildren->selectionTop()
- && pointInLogicalContents.y() < firstRootBoxWithChildren->logicalTop()) {
- InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
- if (box->isLineBreak()) {
- if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak())
- box = newBox;
+ if (moveCaretToBoundary) {
+ LayoutUnit firstRootBoxWithChildrenTop = min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop());
+ if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop
+ || (blocksAreFlipped && pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) {
+ InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
+ if (box->isLineBreak()) {
+ if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak())
+ box = newBox;
+ }
+ // y coordinate is above first root line box, so return the start of the first
+ return VisiblePosition(positionForBox(box, true), DOWNSTREAM);
}
- // y coordinate is above first root line box, so return the start of the first
- return VisiblePosition(positionForBox(box, true), DOWNSTREAM);
}
// pass the box a top position that is inside it
@@ -5025,13 +5031,19 @@
while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
lastCandidateBox = lastCandidateBox->previousSiblingBox();
+ bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
if (lastCandidateBox) {
- if (pointInLogicalContents.y() > logicalTopForChild(lastCandidateBox))
+ if (pointInLogicalContents.y() > logicalTopForChild(lastCandidateBox)
+ || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopForChild(lastCandidateBox)))
return positionForPointRespectingEditingBoundaries(this, lastCandidateBox, pointInContents);
for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
+ if (!isChildHitTestCandidate(childBox))
+ continue;
+ LayoutUnit childLogicalBottom = logicalTopForChild(childBox) + logicalHeightForChild(childBox);
// We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
- if (isChildHitTestCandidate(childBox) && pointInLogicalContents.y() < logicalTopForChild(childBox) + logicalHeightForChild(childBox))
+ if (isChildHitTestCandidate(childBox) && (pointInLogicalContents.y() < childLogicalBottom
+ || (blocksAreFlipped && pointInLogicalContents.y() == childLogicalBottom)))
return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
}
}