Diff
Modified: trunk/Source/WebCore/ChangeLog (90762 => 90763)
--- trunk/Source/WebCore/ChangeLog 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/ChangeLog 2011-07-11 17:55:26 UTC (rev 90763)
@@ -1,3 +1,39 @@
+2011-07-11 Ryosuke Niwa <rn...@webkit.org>
+
+ Move selection related code from RenderTextControl to HTMLTextFormControlElement
+ https://bugs.webkit.org/show_bug.cgi?id=64133
+
+ Reviewed by Dimitri Glazkov.
+
+ 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:
+
2011-07-11 Andreas Kling <kl...@webkit.org>
Reviewed by Oliver Hunt.
Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (90762 => 90763)
--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2011-07-11 17:55:26 UTC (rev 90763)
@@ -1994,8 +1994,8 @@
return String(); // need to return something distinct from empty string
if (isNativeTextControl()) {
- RenderTextControl* textControl = toRenderTextControl(m_renderer);
- return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
+ HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
+ return textControl->selectedText();
}
if (ariaRoleAttribute() == UnknownRole)
@@ -2028,7 +2028,7 @@
AccessibilityRole ariaRole = ariaRoleAttribute();
if (isNativeTextControl() && ariaRole == UnknownRole) {
- RenderTextControl* textControl = toRenderTextControl(m_renderer);
+ HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
}
@@ -2041,7 +2041,8 @@
void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range)
{
if (isNativeTextControl()) {
- setSelectionRange(m_renderer->node(), range.start, range.start + range.length);
+ HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
+ textControl->setSelectionRange(range.start, range.start + range.length);
return;
}
Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (90762 => 90763)
--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp 2011-07-11 17:55:26 UTC (rev 90763)
@@ -662,6 +662,16 @@
setSelectionRange(0, numeric_limits<int>::max());
}
+String HTMLTextFormControlElement::selectedText() const
+{
+ // FIXME: We should be able to extract selected contents even if there were no renderer.
+ if (!renderer() || renderer()->isTextControl())
+ return String();
+
+ RenderTextControl* textControl = toRenderTextControl(renderer());
+ return textControl->text().substring(selectionStart(), selectionEnd() - selectionStart());
+}
+
void HTMLTextFormControlElement::dispatchFormControlChangeEvent()
{
if (m_textAsOfLastFormControlChangeEvent != value()) {
@@ -671,9 +681,45 @@
setChangedSinceLastFormControlChangeEvent(false);
}
+static inline bool hasVisibleTextArea(RenderTextControl* textControl)
+{
+ ASSERT(textControl);
+ HTMLElement* innerText = textControl->innerTextElement();
+ return textControl->style()->visibility() == HIDDEN || !innerText || !innerText->renderer() || !innerText->renderBox()->height();
+}
+
void HTMLTextFormControlElement::setSelectionRange(int start, int end)
{
- WebCore::setSelectionRange(this, start, end);
+ document()->updateLayoutIgnorePendingStylesheets();
+
+ if (!renderer() || !renderer()->isTextControl())
+ return;
+
+ end = max(end, 0);
+ start = min(max(start, 0), end);
+
+ RenderTextControl* control = toRenderTextControl(renderer());
+ if (hasVisibleTextArea(control)) {
+ cacheSelection(start, end);
+ return;
+ }
+ VisiblePosition startPosition = control->visiblePositionForIndex(start);
+ VisiblePosition endPosition;
+ if (start == end)
+ endPosition = startPosition;
+ else
+ endPosition = control->visiblePositionForIndex(end);
+
+ // startPosition and endPosition can be null position for example when
+ // "-webkit-user-select: none" style attribute is specified.
+ if (startPosition.isNotNull() && endPosition.isNotNull()) {
+ ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this
+ && endPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == this);
+ }
+ VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
+
+ if (Frame* frame = document()->frame())
+ frame->selection()->setSelection(newSelection);
}
int HTMLTextFormControlElement::selectionStart() const
@@ -682,9 +728,21 @@
return 0;
if (document()->focusedNode() != this && hasCachedSelectionStart())
return m_cachedSelectionStart;
- if (!renderer())
+
+ return computeSelectionStart();
+}
+
+int HTMLTextFormControlElement::computeSelectionStart() const
+{
+ Frame* frame = document()->frame();
+ if (!renderer() || !frame)
return 0;
- return toRenderTextControl(renderer())->selectionStart();
+
+ HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
+ // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
+ // from frame->selection->start() can blow us from underneath. Also, function ordering is
+ // usually dependent on the compiler.
+ return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->start());
}
int HTMLTextFormControlElement::selectionEnd() const
@@ -693,21 +751,77 @@
return 0;
if (document()->focusedNode() != this && hasCachedSelectionEnd())
return m_cachedSelectionEnd;
- if (!renderer())
+ return computeSelectionEnd();
+}
+
+int HTMLTextFormControlElement::computeSelectionEnd() const
+{
+ Frame* frame = document()->frame();
+ if (!renderer() || !frame)
return 0;
- return toRenderTextControl(renderer())->selectionEnd();
+
+ HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
+ // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
+ // from frame->selection->end() can blow us from underneath. Also, function ordering is
+ // usually dependent on the compiler.
+ return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->end());
}
+static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
+{
+ if (node->isTextNode()) {
+ containerNode = node;
+ offsetInContainer = offset;
+ } else {
+ containerNode = node->parentNode();
+ offsetInContainer = node->nodeIndex() + offset;
+ }
+}
+
PassRefPtr<Range> HTMLTextFormControlElement::selection() const
{
if (!renderer() || !isTextFormControl() || !hasCachedSelectionStart() || !hasCachedSelectionEnd())
return 0;
- return toRenderTextControl(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
+
+ int start = m_cachedSelectionStart;
+ int end = m_cachedSelectionEnd;
+
+ ASSERT(start <= end);
+ HTMLElement* innerText = toRenderTextControl(renderer())->innerTextElement();
+ if (!innerText)
+ return 0;
+
+ if (!innerText->firstChild())
+ return Range::create(document(), innerText, 0, innerText, 0);
+
+ int offset = 0;
+ Node* startNode = 0;
+ Node* endNode = 0;
+ for (Node* node = innerText->firstChild(); node; node = node->traverseNextNode(innerText)) {
+ ASSERT(!node->firstChild());
+ ASSERT(node->isTextNode() || node->hasTagName(brTag));
+ int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
+
+ if (offset <= start && start <= offset + length)
+ setContainerAndOffsetForRange(node, start - offset, startNode, start);
+
+ if (offset <= end && end <= offset + length) {
+ setContainerAndOffsetForRange(node, end - offset, endNode, end);
+ break;
+ }
+
+ offset += length;
+ }
+
+ if (!startNode || !endNode)
+ return 0;
+
+ return Range::create(document(), startNode, start, endNode, end);
}
void HTMLTextFormControlElement::restoreCachedSelection()
{
- WebCore::setSelectionRange(this, m_cachedSelectionStart, m_cachedSelectionEnd);
+ setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd);
}
void HTMLTextFormControlElement::selectionChanged(bool userTriggered)
@@ -715,8 +829,8 @@
if (!renderer() || !isTextFormControl())
return;
- RenderTextControl* renderTextControl = toRenderTextControl(renderer());
- cacheSelection(renderTextControl->selectionStart(), renderTextControl->selectionEnd());
+ // selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
+ cacheSelection(computeSelectionStart(), computeSelectionEnd());
if (Frame* frame = document()->frame()) {
if (frame->selection()->isRange() && userTriggered)
Modified: trunk/Source/WebCore/html/HTMLFormControlElement.h (90762 => 90763)
--- trunk/Source/WebCore/html/HTMLFormControlElement.h 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.h 2011-07-11 17:55:26 UTC (rev 90763)
@@ -207,6 +207,7 @@
void select();
void setSelectionRange(int start, int end);
PassRefPtr<Range> selection() const;
+ String selectedText() const;
virtual void dispatchFormControlChangeEvent();
@@ -235,6 +236,9 @@
bool hasCachedSelectionEnd() const { return m_cachedSelectionEnd >= 0; }
private:
+ int computeSelectionStart() const;
+ int computeSelectionEnd() const;
+
virtual void dispatchFocusEvent();
virtual void dispatchBlurEvent();
Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (90762 => 90763)
--- trunk/Source/WebCore/html/HTMLInputElement.cpp 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp 2011-07-11 17:55:26 UTC (rev 90763)
@@ -1016,7 +1016,7 @@
if (isTextField()) {
unsigned max = visibleValue().length();
if (document()->focusedNode() == this)
- WebCore::setSelectionRange(this, max, max);
+ setSelectionRange(max, max);
else
cacheSelection(max, max);
m_suggestedValue = String();
Modified: trunk/Source/WebCore/rendering/RenderTextControl.cpp (90762 => 90763)
--- trunk/Source/WebCore/rendering/RenderTextControl.cpp 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/rendering/RenderTextControl.cpp 2011-07-11 17:55:26 UTC (rev 90763)
@@ -82,6 +82,11 @@
{
}
+HTMLTextFormControlElement* RenderTextControl::textFormControlElement()
+{
+ return static_cast<HTMLTextFormControlElement*>(node());
+}
+
void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -173,73 +178,6 @@
document()->setIgnoreAutofocus(lastChangeWasUserEdit);
}
-int RenderTextControl::selectionStart() const
-{
- Frame* frame = this->frame();
- if (!frame)
- return 0;
-
- HTMLElement* innerText = innerTextElement();
- // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
- // from frame->selection->start() can blow us from underneath. Also, function ordering is
- // usually dependent on the compiler.
- return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->start());
-}
-
-int RenderTextControl::selectionEnd() const
-{
- Frame* frame = this->frame();
- if (!frame)
- return 0;
-
- HTMLElement* innerText = innerTextElement();
- // Do not call innerTextElement() in the function arguments as creating a VisiblePosition
- // from frame->selection->end() can blow us from underneath. Also, function ordering is
- // usually dependent on the compiler.
- return RenderTextControl::indexForVisiblePosition(innerText, frame->selection()->end());
-}
-
-bool RenderTextControl::hasVisibleTextArea() const
-{
- HTMLElement* innerText = innerTextElement();
- return style()->visibility() == HIDDEN || !innerText || !innerText->renderer() || !innerText->renderBox()->height();
-}
-
-void setSelectionRange(Node* node, int start, int end)
-{
- ASSERT(node);
- node->document()->updateLayoutIgnorePendingStylesheets();
-
- if (!node->renderer() || !node->renderer()->isTextControl())
- return;
-
- end = max(end, 0);
- start = min(max(start, 0), end);
-
- RenderTextControl* control = toRenderTextControl(node->renderer());
-
- if (control->hasVisibleTextArea()) {
- static_cast<HTMLTextFormControlElement*>(node)->cacheSelection(start, end);
- return;
- }
- VisiblePosition startPosition = control->visiblePositionForIndex(start);
- VisiblePosition endPosition;
- if (start == end)
- endPosition = startPosition;
- else
- endPosition = control->visiblePositionForIndex(end);
-
- // startPosition and endPosition can be null position for example when
- // "-webkit-user-select: none" style attribute is specified.
- if (startPosition.isNotNull() && endPosition.isNotNull()) {
- ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == node && endPosition.deepEquivalent().deprecatedNode()->shadowAncestorNode() == node);
- }
- VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
-
- if (Frame* frame = node->document()->frame())
- frame->selection()->setSelection(newSelection);
-}
-
bool RenderTextControl::isSelectableElement(HTMLElement* innerText, Node* node)
{
if (!node || !innerText)
@@ -256,52 +194,6 @@
|| (shadowAncestor->hasTagName(inputTag) && static_cast<HTMLInputElement*>(shadowAncestor)->isTextField()));
}
-static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
-{
- if (node->isTextNode()) {
- containerNode = node;
- offsetInContainer = offset;
- } else {
- containerNode = node->parentNode();
- offsetInContainer = node->nodeIndex() + offset;
- }
-}
-
-PassRefPtr<Range> RenderTextControl::selection(int start, int end) const
-{
- ASSERT(start <= end);
- HTMLElement* innerText = innerTextElement();
- if (!innerText)
- return 0;
-
- if (!innerText->firstChild())
- return Range::create(document(), innerText, 0, innerText, 0);
-
- int offset = 0;
- Node* startNode = 0;
- Node* endNode = 0;
- for (Node* node = innerText->firstChild(); node; node = node->traverseNextNode(innerText)) {
- ASSERT(!node->firstChild());
- ASSERT(node->isTextNode() || node->hasTagName(brTag));
- int length = node->isTextNode() ? lastOffsetInNode(node) : 1;
-
- if (offset <= start && start <= offset + length)
- setContainerAndOffsetForRange(node, start - offset, startNode, start);
-
- if (offset <= end && end <= offset + length) {
- setContainerAndOffsetForRange(node, end - offset, endNode, end);
- break;
- }
-
- offset += length;
- }
-
- if (!startNode || !endNode)
- return 0;
-
- return Range::create(document(), startNode, start, endNode, end);
-}
-
VisiblePosition RenderTextControl::visiblePositionForIndex(int index) const
{
if (index <= 0)
Modified: trunk/Source/WebCore/rendering/RenderTextControl.h (90762 => 90763)
--- trunk/Source/WebCore/rendering/RenderTextControl.h 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebCore/rendering/RenderTextControl.h 2011-07-11 17:55:26 UTC (rev 90763)
@@ -26,6 +26,7 @@
namespace WebCore {
+class HTMLTextFormControlElement;
class VisibleSelection;
class TextControlInnerElement;
class TextControlInnerTextElement;
@@ -34,16 +35,13 @@
public:
virtual ~RenderTextControl();
+ HTMLTextFormControlElement* textFormControlElement();
virtual HTMLElement* innerTextElement() const = 0;
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
bool lastChangeWasUserEdit() const { return m_lastChangeWasUserEdit; }
void setLastChangeWasUserEdit(bool lastChangeWasUserEdit);
- int selectionStart() const;
- int selectionEnd() const;
- PassRefPtr<Range> selection(int start, int end) const;
-
virtual void subtreeHasChanged();
String text();
String textWithHardLineBreaks();
@@ -96,8 +94,6 @@
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- bool hasVisibleTextArea() const;
- friend void setSelectionRange(Node*, int start, int end);
static bool isSelectableElement(HTMLElement*, Node*);
virtual int textBlockInsetLeft() const = 0;
@@ -109,8 +105,6 @@
bool m_lastChangeWasUserEdit;
};
-void setSelectionRange(Node*, int start, int end);
-
inline RenderTextControl* toRenderTextControl(RenderObject* object)
{
ASSERT(!object || object->isTextControl());
Modified: trunk/Source/WebKit/qt/Api/qwebpage.cpp (90762 => 90763)
--- trunk/Source/WebKit/qt/Api/qwebpage.cpp 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebKit/qt/Api/qwebpage.cpp 2011-07-11 17:55:26 UTC (rev 90763)
@@ -1111,8 +1111,10 @@
case QInputMethodEvent::Selection: {
hasSelection = true;
// A selection in the inputMethodEvent is always reflected in the visible text
- if (node)
- setSelectionRange(node, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
+ if (node) {
+ if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
+ textControl->setSelectionRange(qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
+ }
if (!ev->preeditString().isEmpty())
editor->setComposition(ev->preeditString(), underlines, qMin(a.start, (a.start + a.length)), qMax(a.start, (a.start + a.length)));
@@ -1132,7 +1134,8 @@
if (node && ev->replacementLength() > 0) {
int cursorPos = frame->selection()->extent().offsetInContainerNode();
int start = cursorPos + ev->replacementStart();
- setSelectionRange(node, start, start + ev->replacementLength());
+ if (HTMLTextFormControlElement* textControl = toTextFormControl(node))
+ textControl->setSelectionRange(start, start + ev->replacementLength());
// Commit regardless of whether commitString is empty, to get rid of selection.
editor->confirmComposition(ev->commitString());
} else if (!ev->commitString().isEmpty()) {
Modified: trunk/Source/WebKit/qt/ChangeLog (90762 => 90763)
--- trunk/Source/WebKit/qt/ChangeLog 2011-07-11 17:51:04 UTC (rev 90762)
+++ trunk/Source/WebKit/qt/ChangeLog 2011-07-11 17:55:26 UTC (rev 90763)
@@ -1,3 +1,15 @@
+2011-07-11 Ryosuke Niwa <rn...@webkit.org>
+
+ Move selection related code from RenderTextControl to HTMLTextFormControlElement
+ https://bugs.webkit.org/show_bug.cgi?id=64133
+
+ Reviewed by Dimitri Glazkov.
+
+ Replaced calls to WebCore::setSelectionRange by calls to HTMLTextFormControlElement::setSelectionRange.
+
+ * Api/qwebpage.cpp:
+ (QWebPagePrivate::inputMethodEvent):
+
2011-07-08 Adam Barth <aba...@webkit.org>
Unreviewed, rolling out r90662.