Move setInnerTextValue from RenderTextControl to HTMLTextFormControlElement
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 Aug 2011 05:51:19 +0000 (05:51 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 30 Aug 2011 05:51:19 +0000 (05:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=67152

Reviewed by Darin Adler.

Moved setInnerTextValue from RenderTextControl to HTMLTextFormControlElement.

Also moved m_lastChangeWasUserEdit from RenderTextControl to HTMLTextFormControlElement
and related inline functions from RenderTextControl to HTMLTextFormControlElement.
Because m_lastChangeWasUserEdit is no longer reset when RenderTextControl is recreated,
added explicit calls to setLastChangeWasNotUserEdit in setValue functions of HTMLInputElement
and HTMLTextAreaElement.

This patch also fixes the bug that lastChangeWasUserEdit() incorrectly returns false
when input or textarea don't have renderer (e.g. invisible).

Unfortunately, there is no way to test this behavioral change from layout tests.

* WebCore.exp.in: Exports lastChangeWasUserEdit in HTMLTextFormControlElement instead of
that of HTMLInputElement and HTMLTextAreaElement.
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setValue): Explicitly calls setLastChangeWasNotUserEdit.
* html/HTMLInputElement.h:
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::setValueCommon): Ditto.
* html/HTMLTextAreaElement.h:
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::HTMLTextFormControlElement):
(WebCore::HTMLTextFormControlElement::subtreeHasChanged): Sets m_lastChangeWasUserEdit true
as it used to do via respondToChangeByUser.
(WebCore::HTMLTextFormControlElement::lastChangeWasUserEdit): Moved from HTMLInputElement
and HTMLTextAreaElement.
(WebCore::HTMLTextFormControlElement::setInnerTextValue): Moved from RenderTextControl.
* html/HTMLTextFormControlElement.h:
(WebCore::HTMLTextFormControlElement::setLastChangeWasNotUserEdit): Added.
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::RenderTextControl): No longer initializes m_lastChangeWasUserEdit.
* rendering/RenderTextControl.h:
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::updateFromElement): Calls setInnerTextValue.
* rendering/RenderTextControlMultiLine.cpp:
(WebCore::RenderTextControlMultiLine::updateFromElement): Ditto.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@94047 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLInputElement.h
Source/WebCore/html/HTMLTextAreaElement.cpp
Source/WebCore/html/HTMLTextAreaElement.h
Source/WebCore/html/HTMLTextFormControlElement.cpp
Source/WebCore/html/HTMLTextFormControlElement.h
Source/WebCore/rendering/RenderTextControl.cpp
Source/WebCore/rendering/RenderTextControl.h
Source/WebCore/rendering/RenderTextControlMultiLine.cpp
Source/WebCore/rendering/RenderTextControlSingleLine.cpp

index b86d41b..8c447ce 100644 (file)
@@ -1,3 +1,48 @@
+2011-08-29  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Move setInnerTextValue from RenderTextControl to HTMLTextFormControlElement
+        https://bugs.webkit.org/show_bug.cgi?id=67152
+
+        Reviewed by Darin Adler.
+
+        Moved setInnerTextValue from RenderTextControl to HTMLTextFormControlElement.
+
+        Also moved m_lastChangeWasUserEdit from RenderTextControl to HTMLTextFormControlElement
+        and related inline functions from RenderTextControl to HTMLTextFormControlElement.
+        Because m_lastChangeWasUserEdit is no longer reset when RenderTextControl is recreated,
+        added explicit calls to setLastChangeWasNotUserEdit in setValue functions of HTMLInputElement
+        and HTMLTextAreaElement.
+
+        This patch also fixes the bug that lastChangeWasUserEdit() incorrectly returns false
+        when input or textarea don't have renderer (e.g. invisible).
+
+        Unfortunately, there is no way to test this behavioral change from layout tests.
+
+        * WebCore.exp.in: Exports lastChangeWasUserEdit in HTMLTextFormControlElement instead of
+        that of HTMLInputElement and HTMLTextAreaElement.
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setValue): Explicitly calls setLastChangeWasNotUserEdit.
+        * html/HTMLInputElement.h:
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::setValueCommon): Ditto.
+        * html/HTMLTextAreaElement.h:
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::HTMLTextFormControlElement):
+        (WebCore::HTMLTextFormControlElement::subtreeHasChanged): Sets m_lastChangeWasUserEdit true
+        as it used to do via respondToChangeByUser.
+        (WebCore::HTMLTextFormControlElement::lastChangeWasUserEdit): Moved from HTMLInputElement
+        and HTMLTextAreaElement.
+        (WebCore::HTMLTextFormControlElement::setInnerTextValue): Moved from RenderTextControl.
+        * html/HTMLTextFormControlElement.h:
+        (WebCore::HTMLTextFormControlElement::setLastChangeWasNotUserEdit): Added.
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::RenderTextControl): No longer initializes m_lastChangeWasUserEdit.
+        * rendering/RenderTextControl.h:
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::updateFromElement): Calls setInnerTextValue.
+        * rendering/RenderTextControlMultiLine.cpp:
+        (WebCore::RenderTextControlMultiLine::updateFromElement): Ditto.
+
 2011-08-25  Kent Tamura  <tkent@chromium.org>
 
         REGRESSION(r88115): Disabling a file upload control causes an endless busyloop.
index 4a9fe48..45ddc0d 100644 (file)
@@ -1182,7 +1182,6 @@ __ZNK7WebCore16FontFallbackList10fontDataAtEPKNS_4FontEj
 __ZNK7WebCore16HTMLInputElement11isTextFieldEv
 __ZNK7WebCore16HTMLInputElement15isPasswordFieldEv
 __ZNK7WebCore16HTMLInputElement18shouldAutocompleteEv
-__ZNK7WebCore16HTMLInputElement21lastChangeWasUserEditEv
 __ZNK7WebCore16IconDatabaseBase12databasePathEv
 __ZNK7WebCore16ResourceResponse13nsURLResponseEv
 __ZNK7WebCore16VisibleSelection17isContentEditableEv
@@ -1192,7 +1191,6 @@ __ZNK7WebCore16VisibleSelection23isContentRichlyEditableEv
 __ZNK7WebCore16VisibleSelection5isAllENS_27EditingBoundaryCrossingRuleE
 __ZNK7WebCore17ResourceErrorBase8lazyInitEv
 __ZNK7WebCore19AnimationController24numberOfActiveAnimationsEPNS_8DocumentE
-__ZNK7WebCore19HTMLTextAreaElement21lastChangeWasUserEditEv
 __ZNK7WebCore19ResourceRequestBase10httpMethodEv
 __ZNK7WebCore19ResourceRequestBase15httpHeaderFieldEPKc
 __ZNK7WebCore19ResourceRequestBase3urlEv
@@ -1217,6 +1215,7 @@ __ZNK7WebCore21UserContentURLPattern7matchesERKNS_4KURLE
 __ZNK7WebCore23AuthenticationChallenge20authenticationClientEv
 __ZNK7WebCore23FrameLoaderStateMachine15firstLayoutDoneEv
 __ZNK7WebCore23FrameLoaderStateMachine23committingFirstRealLoadEv
+__ZNK7WebCore26HTMLTextFormControlElement21lastChangeWasUserEditEv
 __ZNK7WebCore26NetscapePlugInStreamLoader6isDoneEv
 __ZNK7WebCore27AuthenticationChallengeBase15failureResponseEv
 __ZNK7WebCore27AuthenticationChallengeBase15protectionSpaceEv
index f4acd7c..f7e4b5c 100644 (file)
@@ -206,17 +206,6 @@ void HTMLInputElement::updateCheckedRadioButtons()
     }
 }
 
-bool HTMLInputElement::lastChangeWasUserEdit() const
-{
-    if (!isTextField())
-        return false;
-    
-    if (!renderer())
-        return false;
-
-    return toRenderTextControl(renderer())->lastChangeWasUserEdit();
-}
-
 bool HTMLInputElement::isValidValue(const String& value) const
 {
     if (!m_inputType->canSetStringValue()) {
@@ -1068,6 +1057,7 @@ void HTMLInputElement::setValue(const String& value, bool sendChangeEvent)
     String sanitizedValue = sanitizeValue(value);
     bool valueChanged = sanitizedValue != this->value();
 
+    setLastChangeWasNotUserEdit();
     setFormControlValueMatchesRenderer(false);
     if (m_inputType->storesValueSeparateFromAttribute()) {
         if (files())
index dfdb62b..37f84eb 100644 (file)
@@ -228,8 +228,6 @@ public:
     bool isConformToInputMask(const String&) const;
 #endif
 
-    bool lastChangeWasUserEdit() const;
-
     static const int maximumLength;
 
 protected:
index 984f57f..07da99a 100644 (file)
@@ -333,6 +333,7 @@ void HTMLTextAreaElement::setValueCommon(const String& newValue)
         return;
 
     m_value = normalizedValue;
+    setLastChangeWasNotUserEdit();
     updatePlaceholderVisibility(false);
     setNeedsStyleRecalc();
     setFormControlValueMatchesRenderer(true);
@@ -433,13 +434,6 @@ void HTMLTextAreaElement::setRows(int rows)
     setAttribute(rowsAttr, String::number(rows));
 }
 
-bool HTMLTextAreaElement::lastChangeWasUserEdit() const
-{
-    if (!renderer())
-        return false;
-    return toRenderTextControl(renderer())->lastChangeWasUserEdit();
-}
-
 bool HTMLTextAreaElement::shouldUseInputMethod()
 {
     return true;
index 2b3f6eb..4fdf152 100644 (file)
@@ -58,8 +58,6 @@ public:
     void setCols(int);
     void setRows(int);
 
-    bool lastChangeWasUserEdit() const;
-
 private:
     HTMLTextAreaElement(const QualifiedName&, Document*, HTMLFormElement*);
 
index 5089991..6b3167f 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "HTMLTextFormControlElement.h"
 
+#include "AXObjectCache.h"
 #include "Attribute.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
@@ -32,6 +33,7 @@
 #include "Event.h"
 #include "EventNames.h"
 #include "Frame.h"
+#include "HTMLBRElement.h"
 #include "HTMLFormElement.h"
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
@@ -50,6 +52,7 @@ using namespace std;
 
 HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* form)
     : HTMLFormControlElementWithState(tagName, doc, form)
+    , m_lastChangeWasUserEdit(false)
     , m_cachedSelectionStart(-1)
     , m_cachedSelectionEnd(-1)
     , m_cachedSelectionDirection(SelectionHasNoDirection)
@@ -102,7 +105,7 @@ void HTMLTextFormControlElement::forwardEvent(Event* event)
 
 void HTMLTextFormControlElement::subtreeHasChanged()
 {
-    toRenderTextControl(renderer())->respondToChangeByUser();
+    m_lastChangeWasUserEdit = true;
 }
 
 String HTMLTextFormControlElement::strippedPlaceholder() const
@@ -441,11 +444,45 @@ void HTMLTextFormControlElement::notifyFormStateChanged()
     Frame* frame = document()->frame();
     if (!frame)
         return;
-    
+
     if (Page* page = frame->page())
         page->chrome()->client()->formStateDidChange(this);
 }
 
+bool HTMLTextFormControlElement::lastChangeWasUserEdit() const
+{
+    if (!isTextFormControl())
+        return false;
+    return m_lastChangeWasUserEdit;
+}
+
+void HTMLTextFormControlElement::setInnerTextValue(const String& value)
+{
+    if (!renderer() || !isTextFormControl())
+        return;
+
+    RenderTextControl* textControl = toRenderTextControl(renderer());
+    bool textIsChanged = value != textControl->text();
+    if (textIsChanged || !innerTextElement()->hasChildNodes()) {
+        if (textIsChanged && document() && AXObjectCache::accessibilityEnabled())
+            document()->axObjectCache()->postNotification(textControl, AXObjectCache::AXValueChanged, false);
+
+        ExceptionCode ec = 0;
+        innerTextElement()->setInnerText(value, ec);
+        ASSERT(!ec);
+
+        if (value.endsWith("\n") || value.endsWith("\r")) {
+            innerTextElement()->appendChild(HTMLBRElement::create(document()), ec);
+            ASSERT(!ec);
+        }
+
+        // We set m_lastChangeWasUserEdit to false since this change was not explicitly made by the user (say, via typing on the keyboard), see <rdar://problem/5359921>.
+        m_lastChangeWasUserEdit = false;
+    }
+
+    setFormControlValueMatchesRenderer(true);
+}
+
 HTMLTextFormControlElement* enclosingTextFormControl(const Position& position)
 {
     ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor
index 900c0d8..a339bcb 100644 (file)
@@ -75,6 +75,8 @@ public:
 
     void selectionChanged(bool userTriggered);
     void notifyFormStateChanged();
+    bool lastChangeWasUserEdit() const;
+    void setInnerTextValue(const String&);
 
 protected:
     HTMLTextFormControlElement(const QualifiedName&, Document*, HTMLFormElement*);
@@ -97,6 +99,7 @@ protected:
     virtual void defaultEventHandler(Event*);
     virtual void subtreeHasChanged();
 
+    void setLastChangeWasNotUserEdit() { m_lastChangeWasUserEdit = false; }
 private:
     int computeSelectionStart() const;
     int computeSelectionEnd() const;
@@ -119,6 +122,7 @@ private:
     RenderTextControl* textRendererAfterUpdateLayout();
 
     String m_textAsOfLastFormControlChangeEvent;
+    bool m_lastChangeWasUserEdit;
     
     int m_cachedSelectionStart;
     int m_cachedSelectionEnd;
index 75c475f..f21b5e2 100644 (file)
@@ -22,7 +22,6 @@
 #include "config.h"
 #include "RenderTextControl.h"
 
-#include "AXObjectCache.h"
 #include "Editor.h"
 #include "Frame.h"
 #include "HTMLBRElement.h"
@@ -68,7 +67,6 @@ static Color disabledTextColor(const Color& textColor, const Color& backgroundCo
 
 RenderTextControl::RenderTextControl(Node* node)
     : RenderBlock(node)
-    , m_lastChangeWasUserEdit(false)
 {
     ASSERT(toTextFormControl(node));
 }
@@ -151,29 +149,6 @@ void RenderTextControl::updateFromElement()
         updateUserModifyProperty(node(), innerText->renderer()->style());
 }
 
-void RenderTextControl::setInnerTextValue(const String& value)
-{
-    bool textIsChanged = value != text();
-    if (textIsChanged || !innerTextElement()->hasChildNodes()) {
-        if (textIsChanged && document() && AXObjectCache::accessibilityEnabled())
-            document()->axObjectCache()->postNotification(this, AXObjectCache::AXValueChanged, false);
-
-        ExceptionCode ec = 0;
-        innerTextElement()->setInnerText(value, ec);
-        ASSERT(!ec);
-
-        if (value.endsWith("\n") || value.endsWith("\r")) {
-            innerTextElement()->appendChild(HTMLBRElement::create(document()), ec);
-            ASSERT(!ec);
-        }
-
-        // We set m_lastChangeWasUserEdit to false since this change was not explicitly made by the user (say, via typing on the keyboard), see <rdar://problem/5359921>.
-        m_lastChangeWasUserEdit = false;
-    }
-
-    textFormControlElement()->setFormControlValueMatchesRenderer(true);
-}
-
 VisiblePosition RenderTextControl::visiblePositionForIndex(int index) const
 {
     if (index <= 0)
index 8b21c6f..250518a 100644 (file)
@@ -35,8 +35,6 @@ public:
     HTMLTextFormControlElement* textFormControlElement() const;
     virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
 
-    bool lastChangeWasUserEdit() const { return m_lastChangeWasUserEdit; }
-    void respondToChangeByUser() { m_lastChangeWasUserEdit = true; }
     String text();
     String textWithHardLineBreaks();
 
@@ -50,7 +48,6 @@ protected:
 
     int scrollbarThickness() const;
     void adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const;
-    void setInnerTextValue(const String&);
 
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
 
@@ -88,8 +85,6 @@ private:
     virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
 
     static bool isSelectableElement(HTMLElement*, Node*);
-    
-    bool m_lastChangeWasUserEdit;
 };
 
 inline RenderTextControl* toRenderTextControl(RenderObject* object)
index c1d40a6..1b8e846 100644 (file)
@@ -84,7 +84,7 @@ void RenderTextControlMultiLine::updateFromElement()
 {
     RenderTextControl::updateFromElement();
 
-    setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value());
+    textFormControlElement()->setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value());
 }
 
 PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
index b258379..537a17d 100644 (file)
@@ -477,14 +477,14 @@ void RenderTextControlSingleLine::updateFromElement()
         updateCancelButtonVisibility();
 
     if (!inputElement()->suggestedValue().isNull())
-        setInnerTextValue(inputElement()->suggestedValue());
+        textFormControlElement()->setInnerTextValue(inputElement()->suggestedValue());
     else {
         if (node()->hasTagName(inputTag)) {
             // For HTMLInputElement, update the renderer value if the formControlValueMatchesRenderer()
             // flag is false. It protects an unacceptable renderer value from
             // being overwritten with the DOM value.
             if (!inputElement()->formControlValueMatchesRenderer())
-                setInnerTextValue(inputElement()->visibleValue());
+                textFormControlElement()->setInnerTextValue(inputElement()->visibleValue());
         }
     }