Changeset 164180 in webkit


Ignore:
Timestamp:
Feb 15, 2014 2:32:05 PM (10 years ago)
Author:
rniwa@webkit.org
Message:

computeSelectionStart and computeSelectionEnd shouldn't trigger synchronous layout
https://bugs.webkit.org/show_bug.cgi?id=128806

Reviewed by Darin Adler.

Added indexForPosition to HTMLTextFormControlElement. Like r163825, this patch traverses the DOM tree
instead of the render tree to compute the index for a given position.

We traverse the DOM Tree backwards starting at the specified Position all the way back to the beginning
of the inner text element. The index is computed as the number of characters we encountered during
this backwards DOM traversal.

It's worth noting that passedPosition.computeNodeBeforePosition() returns and only returns 0 when the
position is before the first node of its parent or inside a text node. In such cases, we call
passedPosition.containerNode() to find the parent or the text node.

  • html/HTMLTextFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::indexForVisiblePosition): Use indexForPosition.
(WebCore::HTMLTextFormControlElement::computeSelectionStart): Ditto.
(WebCore::HTMLTextFormControlElement::computeSelectionEnd): Dotto.
(WebCore::finishText): Cleanup. Use newlineCharacter instead of hard-coding '\n'.
(WebCore::HTMLTextFormControlElement::indexForPosition): Added. See above for the description.

  • html/HTMLTextFormControlElement.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r164177 r164180  
     12014-02-15  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        computeSelectionStart and computeSelectionEnd shouldn't trigger synchronous layout
     4        https://bugs.webkit.org/show_bug.cgi?id=128806
     5
     6        Reviewed by Darin Adler.
     7
     8        Added indexForPosition to HTMLTextFormControlElement. Like r163825, this patch traverses the DOM tree
     9        instead of the render tree to compute the index for a given position.
     10
     11        We traverse the DOM Tree backwards starting at the specified Position all the way back to the beginning
     12        of the inner text element. The index is computed as the number of characters we encountered during
     13        this backwards DOM traversal.
     14
     15        It's worth noting that passedPosition.computeNodeBeforePosition() returns and only returns 0 when the
     16        position is before the first node of its parent or inside a text node. In such cases, we call
     17        passedPosition.containerNode() to find the parent or the text node.
     18
     19        * html/HTMLTextFormControlElement.cpp:
     20        (WebCore::HTMLTextFormControlElement::indexForVisiblePosition): Use indexForPosition.
     21        (WebCore::HTMLTextFormControlElement::computeSelectionStart): Ditto.
     22        (WebCore::HTMLTextFormControlElement::computeSelectionEnd): Dotto.
     23        (WebCore::finishText): Cleanup. Use newlineCharacter instead of hard-coding '\n'.
     24        (WebCore::HTMLTextFormControlElement::indexForPosition): Added. See above for the description.
     25        * html/HTMLTextFormControlElement.h:
     26
    1272014-02-15  Brent Fulgham  <bfulgham@apple.com>
    228
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp

    r164156 r164180  
    331331    if (!innerText || !innerText->contains(position.deepEquivalent().anchorNode()))
    332332        return 0;
    333     bool forSelectionPreservation = false;
    334     unsigned index = WebCore::indexForVisiblePosition(innerTextElement(), position, forSelectionPreservation);
     333    unsigned index = indexForPosition(position.deepEquivalent());
    335334    ASSERT(VisiblePosition(positionForIndex(innerTextElement(), index)) == position);
    336335    return index;
     
    361360        return 0;
    362361
    363     return indexForVisiblePosition(frame->selection().selection().start());
     362    return indexForPosition(frame->selection().selection().start());
    364363}
    365364
     
    380379        return 0;
    381380
    382     return indexForVisiblePosition(frame->selection().selection().end());
     381    return indexForPosition(frame->selection().selection().end());
    383382}
    384383
     
    538537    // Remove one trailing newline; there's always one that's collapsed out by rendering.
    539538    size_t size = result.length();
    540     if (size && result[size - 1] == '\n')
     539    if (size && result[size - 1] == newlineCharacter)
    541540        result.resize(--size);
    542541    return result.toString();
     
    578577    }
    579578    return lastPositionInNode(innerText);
     579}
     580
     581unsigned HTMLTextFormControlElement::indexForPosition(const Position& passedPosition) const
     582{
     583    TextControlInnerTextElement* innerText = innerTextElement();
     584    if (!innerText || !innerText->contains(passedPosition.anchorNode()) || passedPosition.isNull())
     585        return 0;
     586
     587    if (positionBeforeNode(innerText) == passedPosition)
     588        return 0;
     589
     590    unsigned index = 0;
     591    Node* startNode = passedPosition.computeNodeBeforePosition();
     592    if (!startNode)
     593        startNode = passedPosition.containerNode();
     594    ASSERT(startNode);
     595    ASSERT(innerText->contains(startNode));
     596
     597    for (Node* node = startNode; node; node = NodeTraversal::previous(node, innerText)) {
     598        if (node->isTextNode()) {
     599            unsigned length = toText(*node).length();
     600            if (node == passedPosition.containerNode())
     601                index += std::min<unsigned>(length, passedPosition.offsetInContainerNode());
     602            else
     603                index += length;
     604        } else if (node->hasTagName(brTag))
     605            index++;
     606    }
     607
     608    unsigned length = innerTextValue().length();
     609    index = std::min(index, length); // FIXME: We shouldn't have to call innerTextValue() just to ignore the last LF. See finishText.
     610#ifndef ASSERT_DISABLED
     611    VisiblePosition visiblePosition = passedPosition;
     612    unsigned indexComputedByVisiblePosition = 0;
     613    if (visiblePosition.isNotNull())
     614        indexComputedByVisiblePosition = WebCore::indexForVisiblePosition(innerText, visiblePosition, false /* forSelectionPreservation */);
     615    ASSERT(index == indexComputedByVisiblePosition);
     616#endif
     617    return index;
    580618}
    581619
  • trunk/Source/WebCore/html/HTMLTextFormControlElement.h

    r163721 r164180  
    125125    virtual bool childShouldCreateRenderer(const Node&) const override;
    126126
     127    unsigned indexForPosition(const Position&) const;
     128
    127129    // Returns true if user-editable value is empty. Used to check placeholder visibility.
    128130    virtual bool isEmptyValue() const = 0;
Note: See TracChangeset for help on using the changeset viewer.