Changeset 64974 in webkit


Ignore:
Timestamp:
Aug 9, 2010 4:40:10 AM (14 years ago)
Author:
morrita@google.com
Message:

2010-05-20 MORITA Hajime <morrita@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@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):
Location:
trunk
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r64973 r64974  
     12010-05-20  MORITA Hajime  <morrita@google.com>
     2
     3        Reviewed by Ojan Vafai.
     4
     5        <http://webkit.org/b/36360>
     6        Double clicking page's first editable inline element cannot select a word.
     7        <http://webkit.org/b/36359>
     8        Double clicking page's last editable inline element causes assertion failure.
     9
     10        * editing/selection/doubleclick-inline-first-last-contenteditable-expected.txt: Added.
     11        * editing/selection/doubleclick-inline-first-last-contenteditable.html: Added.
     12        * editing/selection/script-tests/doubleclick-inline-first-last-contenteditable.js: Added. 
     13
    1142010-08-09  Ilya Tikhonovsky  <loislo@chromium.org>
    215
  • trunk/WebCore/ChangeLog

    r64973 r64974  
     12010-05-27  MORITA Hajime  <morrita@google.com>
     2
     3        Reviewed by Ojan Vafai.
     4
     5        <http://webkit.org/b/36359>
     6        Double clicking page's last editable inline element causes assertion failure.
     7        <http://webkit.org/b/36360>
     8        Double clicking page's first editable inline element cannot select a word.
     9
     10        nextBoundary() and previousBoundary() assumed that editable
     11        boundaries are on block-level elements, But it can appear on
     12        inline-level elements. So we start boundary look-up from the given
     13        node, instead of the containingBlock of the given node.
     14        Also, added TextIteratorEndsAtEditingBoundary to
     15        BackwardsCharacterIterator, otherwise, the VisiblePosition
     16        returned by BackwardsCharacterIterator might cross an editing
     17        boundary.
     18
     19        Test: editing/selection/doubleclick-inline-first-last-contenteditable.html       
     20
     21        * dom/Position.cpp:
     22        (WebCore::Position::parentEditingBoundary): Added.
     23        * dom/Position.h:
     24        * editing/TextIterator.cpp:
     25        (WebCore::TextIterator::TextIterator):
     26        (WebCore::SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator):
     27        (WebCore::SimplifiedBackwardsTextIterator::advance):
     28        (WebCore::SimplifiedBackwardsTextIterator::crossesEditingBoundary): Added.
     29        (WebCore::SimplifiedBackwardsTextIterator::setCurrentNode): Added.
     30        (WebCore::SimplifiedBackwardsTextIterator::clearCurrentNode): Added.
     31        (WebCore::BackwardsCharacterIterator::BackwardsCharacterIterator):
     32        * editing/TextIterator.h:
     33        (WebCore::):
     34        * editing/visible_units.cpp:
     35        (WebCore::previousBoundary):
     36        (WebCore::nextBoundary):
     37
    1382010-08-09  Ilya Tikhonovsky  <loislo@chromium.org>
    239
  • trunk/WebCore/dom/Position.cpp

    r61724 r64974  
    329329}
    330330
     331Node* Position::parentEditingBoundary() const
     332{
     333    if (!m_anchorNode || !m_anchorNode->document())
     334        return 0;
     335
     336    Node* documentElement = m_anchorNode->document()->documentElement();
     337    if (!documentElement)
     338        return 0;
     339
     340    Node* boundary = m_anchorNode.get();
     341    while (boundary != documentElement && boundary->parentNode() && m_anchorNode->isContentEditable() == boundary->parentNode()->isContentEditable())
     342        boundary = boundary->parentNode();
     343   
     344    return boundary;
     345}
     346
     347
    331348bool Position::atStartOfTree() const
    332349{
  • trunk/WebCore/dom/Position.h

    r61441 r64974  
    139139    // Returns true if the visually equivalent positions around have different editability
    140140    bool atEditingBoundary() const;
     141    Node* parentEditingBoundary() const;
    141142   
    142143    bool atStartOfTree() const;
  • trunk/WebCore/editing/TextIterator.cpp

    r58153 r64974  
    273273    , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding)
    274274{
     275    // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609
     276    ASSERT(behavior != TextIteratorEndsAtEditingBoundary);
     277
    275278    if (!r)
    276279        return;
     
    945948
    946949SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
    947     : m_positionNode(0)
    948 {
    949 }
    950 
    951 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r)
    952     : m_positionNode(0)
    953 {
     950    : m_behavior(TextIteratorDefaultBehavior)
     951    , m_node(0)
     952    , m_positionNode(0)
     953{
     954}
     955
     956SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior)
     957    : m_behavior(behavior)
     958    , m_node(0)
     959    , m_positionNode(0)
     960{
     961    ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary);
     962
    954963    if (!r)
    955964        return;
     
    975984    }
    976985
    977     m_node = endNode;
     986    setCurrentNode(endNode);
    978987    setUpFullyClippedStack(m_fullyClippedStack, m_node);   
    979988    m_offset = endOffset;
     
    10391048            }
    10401049            // Exit all other containers.
    1041             next = m_node->previousSibling();
    1042             while (!next) {
    1043                 Node* parentNode = parentCrossingShadowBoundaries(m_node);
    1044                 if (!parentNode)
     1050            while (!m_node->previousSibling()) {
     1051                if (!setCurrentNode(parentCrossingShadowBoundaries(m_node)))
    10451052                    break;
    1046                 m_node = parentNode;
    10471053                m_fullyClippedStack.pop();
    10481054                exitNode();
     
    10521058                    return;
    10531059                }
    1054                 next = m_node->previousSibling();
    10551060            }
     1061
     1062            next = m_node->previousSibling();
    10561063            m_fullyClippedStack.pop();
    10571064        }
    10581065       
    1059         m_node = next;
    1060         if (m_node)
     1066        if (m_node && setCurrentNode(next))
    10611067            pushFullyClippedState(m_fullyClippedStack, m_node);
     1068        else
     1069            clearCurrentNode();
     1070
    10621071        // For the purpose of word boundary detection,
    10631072        // we should iterate all visible text and trailing (collapsed) whitespaces.
     
    11361145    m_textLength = 1;
    11371146    m_lastCharacter = c;
     1147}
     1148
     1149bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const
     1150{
     1151    return m_node && m_node->isContentEditable() != node->isContentEditable();
     1152}
     1153
     1154bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node)
     1155{
     1156    if (!node)
     1157        return false;
     1158    if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node))
     1159        return false;
     1160    m_node = node;
     1161    return true;
     1162}
     1163
     1164void SimplifiedBackwardsTextIterator::clearCurrentNode()
     1165{
     1166    m_node = 0;
    11381167}
    11391168
     
    12631292}
    12641293
    1265 BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range)
     1294BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior)
    12661295    : m_offset(0)
    12671296    , m_runOffset(0)
    12681297    , m_atBreak(true)
    1269     , m_textIterator(range)
     1298    , m_textIterator(range, behavior)
    12701299{
    12711300    while (!atEnd() && !m_textIterator.length())
  • trunk/WebCore/editing/TextIterator.h

    r58149 r64974  
    7474    TextIteratorEntersTextControls = 1 << 1,
    7575    TextIteratorEmitsTextsWithoutTranscoding = 1 << 2,
     76    TextIteratorEndsAtEditingBoundary = 1 << 3
    7677};
    7778
     
    168169public:
    169170    SimplifiedBackwardsTextIterator();
    170     explicit SimplifiedBackwardsTextIterator(const Range*);
     171    explicit SimplifiedBackwardsTextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
    171172   
    172173    bool atEnd() const { return !m_positionNode; }
     
    184185    bool handleNonTextNode();
    185186    void emitCharacter(UChar, Node*, int startOffset, int endOffset);
    186    
     187    bool crossesEditingBoundary(Node*) const;
     188    bool setCurrentNode(Node*);
     189    void clearCurrentNode();
     190
     191    TextIteratorBehavior m_behavior;
    187192    // Current position, not necessarily of the text being returned, but position
    188193    // as we walk through the DOM tree.
     
    248253public:
    249254    BackwardsCharacterIterator();
    250     explicit BackwardsCharacterIterator(const Range*);
     255    explicit BackwardsCharacterIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
    251256
    252257    void advance(int);
     
    257262
    258263private:
     264    TextIteratorBehavior m_behavior;
    259265    int m_offset;
    260266    int m_runOffset;
  • trunk/WebCore/editing/visible_units.cpp

    r63918 r64974  
    7676{
    7777    Position pos = c.deepEquivalent();
    78     Node *n = pos.node();
    79     if (!n)
    80         return VisiblePosition();
    81     Document *d = n->document();
    82     Node *de = d->documentElement();
    83     if (!de)
    84         return VisiblePosition();
    85     Node *boundary = n->enclosingBlockFlowElement();
     78    Node* boundary = pos.parentEditingBoundary();
    8679    if (!boundary)
    8780        return VisiblePosition();
    88     bool isContentEditable = boundary->isContentEditable();
    89     while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
    90         boundary = boundary->parentNode();
    91 
     81
     82    Document* d = boundary->document();
    9283    Position start = rangeCompliantEquivalent(Position(boundary, 0));
    9384    Position end = rangeCompliantEquivalent(pos);
     
    122113        return VisiblePosition();
    123114
    124     SimplifiedBackwardsTextIterator it(searchRange.get());
     115    SimplifiedBackwardsTextIterator it(searchRange.get(), TextIteratorEndsAtEditingBoundary);
    125116    unsigned next = 0;
    126117    bool inTextSecurityMode = start.node() && start.node()->renderer() && start.node()->renderer()->style()->textSecurity() != TSNONE;
     
    157148        else {
    158149            // Use the character iterator to translate the next value into a DOM position.
    159             BackwardsCharacterIterator charIt(searchRange.get());
     150            BackwardsCharacterIterator charIt(searchRange.get(), TextIteratorEndsAtEditingBoundary);
    160151            charIt.advance(string.size() - suffixLength - next);
    161152            pos = charIt.range()->endPosition();
     
    169160{
    170161    Position pos = c.deepEquivalent();
    171     Node *n = pos.node();
    172     if (!n)
    173         return VisiblePosition();
    174     Document *d = n->document();
    175     Node *de = d->documentElement();
    176     if (!de)
    177         return VisiblePosition();
    178     Node *boundary = n->enclosingBlockFlowElement();
     162    Node* boundary = pos.parentEditingBoundary();
    179163    if (!boundary)
    180164        return VisiblePosition();
    181     bool isContentEditable = boundary->isContentEditable();
    182     while (boundary && boundary != de && boundary->parentNode() && isContentEditable == boundary->parentNode()->isContentEditable())
    183         boundary = boundary->parentNode();
    184 
     165
     166    Document* d = boundary->document();
    185167    RefPtr<Range> searchRange(d->createRange());
    186168    Position start(rangeCompliantEquivalent(pos));
Note: See TracChangeset for help on using the changeset viewer.