https://bugs.webkit.org/show_bug.cgi?id=129035
Reviewed by Andreas Kling.
Source/WebCore:
To eliminate the internal use of -webkit-user-modify, use contenteditable attribute in the inner text elements
instead of manually inspecting disabled-ness and readonly-ness in RenderTextControl.
Unfortunately, we still have to manually set UserModify value in RenderTextControl::adjustInnerTextStyle since
RenderTextControl::styleDidChange creates RenderStyle for its inner text from scratch via createInnerTextStyle.
* html/HTMLFieldSetElement.cpp:
(WebCore::HTMLFieldSetElement::disabledStateChanged): Don't use childrenOfType iterator which asserts that DOM
isn't mutated during the traversal since we now set contenteditable attribute inside disabledStateChanged via
updateFromControlElementsAncestorDisabledStateUnder.
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::parseAttribute): Extracted readOnlyAttributeChanged out of this function so
that HTMLTextFormControl could override it to call updateInnerTextElementEditability.
(WebCore::HTMLFormControlElement::readOnlyAttributeChanged): Ditto.
* html/HTMLFormControlElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::didAddUserAgentShadowRoot): Call updateInnerTextElementEditability after creating
shadow DOM for the current input type.
(WebCore::HTMLInputElement::updateType): Ditto.
(WebCore::HTMLInputElement::parseAttribute): Ditto.
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::didAddUserAgentShadowRoot): Call updateInnerTextElementEditability.
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::disabledStateChanged): Added to update contenteditable attribute since
the editability of the inner text element depends on disabled-ness of the element.
(WebCore::HTMLTextFormControlElement::readOnlyAttributeChanged): Ditto for the readonly-ness of the element.
(WebCore::HTMLTextFormControlElement::updateInnerTextElementEditability): Added.
* html/HTMLTextFormControlElement.h:
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::adjustInnerTextStyle): Use the inner text element's presentationAttributeStyle() to
compute the appropriate EUserModify value instead of hard-coding it here.
* rendering/RenderTextControl.h:
LayoutTests:
Rebaselined tests as the user agent shadow DOM of input and textarea elements now have contenteditable attribute.
* editing/input/paste-text-ending-with-interchange-newline-expected.txt:
* editing/inserting/
5607069-2-expected.txt:
* editing/inserting/
5607069-3-expected.txt:
* editing/pasteboard/copy-image-with-alt-text-expected.txt:
* editing/pasteboard/copy-null-characters-expected.txt:
* editing/pasteboard/nested-blocks-with-text-area-expected.txt:
* editing/pasteboard/nested-blocks-with-text-field-expected.txt:
* editing/selection/dump-as-markup-expected.txt:
* editing/selection/dump-as-markup-form-text-expected.txt:
* fast/forms/suggested-value-after-setvalue-expected.txt:
* fast/forms/suggested-value-expected.txt:
* fast/parser/object-with-textarea-fallback-expected.txt:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164526
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-02-21 Ryosuke Niwa <rniwa@webkit.org>
+
+ Inner text element should not use -webkit-user-modify
+ https://bugs.webkit.org/show_bug.cgi?id=129035
+
+ Reviewed by Andreas Kling.
+
+ Rebaselined tests as the user agent shadow DOM of input and textarea elements now have contenteditable attribute.
+
+ * editing/input/paste-text-ending-with-interchange-newline-expected.txt:
+ * editing/inserting/5607069-2-expected.txt:
+ * editing/inserting/5607069-3-expected.txt:
+ * editing/pasteboard/copy-image-with-alt-text-expected.txt:
+ * editing/pasteboard/copy-null-characters-expected.txt:
+ * editing/pasteboard/nested-blocks-with-text-area-expected.txt:
+ * editing/pasteboard/nested-blocks-with-text-field-expected.txt:
+ * editing/selection/dump-as-markup-expected.txt:
+ * editing/selection/dump-as-markup-form-text-expected.txt:
+ * fast/forms/suggested-value-after-setvalue-expected.txt:
+ * fast/forms/suggested-value-expected.txt:
+ * fast/parser/object-with-textarea-fallback-expected.txt:
+
2014-02-21 Myles C. Maxfield <mmaxfield@apple.com>
After copy and paste, cursor may appear to be above the bottom of content
This tests pasting a text with an interchange new line at the end. WebKit shouldn't insert a new line.
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "abc def"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| <br>
| <input>
| type="text"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "x"
| <br>
| "<#selection-caret>x"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
Dump of markup 1:
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "Here is an emoticon [], some more text [], an empty alt tag [], no alt tag [] and two consecutive images [].
"
Dump of markup 3:
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "Here is an emoticon [:)], some more text [sample text], an empty alt tag [], no alt tag [] and two consecutive images [firstsecond].
"
green"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "Copy paste mebold
Copy paste me
| " "
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| " "
| "
x<#selection-caret>
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "
x<#selection-caret>
"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "
"
| <div>
| this.value="replaced"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "replaced"
| "
"
| "original"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "replaced"
| "
"
| this.value="initial value"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "suggested value"
| "input.value: initial value"
| "internals.suggestedValue(input): suggested value"
| this.value="new value"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "new value"
| "input.value: new value"
| "internals.suggestedValue(input): "
| this.value="initial value"
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "suggested value"
| "input.value: initial value"
| "internals.suggestedValue(input): suggested value"
| this.value=""
| <shadow:root>
| <div>
+| contenteditable="plaintext-only"
| "
"
| "
+2014-02-21 Ryosuke Niwa <rniwa@webkit.org>
+
+ Inner text element should not use -webkit-user-modify
+ https://bugs.webkit.org/show_bug.cgi?id=129035
+
+ Reviewed by Andreas Kling.
+
+ To eliminate the internal use of -webkit-user-modify, use contenteditable attribute in the inner text elements
+ instead of manually inspecting disabled-ness and readonly-ness in RenderTextControl.
+
+ Unfortunately, we still have to manually set UserModify value in RenderTextControl::adjustInnerTextStyle since
+ RenderTextControl::styleDidChange creates RenderStyle for its inner text from scratch via createInnerTextStyle.
+
+ * html/HTMLFieldSetElement.cpp:
+ (WebCore::HTMLFieldSetElement::disabledStateChanged): Don't use childrenOfType iterator which asserts that DOM
+ isn't mutated during the traversal since we now set contenteditable attribute inside disabledStateChanged via
+ updateFromControlElementsAncestorDisabledStateUnder.
+
+ * html/HTMLFormControlElement.cpp:
+ (WebCore::HTMLFormControlElement::parseAttribute): Extracted readOnlyAttributeChanged out of this function so
+ that HTMLTextFormControl could override it to call updateInnerTextElementEditability.
+ (WebCore::HTMLFormControlElement::readOnlyAttributeChanged): Ditto.
+ * html/HTMLFormControlElement.h:
+
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::didAddUserAgentShadowRoot): Call updateInnerTextElementEditability after creating
+ shadow DOM for the current input type.
+ (WebCore::HTMLInputElement::updateType): Ditto.
+ (WebCore::HTMLInputElement::parseAttribute): Ditto.
+
+ * html/HTMLTextAreaElement.cpp:
+ (WebCore::HTMLTextAreaElement::didAddUserAgentShadowRoot): Call updateInnerTextElementEditability.
+
+ * html/HTMLTextFormControlElement.cpp:
+ (WebCore::HTMLTextFormControlElement::disabledStateChanged): Added to update contenteditable attribute since
+ the editability of the inner text element depends on disabled-ness of the element.
+ (WebCore::HTMLTextFormControlElement::readOnlyAttributeChanged): Ditto for the readonly-ness of the element.
+ (WebCore::HTMLTextFormControlElement::updateInnerTextElementEditability): Added.
+ * html/HTMLTextFormControlElement.h:
+
+ * rendering/RenderTextControl.cpp:
+ (WebCore::RenderTextControl::adjustInnerTextStyle): Use the inner text element's presentationAttributeStyle() to
+ compute the appropriate EUserModify value instead of hard-coding it here.
+ * rendering/RenderTextControl.h:
+
2014-02-21 ChangSeok Oh <changseok.oh@collabora.com>
[GTK] Support WEBGL_draw_buffers extension.
bool thisFieldsetIsDisabled = hasAttribute(disabledAttr);
bool hasSeenFirstLegendElement = false;
- for (auto& control : childrenOfType<HTMLElement>(*this)) {
+ for (HTMLElement* control = Traversal<HTMLElement>::firstChild(this); control; control = Traversal<HTMLElement>::nextSibling(control)) {
if (!hasSeenFirstLegendElement && isHTMLLegendElement(control)) {
hasSeenFirstLegendElement = true;
- updateFromControlElementsAncestorDisabledStateUnder(control, false /* isDisabled */);
+ updateFromControlElementsAncestorDisabledStateUnder(*control, false /* isDisabled */);
continue;
}
- updateFromControlElementsAncestorDisabledStateUnder(control, thisFieldsetIsDisabled);
+ updateFromControlElementsAncestorDisabledStateUnder(*control, thisFieldsetIsDisabled);
}
}
} else if (name == readonlyAttr) {
bool wasReadOnly = m_isReadOnly;
m_isReadOnly = !value.isNull();
- if (wasReadOnly != m_isReadOnly) {
- setNeedsWillValidateCheck();
- setNeedsStyleRecalc();
- if (renderer() && renderer()->style().hasAppearance())
- renderer()->theme().stateChanged(renderer(), ReadOnlyState);
- }
+ if (wasReadOnly != m_isReadOnly)
+ readOnlyAttributeChanged();
} else if (name == requiredAttr) {
bool wasRequired = m_isRequired;
m_isRequired = !value.isNull();
renderer()->theme().stateChanged(renderer(), EnabledState);
}
+void HTMLFormControlElement::readOnlyAttributeChanged()
+{
+ setNeedsWillValidateCheck();
+ setNeedsStyleRecalc();
+ if (renderer() && renderer()->style().hasAppearance())
+ renderer()->theme().stateChanged(renderer(), ReadOnlyState);
+}
+
void HTMLFormControlElement::requiredAttributeChanged()
{
setNeedsValidityCheck();
bool disabledByAncestorFieldset() const { return m_disabledByAncestorFieldset; }
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
- virtual void requiredAttributeChanged();
virtual void disabledAttributeChanged();
virtual void disabledStateChanged();
+ virtual void readOnlyAttributeChanged();
+ virtual void requiredAttributeChanged();
virtual void didAttachRenderers() override;
virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
virtual void removedFrom(ContainerNode&) override;
void HTMLInputElement::didAddUserAgentShadowRoot(ShadowRoot*)
{
m_inputType->createShadowSubtree();
+ updateInnerTextElementEditability();
}
HTMLInputElement::~HTMLInputElement()
m_inputType = std::move(newType);
m_inputType->createShadowSubtree();
+ updateInnerTextElementEditability();
#if ENABLE(TOUCH_EVENTS)
bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
else if (name == webkitspeechAttr) {
m_inputType->destroyShadowSubtree();
m_inputType->createShadowSubtree();
+ updateInnerTextElementEditability();
// This renderer and its children have quite different layouts and styles depending on
// whether the speech button is visible or not. So we reset the whole thing and recreate
void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot* root)
{
root->appendChild(TextControlInnerTextElement::create(document()), ASSERT_NO_EXCEPTION);
+ updateInnerTextElementEditability();
}
const AtomicString& HTMLTextAreaElement::formControlType() const
HTMLFormControlElementWithState::parseAttribute(name, value);
}
+void HTMLTextFormControlElement::disabledStateChanged()
+{
+ HTMLFormControlElementWithState::disabledStateChanged();
+ updateInnerTextElementEditability();
+}
+
+void HTMLTextFormControlElement::readOnlyAttributeChanged()
+{
+ HTMLFormControlElementWithState::disabledAttributeChanged();
+ updateInnerTextElementEditability();
+}
+
+void HTMLTextFormControlElement::updateInnerTextElementEditability()
+{
+ if (TextControlInnerTextElement* innerText = innerTextElement())
+ innerText->setAttribute(contenteditableAttr, isDisabledOrReadOnly() ? "false" : "plaintext-only");
+}
+
bool HTMLTextFormControlElement::lastChangeWasUserEdit() const
{
if (!isTextFormControl())
virtual void parseAttribute(const QualifiedName&, const AtomicString&) override;
+ virtual void disabledStateChanged() override;
+ virtual void readOnlyAttributeChanged() override;
+ void updateInnerTextElementEditability();
+
void cacheSelection(int start, int end, TextFieldSelectionDirection direction)
{
m_cachedSelectionStart = start;
#include "config.h"
#include "RenderTextControl.h"
+#include "CSSPrimitiveValueMappings.h"
#include "HTMLTextFormControlElement.h"
#include "HitTestResult.h"
#include "RenderText.h"
#include "RenderTheme.h"
#include "ScrollbarTheme.h"
#include "StyleInheritedData.h"
+#include "StyleProperties.h"
#include "TextControlInnerElements.h"
#include "VisiblePosition.h"
#include <wtf/unicode/CharacterNames.h>
textFormControlElement().updatePlaceholderVisibility(false);
}
-static inline bool updateUserModifyProperty(const HTMLTextFormControlElement& element, RenderStyle* style)
-{
- bool isDisabled = element.isDisabledFormControl();
- bool isReadOnlyControl = element.isReadOnly();
-
- style->setUserModify((isReadOnlyControl || isDisabled) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
- return isDisabled;
-}
-
void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const
{
// The inner block, if present, always has its direction set to LTR,
textBlockStyle->setDirection(style().direction());
textBlockStyle->setUnicodeBidi(style().unicodeBidi());
- bool disabled = updateUserModifyProperty(textFormControlElement(), textBlockStyle);
- if (disabled)
+ HTMLTextFormControlElement& control = textFormControlElement();
+ if (HTMLElement* innerText = control.innerTextElement()) {
+ if (const StyleProperties* properties = innerText->presentationAttributeStyle()) {
+ RefPtr<CSSValue> value = properties->getPropertyCSSValue(CSSPropertyWebkitUserModify);
+ if (value && value->isPrimitiveValue())
+ textBlockStyle->setUserModify(toCSSPrimitiveValue(*value));
+ }
+ }
+
+ if (control.isDisabledFormControl())
textBlockStyle->setColor(theme().disabledTextColor(textBlockStyle->visitedDependentColor(CSSPropertyColor), startStyle->visitedDependentColor(CSSPropertyBackgroundColor)));
#if PLATFORM(IOS)
if (textBlockStyle->textSecurity() != TSNONE && !textBlockStyle->isLeftToRightDirection()) {
return unitWidth;
}
-void RenderTextControl::updateFromElement()
-{
- TextControlInnerTextElement* innerText = innerTextElement();
- if (innerText && innerText->renderer())
- updateUserModifyProperty(textFormControlElement(), &innerText->renderer()->style());
-}
-
int RenderTextControl::scrollbarThickness() const
{
// FIXME: We should get the size of the scrollbar from the RenderTheme instead.
virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const = 0;
virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
- virtual void updateFromElement() override;
virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override;
virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) override;