Title: [111951] releases/WebKitGTK/webkit-1.8

Diff

Modified: releases/WebKitGTK/webkit-1.8/LayoutTests/ChangeLog (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/LayoutTests/ChangeLog	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/LayoutTests/ChangeLog	2012-03-24 00:58:40 UTC (rev 111951)
@@ -1,3 +1,15 @@
+2012-03-23  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r74971): Can't select a line of RTL text on Facebook
+        https://bugs.webkit.org/show_bug.cgi?id=59435
+
+        Reviewed by Eric Seidel.
+
+        Add a regression test for selecting  multiline bidirectional text.
+
+        * editing/selection/select-line-break-with-opposite-directionality-expected.txt: Added.
+        * editing/selection/select-line-break-with-opposite-directionality.html: Added.
+
 2012-03-23  Antti Koivisto  <[email protected]>
 
         REGRESSION (r104060): Page contents not painted if inserting a new stylesheet and temporary body node

Added: releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality-expected.txt (0 => 111951)


--- releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality-expected.txt	                        (rev 0)
+++ releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality-expected.txt	2012-03-24 00:58:40 UTC (rev 111951)
@@ -0,0 +1,30 @@
+This tests selecting LTR/RTL text that spans multiple lines in RTL/LTR block (opposite directionality). To manually test, select text in each of editable regions below by dragging mouse from one edge to another. The entire line should be selected.
+
+TEST 1 line 1:PASS
+TEST 1 line 2:PASS
+TEST 2 line 1:PASS
+TEST 3 line 1:PASS
+TEST 4 line 1:PASS
+TEST 4 line 2:PASS
+TEST 4 line 3:PASS
+TEST 5 line 1:PASS
+TEST 5 line 2:PASS
+TEST 5 line 3:PASS
+TEST 6 line 1:PASS
+TEST 6 line 2:PASS
+TEST 6 line 3:PASS
+TEST 7 line 1:PASS
+TEST 7 line 2:PASS
+TEST 7 line 3:PASS
+TEST 8 line 1:PASS
+TEST 8 line 2:PASS
+TEST 8 line 3:PASS
+TEST 9 line 1:PASS
+TEST 9 line 2:PASS
+TEST 9 line 3:PASS
+TEST 10 line 1:PASS
+TEST 10 line 2:PASS
+TEST 10 line 3:PASS
+
+
+
Property changes on: releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality-expected.txt
___________________________________________________________________

Added: svn:eol-style

Added: releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality.html (0 => 111951)


--- releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality.html	                        (rev 0)
+++ releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality.html	2012-03-24 00:58:40 UTC (rev 111951)
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html;charset=utf-8">
+<style type="text/css">
+
+.tests {
+    width: 250px;
+    float: left;
+    list-style: none;
+}
+
+.tests div, .tests pre {
+    border: solid 1px black;
+    width: 200px;
+    font-size: 13px;
+    line-height: 13px;
+    padding: 13px;
+}
+
+.hideTestsInDRT .tests {
+    display: none;
+}
+
+</style>
+</head>
+<body>
+<p>This tests selecting LTR/RTL text that spans multiple lines in RTL/LTR block (opposite directionality).
+To manually test, select text in each of editable regions below by dragging mouse from one edge to another.
+The entire line should be selected.</p>
+<body>
+<ol class="tests">
+<li><div contenteditable title="0 3, 4 6">abc<br>def</div></li>
+<li><div contenteditable title="0 3">ابص</div></li>
+<li><div contenteditable dir="rtl" title="0 3">abc</div></li>
+<li><div contenteditable title="0 3, 4, 5 6">ابص<span dir="ltr"><br><br>a</span></div></li>
+<li><div contenteditable dir="rtl" title="0 3, 4, 5 6">abc<span dir="rtl"><br><br>ا</span></div></li>
+<li><div contenteditable title="0 3, 4, 5 6">ابص<br><br>a</div></li>
+<li><div contenteditable dir="rtl" title="0 3, 4, 5 6">ابص<br><br>a</div></li>
+</ol>
+<ol class="tests">
+<li><pre contenteditable title="0 3, 4, 5 6"><span dir="rtl">ابص
+
+a</span></pre></li>
+<li><pre contenteditable dir="rtl" title="0 3, 4, 5 6"><span dir="ltr">abc
+
+a</span></pre></li>
+<li><pre contenteditable dir="rtl" title="0 3, 4, 5 6">abc<span dir="rtl">
+
+a</span></pre></li>
+</ol>
+<pre id="log"><script>
+
+function selectLineSafely(test, lineTop) {
+    var y = test.offsetTop + lineTop + 5;
+    eventSender.mouseMoveTo(test.offsetLeft + 5, y);
+    eventSender.mouseDown();
+
+    eventSender.leapForward(200);
+
+    eventSender.mouseMoveTo(test.offsetLeft + test.offsetWidth - 5, y);
+    eventSender.mouseUp();
+}
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+
+    if (!window.eventSender)
+        document.writeln('This test requires eventSender');
+    else {
+        var tests = document.getElementsByTagName('li');
+        var testNumber = 0;
+
+        for (var i = 0; i < tests.length; i++) {
+            var test = tests[i].firstChild;
+            offsets = test.title.split(', ');
+
+            for (var j = 0; j < offsets.length; j++) {
+                function log(msg) {
+                    return document.write('TEST ' + (i + 1) + ' line ' + (j + 1) + ':' + msg + '\n');
+                }
+
+                var start = parseInt(offsets[j].split(' ')[0]);
+                var afterEnd = parseInt(offsets[j].split(' ')[1]); // Might be NaN
+                var selection = window.getSelection();
+
+                selectLineSafely(test, 13 * (j + 1));
+
+                var actual = selection.toString();
+                var expected = test.innerText.substr(start, afterEnd);
+                if (actual == expected)
+                    log('PASS');
+                else
+                    log('FAIL - expected "' + expected + '" but got "' + actual + '"');
+            }
+        }
+    }
+
+    document.body.className = 'hideTestsInDRT';
+}
+
+document.addEventListener('selectionchange', function () {
+    var selection = window.getSelection();
+    if (selection.isCollapsed)
+        document.getElementById('log').innerHTML += selection.baseOffset + '\n';
+    else
+        document.getElementById('log').innerHTML += selection.baseOffset + ':' + selection.extentOffset + '\n';
+})
+
+</script
+></body>
+</html>
Property changes on: releases/WebKitGTK/webkit-1.8/LayoutTests/editing/selection/select-line-break-with-opposite-directionality.html
___________________________________________________________________

Added: svn:eol-style

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/ChangeLog (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/ChangeLog	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/ChangeLog	2012-03-24 00:58:40 UTC (rev 111951)
@@ -1,3 +1,49 @@
+2012-03-23  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r74971): Can't select a line of RTL text on Facebook
+        https://bugs.webkit.org/show_bug.cgi?id=59435
+
+        Reviewed by Eric Seidel.
+
+        The bug was caused by inline text boxes created by BRs being placed at the end of the line
+        according to the block's direction regardless of its unicode bidi-level. e.g. if we have
+        <div dir="rtl"><span dir="ltr">hello<br>world</span></div>
+        the inline box generated by the br has the bidi-level of 2 like the rest of text in the span.
+        This inline text box gives an illusion of having text on the left of "hello" to hit testing
+        and editing code and causes all sorts of problems.
+
+        Fixed the bug by replacing calls to nextLeafChild and prevLeafChild by newly introduced
+        nextLeafChildIgnoringLineBreak and prevLeafChildIgnoringLineBreak. These two functions will
+        return 0 when they hit the end of a line or inline text box that's a line break. In effect,
+        hit testing and editing code can ignore inline boxes generated by br's.
+
+        In the long term, we should move these two functions into RenderedPosition along with the rest
+        of code that converts a Position and an inline box, offset pair.
+
+        Test: editing/selection/select-line-break-with-opposite-directionality.html
+
+        * dom/Position.cpp:
+        (WebCore::Position::getInlineBoxAndOffset):
+        * editing/RenderedPosition.cpp:
+        (WebCore::RenderedPosition::prevLeafChild):
+        (WebCore::RenderedPosition::nextLeafChild):
+        * rendering/InlineBox.cpp:
+        (WebCore::InlineBox::nextLeafChildIgnoringLineBreak):
+        (WebCore::InlineBox::prevLeafChildIgnoringLineBreak):
+        * rendering/InlineBox.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::positionForPointWithInlineChildren):
+        * rendering/RenderText.cpp:
+        (WebCore::lineDirectionPointFitsInBox): If we're on the left of a RTL line, we should stay at
+        upstream position since we're at the end of a line.
+        (WebCore::createVisiblePositionAfterAdjustingOffsetForBiDi): Merge the two special cases into
+        the general loop as the comment suggests. Skip an inline text box for a line break at the left
+        edge when there are more line boxes on the line.
+        (WebCore::RenderText::positionForPoint):
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::closestLeafChildForLogicalLeftPosition): Ignore line boxes created for
+        line boxes when there are other boxes on the line.
+
 2012-03-23  Antti Koivisto  <[email protected]>
 
         REGRESSION (r104060): Page contents not painted if inserting a new stylesheet and temporary body node

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/dom/Position.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/dom/Position.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/dom/Position.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -1152,7 +1152,8 @@
             }
 
             if (((caretOffset == caretMaxOffset) ^ (affinity == DOWNSTREAM))
-                || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM)))
+                || ((caretOffset == caretMinOffset) ^ (affinity == UPSTREAM))
+                || (caretOffset == caretMaxOffset && box->nextLeafChild() && box->nextLeafChild()->isLineBreak()))
                 break;
 
             candidate = box;
@@ -1217,10 +1218,10 @@
     }
 
     if (caretOffset == inlineBox->caretLeftmostOffset()) {
-        InlineBox* prevBox = inlineBox->prevLeafChild();
+        InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak();
         if (!prevBox || prevBox->bidiLevel() < level) {
             // Left edge of a secondary run. Set to the right edge of the entire run.
-            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
+            while (InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
                 if (nextBox->bidiLevel() < level)
                     break;
                 inlineBox = nextBox;
@@ -1228,7 +1229,7 @@
             caretOffset = inlineBox->caretRightmostOffset();
         } else if (prevBox->bidiLevel() > level) {
             // Right edge of a "tertiary" run. Set to the left edge of that run.
-            while (InlineBox* tertiaryBox = inlineBox->prevLeafChild()) {
+            while (InlineBox* tertiaryBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
                 if (tertiaryBox->bidiLevel() <= level)
                     break;
                 inlineBox = tertiaryBox;
@@ -1236,10 +1237,10 @@
             caretOffset = inlineBox->caretLeftmostOffset();
         }
     } else {
-        InlineBox* nextBox = inlineBox->nextLeafChild();
+        InlineBox* nextBox = inlineBox->nextLeafChildIgnoringLineBreak();
         if (!nextBox || nextBox->bidiLevel() < level) {
             // Right edge of a secondary run. Set to the left edge of the entire run.
-            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
+            while (InlineBox* prevBox = inlineBox->prevLeafChildIgnoringLineBreak()) {
                 if (prevBox->bidiLevel() < level)
                     break;
                 inlineBox = prevBox;
@@ -1247,7 +1248,7 @@
             caretOffset = inlineBox->caretLeftmostOffset();
         } else if (nextBox->bidiLevel() > level) {
             // Left edge of a "tertiary" run. Set to the right edge of that run.
-            while (InlineBox* tertiaryBox = inlineBox->nextLeafChild()) {
+            while (InlineBox* tertiaryBox = inlineBox->nextLeafChildIgnoringLineBreak()) {
                 if (tertiaryBox->bidiLevel() <= level)
                     break;
                 inlineBox = tertiaryBox;

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/editing/RenderedPosition.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/editing/RenderedPosition.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/editing/RenderedPosition.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -100,14 +100,14 @@
 InlineBox* RenderedPosition::prevLeafChild() const
 {
     if (m_prevLeafChild == uncachedInlineBox())
-        m_prevLeafChild = m_inlineBox->prevLeafChild();
+        m_prevLeafChild = m_inlineBox->prevLeafChildIgnoringLineBreak();
     return m_prevLeafChild;
 }
 
 InlineBox* RenderedPosition::nextLeafChild() const
 {
     if (m_nextLeafChild == uncachedInlineBox())
-        m_nextLeafChild = m_inlineBox->nextLeafChild();
+        m_nextLeafChild = m_inlineBox->nextLeafChildIgnoringLineBreak();
     return m_nextLeafChild;
 }
 

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -299,7 +299,23 @@
         leaf = parent()->prevLeafChild();
     return leaf;
 }
-    
+
+InlineBox* InlineBox::nextLeafChildIgnoringLineBreak() const
+{
+    InlineBox* leaf = nextLeafChild();
+    if (leaf && leaf->isLineBreak())
+        return 0;
+    return leaf;
+}
+
+InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const
+{
+    InlineBox* leaf = prevLeafChild();
+    if (leaf && leaf->isLineBreak())
+        return 0;
+    return leaf;
+}
+
 RenderObject::SelectionState InlineBox::selectionState()
 {
     return renderer()->selectionState();

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.h (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.h	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/InlineBox.h	2012-03-24 00:58:40 UTC (rev 111951)
@@ -200,7 +200,13 @@
     
     InlineBox* nextLeafChild() const;
     InlineBox* prevLeafChild() const;
-        
+
+    // Helper functions for editing and hit-testing code.
+    // FIXME: These two functions should be moved to RenderedPosition once the code to convert between
+    // Position and inline box, offset pair is moved to RenderedPosition.
+    InlineBox* nextLeafChildIgnoringLineBreak() const;
+    InlineBox* prevLeafChildIgnoringLineBreak() const;
+
     RenderObject* renderer() const { return m_renderer; }
 
     InlineFlowBox* parent() const

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderBlock.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderBlock.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderBlock.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -4606,12 +4606,17 @@
     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;
+            }
             // y coordinate is above first root line box, so return the start of the first
-            return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
+            return VisiblePosition(positionForBox(box, true), DOWNSTREAM);
         }
 
         // pass the box a top position that is inside it
-        LayoutPoint point(pointInLogicalContents.x(), closestBox->logicalTop());
+        LayoutPoint point(pointInLogicalContents.x(), max(closestBox->root()->lineTop(), closestBox->root()->selectionTop()));
         if (!isHorizontalWritingMode())
             point = point.transposedPoint();
         if (closestBox->renderer()->isReplaced())

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderText.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderText.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RenderText.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -479,8 +479,11 @@
 
     // the x coordinate is equal to the left edge of this box
     // the affinity must be downstream so the position doesn't jump back to the previous line
-    if (pointLineDirection == box->logicalLeft())
+    // except when box is the first box in the line
+    if (pointLineDirection <= box->logicalLeft()) {
+        shouldAffinityBeDownstream = !box->prevLeafChild() ? UpstreamIfPositionIsNotAtStart : AlwaysDownstream;
         return true;
+    }
 
     // and the x coordinate is to the left of the right edge of this box
     // check to see if position goes in this box
@@ -491,10 +494,10 @@
 
     // box is first on line
     // and the x coordinate is to the left of the first text box left edge
-    if (!box->prevOnLine() && pointLineDirection < box->logicalLeft())
+    if (!box->prevLeafChildIgnoringLineBreak() && pointLineDirection < box->logicalLeft())
         return true;
 
-    if (!box->nextOnLine()) {
+    if (!box->nextLeafChildIgnoringLineBreak()) {
         // box is last on line
         // and the x coordinate is to the right of the last text box right edge
         // generate VisiblePosition, use UPSTREAM affinity if possible
@@ -535,7 +538,7 @@
     if (positionIsAtStartOfBox == box->isLeftToRightDirection()) {
         // offset is on the left edge
 
-        const InlineBox* prevBox = box->prevLeafChild();
+        const InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
         if ((prevBox && prevBox->bidiLevel() == box->bidiLevel())
             || box->renderer()->containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA
             return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
@@ -545,7 +548,7 @@
             const InlineBox* leftmostBox;
             do {
                 leftmostBox = prevBox;
-                prevBox = leftmostBox->prevLeafChild();
+                prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
             } while (prevBox && prevBox->bidiLevel() > box->bidiLevel());
             return createVisiblePositionForBox(leftmostBox, leftmostBox->caretRightmostOffset(), shouldAffinityBeDownstream);
         }
@@ -556,7 +559,7 @@
             const InlineBox* nextBox = box;
             do {
                 rightmostBox = nextBox;
-                nextBox = rightmostBox->nextLeafChild();
+                nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
             } while (nextBox && nextBox->bidiLevel() >= box->bidiLevel());
             return createVisiblePositionForBox(rightmostBox,
                 box->isLeftToRightDirection() ? rightmostBox->caretMaxOffset() : rightmostBox->caretMinOffset(), shouldAffinityBeDownstream);
@@ -565,7 +568,7 @@
         return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
     }
 
-    const InlineBox* nextBox = box->nextLeafChild();
+    const InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
     if ((nextBox && nextBox->bidiLevel() == box->bidiLevel())
         || box->renderer()->containingBlock()->style()->direction() == box->direction())
         return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
@@ -576,7 +579,7 @@
         const InlineBox* rightmostBox;
         do {
             rightmostBox = nextBox;
-            nextBox = rightmostBox->nextLeafChild();
+            nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
         } while (nextBox && nextBox->bidiLevel() > box->bidiLevel());
         return createVisiblePositionForBox(rightmostBox, rightmostBox->caretLeftmostOffset(), shouldAffinityBeDownstream);
     }
@@ -587,7 +590,7 @@
         const InlineBox* prevBox = box;
         do {
             leftmostBox = prevBox;
-            prevBox = leftmostBox->prevLeafChild();
+            prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
         } while (prevBox && prevBox->bidiLevel() >= box->bidiLevel());
         return createVisiblePositionForBox(leftmostBox,
             box->isLeftToRightDirection() ? leftmostBox->caretMinOffset() : leftmostBox->caretMaxOffset(), shouldAffinityBeDownstream);
@@ -601,28 +604,14 @@
     if (!firstTextBox() || textLength() == 0)
         return createVisiblePosition(0, DOWNSTREAM);
 
-    // Get the offset for the position, since this will take rtl text into account.
-    int offset;
-
     LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() : point.y();
     LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x();
-    
-    // FIXME: We should be able to roll these special cases into the general cases in the loop below.
-    if (firstTextBox() && pointBlockDirection <  firstTextBox()->root()->selectionBottom() && pointLineDirection < firstTextBox()->logicalLeft()) {
-        // at the y coordinate of the first line or above
-        // and the x coordinate is to the left of the first text box left edge
-        offset = firstTextBox()->offsetForPosition(pointLineDirection);
-        return createVisiblePositionAfterAdjustingOffsetForBiDi(firstTextBox(), offset, UpstreamIfPositionIsNotAtStart);
-    }
-    if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->selectionTop() && pointLineDirection >= lastTextBox()->logicalRight()) {
-        // at the y coordinate of the last line or below
-        // and the x coordinate is to the right of the last text box right edge
-        offset = lastTextBox()->offsetForPosition(pointLineDirection);
-        return createVisiblePositionAfterAdjustingOffsetForBiDi(lastTextBox(), offset, AlwaysUpstream);
-    }
 
-    InlineTextBox* lastBoxAbove = 0;
+    InlineTextBox* lastBox = 0;
     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak())
+            box = box->nextTextBox();
+
         RootInlineBox* rootBox = box->root();
         if (pointBlockDirection >= rootBox->selectionTop() || pointBlockDirection >= rootBox->lineTop()) {
             LayoutUnit bottom = rootBox->selectionBottom();
@@ -631,15 +620,19 @@
 
             if (pointBlockDirection < bottom) {
                 ShouldAffinityBeDownstream shouldAffinityBeDownstream;
-                offset = box->offsetForPosition(pointLineDirection);
                 if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldAffinityBeDownstream))
-                    return createVisiblePositionAfterAdjustingOffsetForBiDi(box, offset, shouldAffinityBeDownstream);
+                    return createVisiblePositionAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream);
             }
-            lastBoxAbove = box;
         }
+        lastBox = box;
     }
 
-    return createVisiblePosition(lastBoxAbove ? lastBoxAbove->start() + lastBoxAbove->len() : 0, DOWNSTREAM);
+    if (lastBox) {
+        ShouldAffinityBeDownstream shouldAffinityBeDownstream;
+        lineDirectionPointFitsInBox(pointLineDirection, lastBox, shouldAffinityBeDownstream);
+        return createVisiblePositionAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream);
+    }
+    return createVisiblePosition(0, DOWNSTREAM);
 }
 
 LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)

Modified: releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RootInlineBox.cpp (111950 => 111951)


--- releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RootInlineBox.cpp	2012-03-24 00:58:06 UTC (rev 111950)
+++ releases/WebKitGTK/webkit-1.8/Source/WebCore/rendering/RootInlineBox.cpp	2012-03-24 00:58:40 UTC (rev 111951)
@@ -580,6 +580,14 @@
 {
     InlineBox* firstLeaf = firstLeafChild();
     InlineBox* lastLeaf = lastLeafChild();
+
+    if (firstLeaf != lastLeaf) {
+        if (firstLeaf->isLineBreak())
+            firstLeaf = firstLeaf->nextLeafChildIgnoringLineBreak();
+        else if (lastLeaf->isLineBreak())
+            lastLeaf = lastLeaf->prevLeafChildIgnoringLineBreak();
+    }
+
     if (firstLeaf == lastLeaf && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
         return firstLeaf;
 
@@ -595,7 +603,7 @@
         return lastLeaf;
 
     InlineBox* closestLeaf = 0;
-    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
+    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChildIgnoringLineBreak()) {
         if (!leaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
             closestLeaf = leaf;
             if (leftPosition < leaf->logicalRight())
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to