Title: [197637] trunk/Source/WebCore
Revision
197637
Author
[email protected]
Date
2016-03-06 02:17:52 -0800 (Sun, 06 Mar 2016)

Log Message

RenderTextControlSingleLine shouldn't mutate placeholder element inline style
https://bugs.webkit.org/show_bug.cgi?id=155086

Reviewed by Andreas Kling.

Text field placeholder element is currently managed by changing its inline style
from the host renderer based on the host style and state. Rendering poking
into DOM is wrong.

* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setRangeText):
(WebCore::HTMLInputElement::shouldTruncateText):

    Add a helper.

(WebCore::HTMLInputElement::createInnerTextStyle):
* html/HTMLInputElement.h:
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::HTMLTextAreaElement):
(WebCore::HTMLTextAreaElement::placeholderElement):
(WebCore::HTMLTextAreaElement::matchesReadWritePseudoClass):
(WebCore::HTMLTextAreaElement::updatePlaceholderText):

    Use the new shadow element.

* html/HTMLTextAreaElement.h:
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::updatePlaceholderVisibility):

    No more poking to inline style.

(WebCore::HTMLTextFormControlElement::setSelectionStart):
* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::updatePlaceholderText):

    Use the new shadow element.

* html/shadow/TextControlInnerElements.cpp:
(WebCore::TextControlPlaceholderElement::TextControlPlaceholderElement):

    Add a subclass for the placeholder element instead of just using div.

(WebCore::TextControlPlaceholderElement::customStyleForRenderer):

    Compute style base on the host state and style.

(WebCore::SearchFieldResultsButtonElement::SearchFieldResultsButtonElement):
* html/shadow/TextControlInnerElements.h:
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::styleDidChange):

    No more setInlineStyleProperty.
    This now needs to trigger layout like it does with other inner elements.

(WebCore::RenderTextControlSingleLine::computeControlLogicalHeight):
(WebCore::RenderTextControlSingleLine::autoscroll):
(WebCore::RenderTextControlSingleLine::textShouldBeTruncated): Deleted.
* rendering/RenderTextControlSingleLine.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (197636 => 197637)


--- trunk/Source/WebCore/ChangeLog	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/ChangeLog	2016-03-06 10:17:52 UTC (rev 197637)
@@ -1,3 +1,64 @@
+2016-03-06  Antti Koivisto  <[email protected]>
+
+        RenderTextControlSingleLine shouldn't mutate placeholder element inline style
+        https://bugs.webkit.org/show_bug.cgi?id=155086
+
+        Reviewed by Andreas Kling.
+
+        Text field placeholder element is currently managed by changing its inline style
+        from the host renderer based on the host style and state. Rendering poking
+        into DOM is wrong.
+
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setRangeText):
+        (WebCore::HTMLInputElement::shouldTruncateText):
+
+            Add a helper.
+
+        (WebCore::HTMLInputElement::createInnerTextStyle):
+        * html/HTMLInputElement.h:
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::HTMLTextAreaElement):
+        (WebCore::HTMLTextAreaElement::placeholderElement):
+        (WebCore::HTMLTextAreaElement::matchesReadWritePseudoClass):
+        (WebCore::HTMLTextAreaElement::updatePlaceholderText):
+
+            Use the new shadow element.
+
+        * html/HTMLTextAreaElement.h:
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::updatePlaceholderVisibility):
+
+            No more poking to inline style.
+
+        (WebCore::HTMLTextFormControlElement::setSelectionStart):
+        * html/TextFieldInputType.cpp:
+        (WebCore::TextFieldInputType::updatePlaceholderText):
+
+            Use the new shadow element.
+
+        * html/shadow/TextControlInnerElements.cpp:
+        (WebCore::TextControlPlaceholderElement::TextControlPlaceholderElement):
+
+            Add a subclass for the placeholder element instead of just using div.
+
+        (WebCore::TextControlPlaceholderElement::customStyleForRenderer):
+
+            Compute style base on the host state and style.
+
+        (WebCore::SearchFieldResultsButtonElement::SearchFieldResultsButtonElement):
+        * html/shadow/TextControlInnerElements.h:
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::styleDidChange):
+
+            No more setInlineStyleProperty.
+            This now needs to trigger layout like it does with other inner elements.
+
+        (WebCore::RenderTextControlSingleLine::computeControlLogicalHeight):
+        (WebCore::RenderTextControlSingleLine::autoscroll):
+        (WebCore::RenderTextControlSingleLine::textShouldBeTruncated): Deleted.
+        * rendering/RenderTextControlSingleLine.h:
+
 2016-03-05  Ryosuke Niwa  <[email protected]>
 
         Add the support for upgrading custom elements in cloneNode

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (197636 => 197637)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -1859,6 +1859,13 @@
     HTMLTextFormControlElement::setRangeText(replacement, start, end, selectionMode, ec);
 }
 
+bool HTMLInputElement::shouldTruncateText(const RenderStyle& style) const
+{
+    if (!isTextField())
+        return false;
+    return document().focusedElement() != this && style.textOverflow() == TextOverflowEllipsis;
+}
+
 Ref<RenderStyle> HTMLInputElement::createInnerTextStyle(const RenderStyle& style) const
 {
     auto textBlockStyle = RenderStyle::create();
@@ -1869,10 +1876,8 @@
     textBlockStyle.get().setOverflowWrap(NormalOverflowWrap);
     textBlockStyle.get().setOverflowX(OHIDDEN);
     textBlockStyle.get().setOverflowY(OHIDDEN);
+    textBlockStyle.get().setTextOverflow(shouldTruncateText(style) ? TextOverflowEllipsis : TextOverflowClip);
 
-    bool textShouldBeTruncated = document().focusedElement() != this && style.textOverflow() == TextOverflowEllipsis;
-    textBlockStyle.get().setTextOverflow(textShouldBeTruncated ? TextOverflowEllipsis : TextOverflowClip);
-
     // Do not allow line-height to be smaller than our default.
     if (textBlockStyle.get().fontMetrics().lineSpacing() > style.computedLineHeight())
         textBlockStyle.get().setLineHeight(RenderStyle::initialLineHeight());

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (197636 => 197637)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2016-03-06 10:17:52 UTC (rev 197637)
@@ -321,6 +321,8 @@
 
     void capsLockStateMayHaveChanged();
 
+    bool shouldTruncateText(const RenderStyle&) const;
+
 protected:
     HTMLInputElement(const QualifiedName&, Document&, HTMLFormElement*, bool createdByParser);
 

Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (197636 => 197637)


--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -92,10 +92,6 @@
     : HTMLTextFormControlElement(tagName, document, form)
     , m_rows(defaultRows)
     , m_cols(defaultCols)
-    , m_wrap(SoftWrap)
-    , m_placeholder(0)
-    , m_isDirty(false)
-    , m_wasModifiedByUser(false)
 {
     ASSERT(hasTagName(textareaTag));
     setFormControlValueMatchesRenderer(true);
@@ -497,7 +493,7 @@
 
 HTMLElement* HTMLTextAreaElement::placeholderElement() const
 {
-    return m_placeholder;
+    return m_placeholder.get();
 }
 
 bool HTMLTextAreaElement::matchesReadWritePseudoClass() const
@@ -516,10 +512,7 @@
         return;
     }
     if (!m_placeholder) {
-        RefPtr<HTMLDivElement> placeholder = HTMLDivElement::create(document());
-        m_placeholder = placeholder.get();
-        m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
-        m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
+        m_placeholder = TextControlPlaceholderElement::create(document());
         userAgentShadowRoot()->insertBefore(*m_placeholder, innerTextElement()->nextSibling());
     }
     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);

Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.h (197636 => 197637)


--- trunk/Source/WebCore/html/HTMLTextAreaElement.h	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.h	2016-03-06 10:17:52 UTC (rev 197637)
@@ -124,11 +124,11 @@
     unsigned m_rows;
     unsigned m_cols;
     int m_maxLength { -1 };
-    WrapMethod m_wrap;
-    HTMLElement* m_placeholder;
+    WrapMethod m_wrap { SoftWrap };
+    RefPtr<HTMLElement> m_placeholder;
     mutable String m_value;
-    mutable bool m_isDirty;
-    mutable bool m_wasModifiedByUser;
+    mutable bool m_isDirty { false };
+    mutable bool m_wasModifiedByUser { false };
 };
 
 } //namespace

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp (197636 => 197637)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -164,9 +164,6 @@
         return;
 
     setNeedsStyleRecalc();
-
-    if (HTMLElement* placeholder = placeholderElement())
-        placeholder->setInlineStyleProperty(CSSPropertyDisplay, m_isPlaceholderVisible ? CSSValueBlock : CSSValueNone, true);
 }
 
 void HTMLTextFormControlElement::setSelectionStart(int start)

Modified: trunk/Source/WebCore/html/TextFieldInputType.cpp (197636 => 197637)


--- trunk/Source/WebCore/html/TextFieldInputType.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/TextFieldInputType.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -494,11 +494,8 @@
         return;
     }
     if (!m_placeholder) {
-        m_placeholder = HTMLDivElement::create(element().document());
-        m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
-        m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, element().isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
-        element().userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement(), ASSERT_NO_EXCEPTION);
-        
+        m_placeholder = TextControlPlaceholderElement::create(element().document());
+        element().userAgentShadowRoot()->insertBefore(*m_placeholder, m_container ? m_container.get() : innerTextElement(), ASSERT_NO_EXCEPTION);        
     }
     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);
 }

Modified: trunk/Source/WebCore/html/shadow/TextControlInnerElements.cpp (197636 => 197637)


--- trunk/Source/WebCore/html/shadow/TextControlInnerElements.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/shadow/TextControlInnerElements.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -39,6 +39,7 @@
 #include "RenderTextControl.h"
 #include "RenderView.h"
 #include "ScriptController.h"
+#include "ShadowRoot.h"
 #include "TextEvent.h"
 #include "TextEventInputType.h"
 #include <wtf/Ref.h>
@@ -139,6 +140,30 @@
 
 // ----------------------------
 
+TextControlPlaceholderElement::TextControlPlaceholderElement(Document& document)
+    : HTMLDivElement(divTag, document)
+{
+    setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
+    setHasCustomStyleResolveCallbacks();
+}
+
+RefPtr<RenderStyle> TextControlPlaceholderElement::customStyleForRenderer(RenderStyle& parentStyle, RenderStyle* shadowHostStyle)
+{
+    auto style = resolveStyle(&parentStyle);
+
+    auto& controlElement = downcast<HTMLTextFormControlElement>(*containingShadowRoot()->host());
+    style->setDisplay(controlElement.isPlaceholderVisible() ? BLOCK : NONE);
+
+    if (is<HTMLInputElement>(controlElement)) {
+        auto& inputElement = downcast<HTMLInputElement>(controlElement);
+        style->setTextOverflow(inputElement.shouldTruncateText(*shadowHostStyle) ? TextOverflowEllipsis : TextOverflowClip);
+    }
+
+    return WTFMove(style);
+}
+
+// ----------------------------
+
 inline SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document& document)
     : HTMLDivElement(divTag, document)
 {

Modified: trunk/Source/WebCore/html/shadow/TextControlInnerElements.h (197636 => 197637)


--- trunk/Source/WebCore/html/shadow/TextControlInnerElements.h	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/html/shadow/TextControlInnerElements.h	2016-03-06 10:17:52 UTC (rev 197637)
@@ -70,6 +70,16 @@
     bool isTextControlInnerTextElement() const override { return true; }
 };
 
+class TextControlPlaceholderElement final : public HTMLDivElement {
+public:
+    static Ref<TextControlPlaceholderElement> create(Document& document) { return adoptRef(*new TextControlPlaceholderElement(document)); }
+
+private:
+    TextControlPlaceholderElement(Document&);
+    
+    RefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle, RenderStyle* shadowHostStyle) override;
+};
+
 class SearchFieldResultsButtonElement final : public HTMLDivElement {
 public:
     static Ref<SearchFieldResultsButtonElement> create(Document&);

Modified: trunk/Source/WebCore/rendering/RenderTextControlSingleLine.cpp (197636 => 197637)


--- trunk/Source/WebCore/rendering/RenderTextControlSingleLine.cpp	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/rendering/RenderTextControlSingleLine.cpp	2016-03-06 10:17:52 UTC (rev 197637)
@@ -245,11 +245,14 @@
         containerRenderer->style().setHeight(Length());
         containerRenderer->style().setWidth(Length());
     }
-    RenderTextControlInnerBlock* innerTextRenderer = innerTextElement()->renderer();
-    if (innerTextRenderer && diff == StyleDifferenceLayout)
-        innerTextRenderer->setNeedsLayout(MarkContainingBlockChain);
-    if (HTMLElement* placeholder = inputElement().placeholderElement())
-        placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
+    if (diff == StyleDifferenceLayout) {
+        if (auto* innerTextRenderer = innerTextElement()->renderer())
+            innerTextRenderer->setNeedsLayout(MarkContainingBlockChain);
+        if (auto* placeholder = inputElement().placeholderElement()) {
+            if (placeholder->renderer())
+                placeholder->renderer()->setNeedsLayout(MarkContainingBlockChain);
+        }
+    }
     setHasOverflowClip(false);
 }
 
@@ -321,11 +324,6 @@
     return lineHeight + nonContentHeight;
 }
 
-bool RenderTextControlSingleLine::textShouldBeTruncated() const
-{
-    return document().focusedElement() != &inputElement() && style().textOverflow() == TextOverflowEllipsis;
-}
-
 void RenderTextControlSingleLine::autoscroll(const IntPoint& position)
 {
     RenderTextControlInnerBlock* renderer = innerTextElement()->renderer();

Modified: trunk/Source/WebCore/rendering/RenderTextControlSingleLine.h (197636 => 197637)


--- trunk/Source/WebCore/rendering/RenderTextControlSingleLine.h	2016-03-06 08:33:29 UTC (rev 197636)
+++ trunk/Source/WebCore/rendering/RenderTextControlSingleLine.h	2016-03-06 10:17:52 UTC (rev 197637)
@@ -73,8 +73,6 @@
     
     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
 
-    bool textShouldBeTruncated() const;
-
     HTMLElement* innerSpinButtonElement() const;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to