[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

morrita at google.com morrita at google.com
Wed Dec 22 11:50:06 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 1632a1f66c490773d8a41a03386995cf0dd7cbac
Author: morrita at google.com <morrita at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Aug 9 11:40:10 2010 +0000

    2010-05-20  MORITA Hajime  <morrita at google.com>
    
            Reviewed by Ojan Vafai.
    
            <http://webkit.org/b/36360>
            Double clicking page's first editable inline element cannot select a word.
            <http://webkit.org/b/36359>
            Double clicking page's last editable inline element causes assertion failure.
    
            * editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt: Added.
            * editing/selection/doubleclick-inline-first-last-contenteditable.html: Added.
            * editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js: Added.
    2010-05-27  MORITA Hajime  <morrita at google.com>
    
            Reviewed by Ojan Vafai.
    
            <http://webkit.org/b/36359>
            Double clicking page's last editable inline element causes assertion failure.
            <http://webkit.org/b/36360>
            Double clicking page's first editable inline element cannot select a word.
    
            nextBoundary() and previousBoundary() assumed that editable
            boundaries are on block-level elements, But it can appear on
            inline-level elements. So we start boundary look-up from the given
            node, instead of the containingBlock of the given node.
            Also, added TextIteratorEndsAtEditingBoundary to
            BackwardsCharacterIterator, otherwise, the VisiblePosition
            returned by BackwardsCharacterIterator might cross an editing
            boundary.
    
            Test: editing/selection/doubleclick-inline-first-last-contenteditable.html
    
            * dom/Position.cpp:
            (WebCore::Position::parentEditingBoundary): Added.
            * dom/Position.h:
            * editing/TextIterator.cpp:
            (WebCore::TextIterator::TextIterator):
            (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
            (WebCore::SimplifiedBackwardsTextIterator::advance):
            (WebCore::SimplifiedBackwardsTextIterator::crossesEditingBoundary): Added.
            (WebCore::SimplifiedBackwardsTextIterator::setCurrentNode): Added.
            (WebCore::SimplifiedBackwardsTextIterator::clearCurrentNode): Added.
            (WebCore::BackwardsCharacterIterator::BackwardsCharacterIterator):
            * editing/TextIterator.h:
            (WebCore::):
            * editing/visible_units.cpp:
            (WebCore::previousBoundary):
            (WebCore::nextBoundary):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64974 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index aee39e9..33c5329 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2010-05-20  MORITA Hajime  <morrita at google.com>
+
+        Reviewed by Ojan Vafai.
+
+        <http://webkit.org/b/36360>
+        Double clicking page's first editable inline element cannot select a word. 
+        <http://webkit.org/b/36359>
+        Double clicking page's last editable inline element causes assertion failure.
+
+        * editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt: Added.
+        * editing/selection/doubleclick-inline-first-last-contenteditable.html: Added.
+        * editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js: Added.  
+
 2010-08-09  Ilya Tikhonovsky  <loislo at chromium.org>
 
         Reviewed by Yury Semikhatsky.
diff --git a/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt
new file mode 100644
index 0000000..230e1b2
--- /dev/null
+++ b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt
@@ -0,0 +1,21 @@
+Test to check if last and first word can be selected when they double-clicked (Bug 36359)
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.getSelection().toString() is 'selectme1'
+PASS window.selectedByModify is 'selectme1'
+PASS window.getSelection().toString() is 'selectme2'
+PASS window.selectedByModify is 'selectme2'
+PASS window.getSelection().toString() is 'selectme3'
+PASS window.selectedByModify is 'selectme3'
+PASS window.getSelection().toString() is 'selectme4'
+PASS window.selectedByModify is 'selectme4'
+PASS window.getSelection().toString() is 'selectme5'
+PASS window.selectedByModify is 'selectme5'
+PASS window.getSelection().toString() is 'selectme6'
+PASS window.selectedByModify is 'selectme6'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html
new file mode 100644
index 0000000..4d388c3
--- /dev/null
+++ b/LayoutTests/editing/selection/doubleclick-inline-first-last-contenteditable.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/js-test-selection-shared.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/doubleclick-inline-first-last-contenteditable.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js b/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js
new file mode 100644
index 0000000..eadc9c4
--- /dev/null
+++ b/LayoutTests/editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js
@@ -0,0 +1,108 @@
+description("Test to check if last and first word can be selected when they double-clicked (Bug 36359)");
+
+function toLiteral(textValue)
+{
+    return "'" + textValue + "'";
+}
+
+function getPositionOfNode(node)
+{
+    var n = node;
+    var offsetX = 0, offsetY = 0;
+
+    while (n) {
+        offsetX += n.offsetLeft;
+        offsetY += n.offsetTop;
+        n = n.offsetParnet;
+    }
+
+    return {
+      "x":  offsetX,
+      "y":  offsetY
+    };
+}
+
+function doubleClickPosition(pos)
+{
+    eventSender.mouseMoveTo(pos.x, pos.y);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+function singleClickPosition(pos)
+{
+    eventSender.mouseMoveTo(pos.x, pos.y);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+var targetRoot = document.createElement("div");
+document.body.appendChild(targetRoot);
+
+var scratchRoot = document.createElement("div");
+document.body.appendChild(scratchRoot);
+
+function computeTextSize(text)
+{
+    scratchRoot.innerHTML = ("<span id='scratch'>" + text + "</span>");
+    var scratch = document.getElementById("scratch");
+    return { width: scratch.offsetWidth, height: scratch.offsetHeight };
+}
+
+function testWithDoublleClick(targetInnerHTML, expectedText)
+{
+    var textSize = computeTextSize(expectedText);
+
+    targetRoot.innerHTML = targetInnerHTML;
+    var target = document.getElementById("target");
+    var nodePosition = getPositionOfNode(target);
+    doubleClickPosition({ x: nodePosition.x + textSize.width / 2, y: nodePosition.y + textSize.height / 2 });
+    shouldBe("window.getSelection().toString()", toLiteral(expectedText));
+}
+
+function testWithClickAndModify(targetInnerHTML, expectedText)
+{
+    var selection = window.getSelection();
+    targetRoot.innerHTML = targetInnerHTML;
+    var target = document.getElementById("target");
+    singleClickPosition(getPositionOfNode(target));
+
+    selection.modify("extend", "forward", "word");
+    var lastHalf = window.getSelection().toString();
+    selection.modify("extend", "backward", "word");
+    var firstHalf = window.getSelection().toString();
+
+    window.selectedByModify = firstHalf + lastHalf;
+    shouldBe("window.selectedByModify", toLiteral(expectedText));
+}
+
+var shouldSelecteFirstWordInline = "<span id='target' contentEditable>selectme1</span> and not select us";
+testWithDoublleClick(shouldSelecteFirstWordInline, "selectme1");
+testWithClickAndModify(shouldSelecteFirstWordInline, "selectme1");
+
+var shouldSelectLastWordInline = "you should ignore us but <span id='target' contentEditable>selectme2</span>";
+testWithDoublleClick(shouldSelectLastWordInline, "selectme2");
+testWithClickAndModify(shouldSelectLastWordInline, "selectme2");
+
+var shouldSelectMiddleWordInline = "you should get <span id='target' contentEditable>selectme3</span> selected";
+testWithDoublleClick(shouldSelectMiddleWordInline, "selectme3");
+testWithClickAndModify(shouldSelectMiddleWordInline, "selectme3");
+
+var shouldSelecteFirstWordBlock = "<div id='target' contentEditable>selectme4</div> and not select us";
+testWithDoublleClick(shouldSelecteFirstWordBlock, "selectme4");
+testWithClickAndModify(shouldSelecteFirstWordBlock, "selectme4");
+
+var shouldSelectLastWordBlock = "you should ignore us but <div id='target' contentEditable>selectme5</div>";
+testWithDoublleClick(shouldSelectLastWordBlock, "selectme5");
+testWithClickAndModify(shouldSelectLastWordBlock, "selectme5");
+
+var shouldSelectMiddleWordBlock = "you should get <div id='target' contentEditable>selectme6</div> selected";
+testWithDoublleClick(shouldSelectMiddleWordBlock, "selectme6");
+testWithClickAndModify(shouldSelectMiddleWordBlock, "selectme6");
+
+targetRoot.style.display = "none";
+scratchRoot.style.display = "none";
+
+var successfullyParsed = true;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index ef2b2c9..f7c7ec7 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2010-05-27  MORITA Hajime  <morrita at google.com>
+
+        Reviewed by Ojan Vafai.
+
+        <http://webkit.org/b/36359>
+        Double clicking page's last editable inline element causes assertion failure.
+        <http://webkit.org/b/36360>
+        Double clicking page's first editable inline element cannot select a word. 
+
+        nextBoundary() and previousBoundary() assumed that editable
+        boundaries are on block-level elements, But it can appear on
+        inline-level elements. So we start boundary look-up from the given
+        node, instead of the containingBlock of the given node.
+        Also, added TextIteratorEndsAtEditingBoundary to
+        BackwardsCharacterIterator, otherwise, the VisiblePosition
+        returned by BackwardsCharacterIterator might cross an editing
+        boundary.
+
+        Test: editing/selection/doubleclick-inline-first-last-contenteditable.html        
+
+        * dom/Position.cpp:
+        (WebCore::Position::parentEditingBoundary): Added.
+        * dom/Position.h:
+        * editing/TextIterator.cpp:
+        (WebCore::TextIterator::TextIterator):
+        (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
+        (WebCore::SimplifiedBackwardsTextIterator::advance):
+        (WebCore::SimplifiedBackwardsTextIterator::crossesEditingBoundary): Added.
+        (WebCore::SimplifiedBackwardsTextIterator::setCurrentNode): Added.
+        (WebCore::SimplifiedBackwardsTextIterator::clearCurrentNode): Added.
+        (WebCore::BackwardsCharacterIterator::BackwardsCharacterIterator):
+        * editing/TextIterator.h:
+        (WebCore::):
+        * editing/visible_units.cpp:
+        (WebCore::previousBoundary):
+        (WebCore::nextBoundary):
+
 2010-08-09  Ilya Tikhonovsky  <loislo at chromium.org>
 
         Reviewed by Yury Semikhatsky.
diff --git a/WebCore/dom/Position.cpp b/WebCore/dom/Position.cpp
index 65b7261..4758bd9 100644
--- a/WebCore/dom/Position.cpp
+++ b/WebCore/dom/Position.cpp
@@ -328,6 +328,23 @@ bool Position::atEditingBoundary() const
         && prevPosition.isNotNull() && !prevPosition.node()->isContentEditable();
 }
 
+Node* Position::parentEditingBoundary() const
+{
+    if (!m_anchorNode || !m_anchorNode->document())
+        return 0;
+
+    Node* documentElement = m_anchorNode->document()->documentElement();
+    if (!documentElement)
+        return 0;
+
+    Node* boundary = m_anchorNode.get();
+    while (boundary != documentElement && boundary->parentNode() && m_anchorNode->isContentEditable() == boundary->parentNode()->isContentEditable())
+        boundary = boundary->parentNode();
+    
+    return boundary;
+}
+
+
 bool Position::atStartOfTree() const
 {
     if (isNull())
diff --git a/WebCore/dom/Position.h b/WebCore/dom/Position.h
index f606c29..9f2ee24 100644
--- a/WebCore/dom/Position.h
+++ b/WebCore/dom/Position.h
@@ -138,6 +138,7 @@ public:
 
     // Returns true if the visually equivalent positions around have different editability
     bool atEditingBoundary() const;
+    Node* parentEditingBoundary() const;
     
     bool atStartOfTree() const;
     bool atEndOfTree() const;
diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp
index f3bd9df..4d6c14a 100644
--- a/WebCore/editing/TextIterator.cpp
+++ b/WebCore/editing/TextIterator.cpp
@@ -272,6 +272,9 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior)
     , m_entersTextControls(behavior & TextIteratorEntersTextControls)
     , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding)
 {
+    // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609
+    ASSERT(behavior != TextIteratorEndsAtEditingBoundary);
+
     if (!r)
         return;
 
@@ -944,13 +947,19 @@ Node* TextIterator::node() const
 // --------
 
 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
-    : m_positionNode(0)
+    : m_behavior(TextIteratorDefaultBehavior)
+    , m_node(0)
+    , m_positionNode(0)
 {
 }
 
-SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
-    : m_positionNode(0)
+SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior)
+    : m_behavior(behavior)
+    , m_node(0)
+    , m_positionNode(0)
 {
+    ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary);
+
     if (!r)
         return;
 
@@ -974,7 +983,7 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
         }
     }
 
-    m_node = endNode;
+    setCurrentNode(endNode);
     setUpFullyClippedStack(m_fullyClippedStack, m_node);    
     m_offset = endOffset;
     m_handledNode = false;
@@ -1038,12 +1047,9 @@ void SimplifiedBackwardsTextIterator::advance()
                 }            
             }
             // Exit all other containers.
-            next = m_node->previousSibling();
-            while (!next) {
-                Node* parentNode = parentCrossingShadowBoundaries(m_node);
-                if (!parentNode)
+            while (!m_node->previousSibling()) {
+                if (!setCurrentNode(parentCrossingShadowBoundaries(m_node)))
                     break;
-                m_node = parentNode;
                 m_fullyClippedStack.pop();
                 exitNode();
                 if (m_positionNode) {
@@ -1051,14 +1057,17 @@ void SimplifiedBackwardsTextIterator::advance()
                     m_handledChildren = true;
                     return;
                 }
-                next = m_node->previousSibling();
             }
+
+            next = m_node->previousSibling();
             m_fullyClippedStack.pop();
         }
         
-        m_node = next;
-        if (m_node)
+        if (m_node && setCurrentNode(next))
             pushFullyClippedState(m_fullyClippedStack, m_node);
+        else
+            clearCurrentNode();
+
         // For the purpose of word boundary detection,
         // we should iterate all visible text and trailing (collapsed) whitespaces. 
         m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0;
@@ -1137,6 +1146,26 @@ void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta
     m_lastCharacter = c;
 }
 
+bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const
+{
+    return m_node && m_node->isContentEditable() != node->isContentEditable();
+}
+
+bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node)
+{
+    if (!node)
+        return false;
+    if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node))
+        return false;
+    m_node = node;
+    return true;
+}
+
+void SimplifiedBackwardsTextIterator::clearCurrentNode()
+{
+    m_node = 0;
+}
+
 PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const
 {
     if (m_positionNode)
@@ -1262,11 +1291,11 @@ BackwardsCharacterIterator::BackwardsCharacterIterator()
 {
 }
 
-BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range)
+BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior)
     : m_offset(0)
     , m_runOffset(0)
     , m_atBreak(true)
-    , m_textIterator(range)
+    , m_textIterator(range, behavior)
 {
     while (!atEnd() && !m_textIterator.length())
         m_textIterator.advance();
diff --git a/WebCore/editing/TextIterator.h b/WebCore/editing/TextIterator.h
index ba381b9..6a0d685 100644
--- a/WebCore/editing/TextIterator.h
+++ b/WebCore/editing/TextIterator.h
@@ -73,6 +73,7 @@ enum TextIteratorBehavior {
     TextIteratorEmitsCharactersBetweenAllVisiblePositions = 1 << 0,
     TextIteratorEntersTextControls = 1 << 1,
     TextIteratorEmitsTextsWithoutTranscoding = 1 << 2,
+    TextIteratorEndsAtEditingBoundary = 1 << 3
 };
 
 class TextIterator {
@@ -167,7 +168,7 @@ private:
 class SimplifiedBackwardsTextIterator {
 public:
     SimplifiedBackwardsTextIterator();
-    explicit SimplifiedBackwardsTextIterator(const Range*);
+    explicit SimplifiedBackwardsTextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
     
     bool atEnd() const { return !m_positionNode; }
     void advance();
@@ -183,7 +184,11 @@ private:
     bool handleReplacedElement();
     bool handleNonTextNode();
     void emitCharacter(UChar, Node*, int startOffset, int endOffset);
-    
+    bool crossesEditingBoundary(Node*) const;
+    bool setCurrentNode(Node*);
+    void clearCurrentNode();
+
+    TextIteratorBehavior m_behavior;
     // Current position, not necessarily of the text being returned, but position
     // as we walk through the DOM tree.
     Node* m_node;
@@ -247,7 +252,7 @@ private:
 class BackwardsCharacterIterator {
 public:
     BackwardsCharacterIterator();
-    explicit BackwardsCharacterIterator(const Range*);
+    explicit BackwardsCharacterIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
 
     void advance(int);
 
@@ -256,6 +261,7 @@ public:
     PassRefPtr<Range> range() const;
 
 private:
+    TextIteratorBehavior m_behavior;
     int m_offset;
     int m_runOffset;
     bool m_atBreak;
diff --git a/WebCore/editing/visible_units.cpp b/WebCore/editing/visible_units.cpp
index dd48406..4fce2d9 100644
--- a/WebCore/editing/visible_units.cpp
+++ b/WebCore/editing/visible_units.cpp
@@ -75,20 +75,11 @@ typedef unsigned (*BoundarySearchFunction)(const UChar*, unsigned length, unsign
 static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
 {
     Position pos = c.deepEquivalent();
-    Node *n = pos.node();
-    if (!n)
-        return VisiblePosition();
-    Document *d = n->document();
-    Node *de = d->documentElement();
-    if (!de)
-        return VisiblePosition();
-    Node *boundary = n->enclosingBlockFlowElement();
+    Node* boundary = pos.parentEditingBoundary();
     if (!boundary)
         return VisiblePosition();
-    bool isContentEditable = boundary->isContentEditable();
-    while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
-        boundary = boundary->parentNode();
 
+    Document* d = boundary->document();
     Position start = rangeCompliantEquivalent(Position(boundary, 0));
     Position end = rangeCompliantEquivalent(pos);
     RefPtr<Range> searchRange = Range::create(d);
@@ -121,7 +112,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
     if (ec)
         return VisiblePosition();
 
-    SimplifiedBackwardsTextIterator it(searchRange.get());
+    SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsAtEditingBoundary);
     unsigned next = 0;
     bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
     bool needMoreContext = false;
@@ -156,7 +147,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
             pos = Position(node, next);
         else {
             // Use the character iterator to translate the next value into a DOM position.
-            BackwardsCharacterIterator charIt(searchRange.get());
+            BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
             charIt.advance(string.size() - suffixLength - next);
             pos = charIt.range()->endPosition();
         }
@@ -168,20 +159,11 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
 static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
 {
     Position pos = c.deepEquivalent();
-    Node *n = pos.node();
-    if (!n)
-        return VisiblePosition();
-    Document *d = n->document();
-    Node *de = d->documentElement();
-    if (!de)
-        return VisiblePosition();
-    Node *boundary = n->enclosingBlockFlowElement();
+    Node* boundary = pos.parentEditingBoundary();
     if (!boundary)
         return VisiblePosition();
-    bool isContentEditable = boundary->isContentEditable();
-    while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
-        boundary = boundary->parentNode();
 
+    Document* d = boundary->document();
     RefPtr<Range> searchRange(d->createRange());
     Position start(rangeCompliantEquivalent(pos));
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list