Changeset 90763 in webkit


Ignore:
Timestamp:
Jul 11, 2011 10:55:26 AM (13 years ago)
Author:
rniwa@webkit.org
Message:

Move selection related code from RenderTextControl to HTMLTextFormControlElement
https://bugs.webkit.org/show_bug.cgi?id=64133

Reviewed by Dimitri Glazkov.

Source/WebCore:

Moved selectionStart, selectionEnd, hasVisibleTextArea, setSelectionRange, setContainerAndOffsetForRange
and selection from RenderTextControl.cpp to HTMLFormControlElement.cpp.

This refactoring removes RenderTextControl's dependency on FrameSelection.

  • accessibility/AccessibilityRenderObject.cpp:

(WebCore::AccessibilityRenderObject::selectedText): Calls HTMLTextFromControl::selectedText.
(WebCore::AccessibilityRenderObject::selectedTextRange): Calls selectionStart and selectionEnd.
(WebCore::AccessibilityRenderObject::setSelectedTextRange): Ditto.

  • html/HTMLFormControlElement.cpp:

(WebCore::HTMLTextFormControlElement::selectedText): Extracted from AccessibilityRenderObject::selectedText.
(WebCore::hasVisibleTextArea): Added.
(WebCore::HTMLTextFormControlElement::setSelectionRange): Merged with the function of the same name in RenderTextControl.
(WebCore::HTMLTextFormControlElement::selectionStart): Calls computeSelectionStart instead of RenderTextControl::selectionStart.
(WebCore::HTMLTextFormControlElement::computeSelectionStart): Moved from RenderTextControl::selectionStart.
(WebCore::HTMLTextFormControlElement::selectionEnd): Calls computeSelectionEnd instead of RenderText::selectionEnd.
(WebCore::HTMLTextFormControlElement::computeSelectionEnd): Moved from RenderTextControl::selectionStart.
(WebCore::setContainerAndOffsetForRange): Moved from RenderTextControl.cpp.
(WebCore::HTMLTextFormControlElement::selection): Merged with the function of the same name in RenderTextControl.
(WebCore::HTMLTextFormControlElement::restoreCachedSelection): Calls computeSelectionStart and computeSelectionEnd instead of
RenderTextControl::selectionStart and RenderTextControl::selectionEnd.
(WebCore::HTMLTextFormControlElement::selectionChanged): Calls selectionStart and selectionEnd.

  • html/HTMLFormControlElement.h:
  • html/HTMLInputElement.cpp:

(WebCore::HTMLInputElement::setValue): Calls setSelectionRange.

  • rendering/RenderTextControl.cpp:

(WebCore::RenderTextControl::textFormControlElement): Added.

  • rendering/RenderTextControl.h:

Source/WebKit/qt:

Replaced calls to WebCore::setSelectionRange by calls to HTMLTextFormControlElement::setSelectionRange.

  • Api/qwebpage.cpp:

(QWebPagePrivate::inputMethodEvent):

Location:
trunk/Source
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r90758 r90763  
     12011-07-11  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Move selection related code from RenderTextControl to HTMLTextFormControlElement
     4        https://bugs.webkit.org/show_bug.cgi?id=64133
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        Moved selectionStart, selectionEnd, hasVisibleTextArea, setSelectionRange, setContainerAndOffsetForRange
     9        and selection from RenderTextControl.cpp to HTMLFormControlElement.cpp.
     10
     11        This refactoring removes RenderTextControl's dependency on FrameSelection.
     12
     13        * accessibility/AccessibilityRenderObject.cpp:
     14        (WebCore::AccessibilityRenderObject::selectedText): Calls HTMLTextFromControl::selectedText.
     15        (WebCore::AccessibilityRenderObject::selectedTextRange): Calls selectionStart and selectionEnd.
     16        (WebCore::AccessibilityRenderObject::setSelectedTextRange): Ditto.
     17        * html/HTMLFormControlElement.cpp:
     18        (WebCore::HTMLTextFormControlElement::selectedText): Extracted from AccessibilityRenderObject::selectedText.
     19        (WebCore::hasVisibleTextArea): Added.
     20        (WebCore::HTMLTextFormControlElement::setSelectionRange): Merged with the function of the same name in RenderTextControl.
     21        (WebCore::HTMLTextFormControlElement::selectionStart): Calls computeSelectionStart instead of RenderTextControl::selectionStart.
     22        (WebCore::HTMLTextFormControlElement::computeSelectionStart): Moved from RenderTextControl::selectionStart.
     23        (WebCore::HTMLTextFormControlElement::selectionEnd): Calls computeSelectionEnd instead of RenderText::selectionEnd.
     24        (WebCore::HTMLTextFormControlElement::computeSelectionEnd): Moved from RenderTextControl::selectionStart.
     25        (WebCore::setContainerAndOffsetForRange): Moved from RenderTextControl.cpp.
     26        (WebCore::HTMLTextFormControlElement::selection): Merged with the function of the same name in RenderTextControl.
     27        (WebCore::HTMLTextFormControlElement::restoreCachedSelection): Calls computeSelectionStart and computeSelectionEnd instead of
     28        RenderTextControl::selectionStart and RenderTextControl::selectionEnd.
     29        (WebCore::HTMLTextFormControlElement::selectionChanged): Calls selectionStart and selectionEnd.
     30        * html/HTMLFormControlElement.h:
     31        * html/HTMLInputElement.cpp:
     32        (WebCore::HTMLInputElement::setValue): Calls setSelectionRange.
     33        * rendering/RenderTextControl.cpp:
     34        (WebCore::RenderTextControl::textFormControlElement): Added.
     35        * rendering/RenderTextControl.h:
     36
    1372011-07-11  Andreas Kling  <kling@webkit.org>
    238
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp

    r90671 r90763  
    19951995   
    19961996    if (isNativeTextControl()) {
    1997         RenderTextControl* textControl = toRenderTextControl(m_renderer);
    1998         return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
     1997        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
     1998        return textControl->selectedText();
    19991999    }
    20002000   
     
    20292029    AccessibilityRole ariaRole = ariaRoleAttribute();
    20302030    if (isNativeTextControl() && ariaRole == UnknownRole) {
    2031         RenderTextControl* textControl = toRenderTextControl(m_renderer);
     2031        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
    20322032        return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
    20332033    }
     
    20422042{
    20432043    if (isNativeTextControl()) {
    2044         setSelectionRange(m_renderer->node(), range.start, range.start + range.length);
     2044        HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
     2045        textControl->setSelectionRange(range.start, range.start + range.length);
    20452046        return;
    20462047    }
  • trunk/Source/WebCore/html/HTMLFormControlElement.cpp

    r90671 r90763  
    663663}
    664664
     665String HTMLTextFormControlElement::selectedText() const
     666{
     667    // FIXME: We should be able to extract selected contents even if there were no renderer.
     668    if (!renderer() || renderer()->isTextControl())
     669        return String();
     670
     671    RenderTextControl* textControl = toRenderTextControl(renderer());
     672    return textControl->text().substring(selectionStart(), selectionEnd() - selectionStart());
     673}
     674
    665675void HTMLTextFormControlElement::dispatchFormControlChangeEvent()
    666676{
     
    672682}
    673683
     684static inline bool hasVisibleTextArea(RenderTextControl* textControl)
     685{
     686    ASSERT(textControl);
     687    HTMLElement* innerText = textControl->innerTextElement();
     688    return textControl->style()->visibility() == HIDDEN || !innerText || !innerText->renderer() || !innerText->renderBox()->height();
     689}
     690
    674691void HTMLTextFormControlElement::setSelectionRange(int start, int end)
    675692{
    676     WebCore::setSelectionRange(this, start, end);
     693    document()->updateLayoutIgnorePendingStylesheets();
     694
     695    if (!renderer() || !renderer()->isTextControl())
     696        return;
     697
     698    end = max(end, 0);
     699    start = min(max(start, 0), end);
     700
     701    RenderTextControl* control = toRenderTextControl(renderer());
     702    if (hasVisibleTextArea(control)) {
     703        cacheSelection(start, end);
     704        return;
     705    }
     706    VisiblePosition startPosition = control->visiblePositionForIndex(start);
     707    VisiblePosition endPosition;
     708    if (start == end)
     709        endPosition = startPosition;
     710    else
     711        endPosition = control->visiblePositionForIndex(end);
     712
     713    // startPosition and endPosition can be null position for example when
     714    // "-webkit-user-select: none" style attribute is specified.
     715    if (startPosition.isNotNull() && endPosition.isNotNull()) {
     716        ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this
     717            && endPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this);
     718    }
     719    VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
     720
     721    if (Frame* frame = document()->frame())
     722        frame->selection()->setSelection(newSelection);
    677723}
    678724
     
    683729    if (document()->focusedNode() != this && hasCachedSelectionStart())
    684730        return m_cachedSelectionStart;
    685     if (!renderer())
    686         return 0;
    687     return toRenderTextControl(renderer())->selectionStart();
     731
     732    return computeSelectionStart();
     733}
     734
     735int HTMLTextFormControlElement::computeSelectionStart() const
     736{
     737    Frame* frame = document()->frame();
     738    if (!renderer() || !frame)
     739        return 0;
     740
     741    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     742    // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
     743    // from frame->selection->start() can blow us from underneath. Also, function ordering is
     744    // usually dependent on the compiler.
     745    return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->start());
    688746}
    689747
     
    694752    if (document()->focusedNode() != this && hasCachedSelectionEnd())
    695753        return m_cachedSelectionEnd;
    696     if (!renderer())
    697         return 0;
    698     return toRenderTextControl(renderer())->selectionEnd();
     754    return computeSelectionEnd();
     755}
     756
     757int HTMLTextFormControlElement::computeSelectionEnd() const
     758{
     759    Frame* frame = document()->frame();
     760    if (!renderer() || !frame)
     761        return 0;
     762
     763    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     764    // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
     765    // from frame->selection->end() can blow us from underneath. Also, function ordering is
     766    // usually dependent on the compiler.
     767    return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->end());
     768}
     769
     770static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
     771{
     772    if (node->isTextNode()) {
     773        containerNode = node;
     774        offsetInContainer = offset;
     775    } else {
     776        containerNode = node->parentNode();
     777        offsetInContainer = node->nodeIndex() + offset;
     778    }
    699779}
    700780
     
    703783    if (!renderer() || !isTextFormControl() || !hasCachedSelectionStart() || !hasCachedSelectionEnd())
    704784        return 0;
    705     return toRenderTextControl(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
     785
     786    int start = m_cachedSelectionStart;
     787    int end = m_cachedSelectionEnd;
     788
     789    ASSERT(start <= end);
     790    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     791    if (!innerText)
     792        return 0;
     793
     794    if (!innerText->firstChild())
     795        return Range::create(document(), innerText, 0, innerText, 0);
     796
     797    int offset = 0;
     798    Node* startNode = 0;
     799    Node* endNode = 0;
     800    for (Node* node = innerText->firstChild(); node; node = node->traverseNextNode(innerText)) {
     801        ASSERT(!node->firstChild());
     802        ASSERT(node->isTextNode() || node->hasTagName(brTag));
     803        int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
     804
     805        if (offset <= start && start <= offset + length)
     806            setContainerAndOffsetForRange(node, start - offset, startNode, start);
     807
     808        if (offset <= end && end <= offset + length) {
     809            setContainerAndOffsetForRange(node, end - offset, endNode, end);
     810            break;
     811        }
     812
     813        offset += length;
     814    }
     815
     816    if (!startNode || !endNode)
     817        return 0;
     818
     819    return Range::create(document(), startNode, start, endNode, end);
    706820}
    707821
    708822void HTMLTextFormControlElement::restoreCachedSelection()
    709823{
    710     WebCore::setSelectionRange(this, m_cachedSelectionStart, m_cachedSelectionEnd);
     824    setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd);
    711825}
    712826
     
    716830        return;
    717831
    718     RenderTextControl* renderTextControl = toRenderTextControl(renderer());
    719     cacheSelection(renderTextControl->selectionStart(), renderTextControl->selectionEnd());
     832    // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
     833    cacheSelection(computeSelectionStart(), computeSelectionEnd());
    720834
    721835    if (Frame* frame = document()->frame()) {
  • trunk/Source/WebCore/html/HTMLFormControlElement.h

    r90671 r90763  
    208208    void setSelectionRange(int start, int end);
    209209    PassRefPtr<Range> selection() const;
     210    String selectedText() const;
    210211
    211212    virtual void dispatchFormControlChangeEvent();
     
    236237
    237238private:
     239    int computeSelectionStart() const;
     240    int computeSelectionEnd() const;
     241
    238242    virtual void dispatchFocusEvent();
    239243    virtual void dispatchBlurEvent();
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r90671 r90763  
    10171017        unsigned max = visibleValue().length();
    10181018        if (document()->focusedNode() == this)
    1019             WebCore::setSelectionRange(this, max, max);
     1019            setSelectionRange(max, max);
    10201020        else
    10211021            cacheSelection(max, max);
  • trunk/Source/WebCore/rendering/RenderTextControl.cpp

    r90671 r90763  
    8383}
    8484
     85HTMLTextFormControlElement* RenderTextControl::textFormControlElement()
     86{
     87    return static_cast<HTMLTextFormControlElement*>(node());
     88}
     89
    8590void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    8691{
     
    174179}
    175180
    176 int RenderTextControl::selectionStart() const
    177 {
    178     Frame* frame = this->frame();
    179     if (!frame)
    180         return 0;
    181    
    182     HTMLElement* innerText = innerTextElement();
    183     // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
    184     // from frame->selection->start() can blow us from underneath. Also, function ordering is
    185     // usually dependent on the compiler.
    186     return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->start());
    187 }
    188 
    189 int RenderTextControl::selectionEnd() const
    190 {
    191     Frame* frame = this->frame();
    192     if (!frame)
    193         return 0;
    194 
    195     HTMLElement* innerText = innerTextElement();
    196     // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
    197     // from frame->selection->end() can blow us from underneath. Also, function ordering is
    198     // usually dependent on the compiler.
    199     return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->end());
    200 }
    201 
    202 bool RenderTextControl::hasVisibleTextArea() const
    203 {
    204     HTMLElement* innerText = innerTextElement();
    205     return style()->visibility() == HIDDEN || !innerText || !innerText->renderer() || !innerText->renderBox()->height();
    206 }
    207 
    208 void setSelectionRange(Node* node, int start, int end)
    209 {
    210     ASSERT(node);
    211     node->document()->updateLayoutIgnorePendingStylesheets();
    212 
    213     if (!node->renderer() || !node->renderer()->isTextControl())
    214         return;
    215 
    216     end = max(end, 0);
    217     start = min(max(start, 0), end);
    218 
    219     RenderTextControl* control = toRenderTextControl(node->renderer());
    220 
    221     if (control->hasVisibleTextArea()) {
    222         static_cast<HTMLTextFormControlElement*>(node)->cacheSelection(start, end);
    223         return;
    224     }
    225     VisiblePosition startPosition = control->visiblePositionForIndex(start);
    226     VisiblePosition endPosition;
    227     if (start == end)
    228         endPosition = startPosition;
    229     else
    230         endPosition = control->visiblePositionForIndex(end);
    231 
    232     // startPosition and endPosition can be null position for example when
    233     // "-webkit-user-select: none" style attribute is specified.
    234     if (startPosition.isNotNull() && endPosition.isNotNull()) {
    235         ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == node && endPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == node);
    236     }
    237     VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
    238 
    239     if (Frame* frame = node->document()->frame())
    240         frame->selection()->setSelection(newSelection);
    241 }
    242 
    243181bool RenderTextControl::isSelectableElement(HTMLElement* innerText, Node* node)
    244182{
     
    255193    return shadowAncestor && (shadowAncestor->hasTagName(textareaTag)
    256194        || (shadowAncestor->hasTagName(inputTag) && static_cast<HTMLInputElement*>(shadowAncestor)->isTextField()));
    257 }
    258 
    259 static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
    260 {
    261     if (node->isTextNode()) {
    262         containerNode = node;
    263         offsetInContainer = offset;
    264     } else {
    265         containerNode = node->parentNode();
    266         offsetInContainer = node->nodeIndex() + offset;
    267     }
    268 }
    269 
    270 PassRefPtr<Range> RenderTextControl::selection(int start, int end) const
    271 {
    272     ASSERT(start <= end);
    273     HTMLElement* innerText = innerTextElement();
    274     if (!innerText)
    275         return 0;
    276 
    277     if (!innerText->firstChild())
    278         return Range::create(document(), innerText, 0, innerText, 0);
    279 
    280     int offset = 0;
    281     Node* startNode = 0;
    282     Node* endNode = 0;
    283     for (Node* node = innerText->firstChild(); node; node = node->traverseNextNode(innerText)) {
    284         ASSERT(!node->firstChild());
    285         ASSERT(node->isTextNode() || node->hasTagName(brTag));
    286         int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
    287    
    288         if (offset <= start && start <= offset + length)
    289             setContainerAndOffsetForRange(node, start - offset, startNode, start);
    290 
    291         if (offset <= end && end <= offset + length) {
    292             setContainerAndOffsetForRange(node, end - offset, endNode, end);
    293             break;
    294         }
    295 
    296         offset += length;
    297     }
    298    
    299     if (!startNode || !endNode)
    300         return 0;
    301 
    302     return Range::create(document(), startNode, start, endNode, end);
    303195}
    304196
  • trunk/Source/WebCore/rendering/RenderTextControl.h

    r90671 r90763  
    2727namespace WebCore {
    2828
     29class HTMLTextFormControlElement;
    2930class VisibleSelection;
    3031class TextControlInnerElement;
     
    3536    virtual ~RenderTextControl();
    3637
     38    HTMLTextFormControlElement* textFormControlElement();
    3739    virtual HTMLElement* innerTextElement() const = 0;
    3840    virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
     
    4042    bool lastChangeWasUserEdit() const { return m_lastChangeWasUserEdit; }
    4143    void setLastChangeWasUserEdit(bool lastChangeWasUserEdit);
    42 
    43     int selectionStart() const;
    44     int selectionEnd() const;
    45     PassRefPtr<Range> selection(int start, int end) const;
    4644
    4745    virtual void subtreeHasChanged();
     
    9795    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
    9896
    99     bool hasVisibleTextArea() const;
    100     friend void setSelectionRange(Node*, int start, int end);
    10197    static bool isSelectableElement(HTMLElement*, Node*);
    10298   
     
    109105    bool m_lastChangeWasUserEdit;
    110106};
    111 
    112 void setSelectionRange(Node*, int start, int end);
    113107
    114108inline RenderTextControl* toRenderTextControl(RenderObject* object)
  • trunk/Source/WebKit/qt/Api/qwebpage.cpp

    r90671 r90763  
    11121112            hasSelection = true;
    11131113            // A selection in the inputMethodEvent is always reflected in the visible text
    1114             if (node)
    1115                 setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
     1114            if (node) {
     1115                if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
     1116                    textControl->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
     1117            }
    11161118
    11171119            if (!ev->preeditString().isEmpty())
     
    11331135        int cursorPos = frame->selection()->extent().offsetInContainerNode();
    11341136        int start = cursorPos + ev->replacementStart();
    1135         setSelectionRange(node, start, start + ev->replacementLength());
     1137        if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
     1138            textControl->setSelectionRange(start, start + ev->replacementLength());
    11361139        // Commit regardless of whether commitString is empty, to get rid of selection.
    11371140        editor->confirmComposition(ev->commitString());
  • trunk/Source/WebKit/qt/ChangeLog

    r90671 r90763  
     12011-07-11  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Move selection related code from RenderTextControl to HTMLTextFormControlElement
     4        https://bugs.webkit.org/show_bug.cgi?id=64133
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        Replaced calls to WebCore::setSelectionRange by calls to HTMLTextFormControlElement::setSelectionRange.
     9
     10        * Api/qwebpage.cpp:
     11        (QWebPagePrivate::inputMethodEvent):
     12
    1132011-07-08  Adam Barth  <abarth@webkit.org>
    214
Note: See TracChangeset for help on using the changeset viewer.