Changeset 90662 in webkit


Ignore:
Timestamp:
Jul 8, 2011 1:30:58 PM (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):
(WebCore::HTMLTextFormControlElement::setSelectionRange): Merged with the function of the same name in
RenderTextControl.
(WebCore::HTMLTextFormControlElement::selectionStart): Ditto.
(WebCore::HTMLTextFormControlElement::selectionEnd): Ditto.
(WebCore::setContainerAndOffsetForRange): Moved from RenderTextControl.cpp
(WebCore::HTMLTextFormControlElement::selection): Merged with the function of the same name in RenderTextControl.
(WebCore::HTMLTextFormControlElement::selectionChanged): Calls selectionStart and selectionEnd.

  • html/HTMLFormControlElement.h:

(WebCore::HTMLTextFormControlElement::restoreCachedSelection): Moved from HTMLFormControlElement.cpp now that
all functions are self-contained in HTMLTextFormControlElement.

  • 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

    r90661 r90662  
     12011-07-07  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):
     20        (WebCore::HTMLTextFormControlElement::setSelectionRange): Merged with the function of the same name in
     21        RenderTextControl.
     22        (WebCore::HTMLTextFormControlElement::selectionStart): Ditto.
     23        (WebCore::HTMLTextFormControlElement::selectionEnd): Ditto.
     24        (WebCore::setContainerAndOffsetForRange): Moved from RenderTextControl.cpp
     25        (WebCore::HTMLTextFormControlElement::selection): Merged with the function of the same name in RenderTextControl.
     26        (WebCore::HTMLTextFormControlElement::selectionChanged): Calls selectionStart and selectionEnd.
     27        * html/HTMLFormControlElement.h:
     28        (WebCore::HTMLTextFormControlElement::restoreCachedSelection): Moved from HTMLFormControlElement.cpp now that
     29        all functions are self-contained in HTMLTextFormControlElement.
     30        * html/HTMLInputElement.cpp:
     31        (WebCore::HTMLInputElement::setValue): Calls setSelectionRange.
     32        * rendering/RenderTextControl.cpp:
     33        (WebCore::RenderTextControl::textFormControlElement): Added.
     34        * rendering/RenderTextControl.h:
     35
    1362011-07-08  Mike Reed  <reed@google.com>
    237
  • trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp

    r90186 r90662  
    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

    r90591 r90662  
    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
     707    VisiblePosition startPosition = control->visiblePositionForIndex(start);
     708    VisiblePosition endPosition;
     709    if (start == end)
     710        endPosition = startPosition;
     711    else
     712        endPosition = control->visiblePositionForIndex(end);
     713
     714    // startPosition and endPosition can be null position for example when
     715    // "-webkit-user-select: none" style attribute is specified.
     716    if (startPosition.isNotNull() && endPosition.isNotNull()) {
     717        ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this
     718            && endPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this);
     719    }
     720
     721    VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
     722    if (Frame* frame = document()->frame())
     723        frame->selection()->setSelection(newSelection);
    677724}
    678725
     
    683730    if (document()->focusedNode() != this && hasCachedSelectionStart())
    684731        return m_cachedSelectionStart;
    685     if (!renderer())
    686         return 0;
    687     return toRenderTextControl(renderer())->selectionStart();
     732
     733    Frame* frame = document()->frame();
     734    if (!renderer() || !frame)
     735        return 0;
     736
     737    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     738    // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
     739    // from frame->selection->start() can blow us from underneath. Also, function ordering is
     740    // usually dependent on the compiler.
     741    return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->start());
    688742}
    689743
     
    694748    if (document()->focusedNode() != this && hasCachedSelectionEnd())
    695749        return m_cachedSelectionEnd;
    696     if (!renderer())
    697         return 0;
    698     return toRenderTextControl(renderer())->selectionEnd();
     750
     751    Frame* frame = document()->frame();
     752    if (!renderer() || !frame)
     753        return 0;
     754
     755    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     756    // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
     757    // from frame->selection->start() can blow us from underneath. Also, function ordering is
     758    // usually dependent on the compiler.
     759    return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->end());
     760}
     761
     762static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
     763{
     764    if (node->isTextNode()) {
     765        containerNode = node;
     766        offsetInContainer = offset;
     767    } else {
     768        containerNode = node->parentNode();
     769        offsetInContainer = node->nodeIndex() + offset;
     770    }
    699771}
    700772
     
    703775    if (!renderer() || !isTextFormControl() || !hasCachedSelectionStart() || !hasCachedSelectionEnd())
    704776        return 0;
    705     return toRenderTextControl(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
    706 }
    707 
    708 void HTMLTextFormControlElement::restoreCachedSelection()
    709 {
    710     WebCore::setSelectionRange(this, m_cachedSelectionStart, m_cachedSelectionEnd);
     777   
     778    int start = m_cachedSelectionStart;
     779    int end = m_cachedSelectionEnd;
     780
     781    ASSERT(start <= end);
     782    HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
     783    if (!innerText)
     784        return 0;
     785
     786    if (!innerText->firstChild())
     787        return Range::create(document(), innerText, 0, innerText, 0);
     788
     789    int offset = 0;
     790    Node* startNode = 0;
     791    Node* endNode = 0;
     792    for (Node* node = innerText->firstChild(); node; node = node->traverseNextNode(innerText)) {
     793        ASSERT(!node->firstChild());
     794        ASSERT(node->isTextNode() || node->hasTagName(brTag));
     795        int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
     796
     797        if (offset <= start && start <= offset + length)
     798            setContainerAndOffsetForRange(node, start - offset, startNode, start);
     799
     800        if (offset <= end && end <= offset + length) {
     801            setContainerAndOffsetForRange(node, end - offset, endNode, end);
     802            break;
     803        }
     804
     805        offset += length;
     806    }
     807
     808    if (!startNode || !endNode)
     809        return 0;
     810
     811    return Range::create(document(), startNode, start, endNode, end);
    711812}
    712813
     
    716817        return;
    717818
    718     RenderTextControl* renderTextControl = toRenderTextControl(renderer());
    719     cacheSelection(renderTextControl->selectionStart(), renderTextControl->selectionEnd());
     819    cacheSelection(selectionStart(), selectionEnd());
    720820
    721821    if (Frame* frame = document()->frame()) {
  • trunk/Source/WebCore/html/HTMLFormControlElement.h

    r90591 r90662  
    208208    void setSelectionRange(int start, int end);
    209209    PassRefPtr<Range> selection() const;
     210    String selectedText() const;
    210211
    211212    virtual void dispatchFormControlChangeEvent();
     
    231232    void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; }
    232233
    233     void restoreCachedSelection();
     234    void restoreCachedSelection() { setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd); }
    234235    bool hasCachedSelectionStart() const { return m_cachedSelectionStart >= 0; }
    235236    bool hasCachedSelectionEnd() const { return m_cachedSelectionEnd >= 0; }
  • trunk/Source/WebCore/html/HTMLInputElement.cpp

    r90591 r90662  
    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

    r90600 r90662  
    2828#include "EventNames.h"
    2929#include "Frame.h"
    30 #include "FrameSelection.h"
    3130#include "HTMLBRElement.h"
    3231#include "HTMLFormControlElement.h"
     
    8382}
    8483
     84HTMLTextFormControlElement* RenderTextControl::textFormControlElement()
     85{
     86    return static_cast<HTMLTextFormControlElement*>(node());
     87}
     88
    8589void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    8690{
     
    174178}
    175179
    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 
    243180bool RenderTextControl::isSelectableElement(HTMLElement* innerText, Node* node)
    244181{
     
    255192    return shadowAncestor && (shadowAncestor->hasTagName(textareaTag)
    256193        || (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);
    303194}
    304195
  • trunk/Source/WebCore/rendering/RenderTextControl.h

    r90591 r90662  
    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;
    10097    friend void setSelectionRange(Node*, int start, int end);
    10198    static bool isSelectableElement(HTMLElement*, Node*);
     
    109106    bool m_lastChangeWasUserEdit;
    110107};
    111 
    112 void setSelectionRange(Node*, int start, int end);
    113108
    114109inline RenderTextControl* toRenderTextControl(RenderObject* object)
  • trunk/Source/WebKit/qt/Api/qwebpage.cpp

    r89744 r90662  
    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

    r90403 r90662  
     12011-07-08  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-05  Rafael Brandao  <rafael.lobo@openbossa.org>
    214
Note: See TracChangeset for help on using the changeset viewer.