- Revision
- 111930
- Author
- [email protected]
- Date
- 2012-03-23 16:41:22 -0700 (Fri, 23 Mar 2012)
Log Message
Add TextFieldDecorator and TextFieldDecorationElement
https://bugs.webkit.org/show_bug.cgi?id=80580
Reviewed by Dimitri Glazkov.
These classes will be used to add a decoration icon to a text field
<input> from outside of WebCore. We have a plan to use them in Chromium
port. So this patch doesn't add TextFieldDecorationElement.{cpp,h} to
non-Chromium build files.
How it works:
When a shadow subtree for a text field is created, we ask ChromeClient
to decorate it. ChromeClient appends a TextFieldDecorationElement to the
existing shadow subtree or another shadow tree. A TextFieldDecorator is
associated to a TextFieldDecorationElement, and it provides decoration
icon images and a click handler.
No new tests. This patch won't make any behavior change for now.
* WebCore.gypi: Add TextFieldDecorationElement.cpp and TextFieldDecorationElement.h
* dom/Element.h:
(WebCore::Element::isTextFieldDecoration):
* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::createShadowSubtree):
Calls ChromeClient::willAddTextFieldDecorationsTo() and addTextFieldDecorationsTo().
* html/shadow/TextFieldDecorationElement.cpp: Added.
(WebCore::TextFieldDecorator::~TextFieldDecorator):
(WebCore::TextFieldDecorationElement::TextFieldDecorationElement):
(WebCore::TextFieldDecorationElement::create):
(WebCore::TextFieldDecorationElement::isTextFieldDecoration):
(WebCore::TextFieldDecorationElement::updateImage):
(WebCore::TextFieldDecorationElement::customStyleForRenderer):
Sets the size to a square of the font-size.
(WebCore::TextFieldDecorationElement::createRenderer):
Always creates a RenderImage.
(WebCore::TextFieldDecorationElement::attach):
Sets an image for appropriate state.
(WebCore::TextFieldDecorationElement::isMouseFocusable):
(WebCore::TextFieldDecorationElement::defaultEventHandler):
Delegate a click event to the corresponding function of TextFieldDecorator.
* html/shadow/TextFieldDecorationElement.h: Added.
(TextFieldDecorator): Added.
(TextFieldDecorationElement): Added.
(WebCore::toTextFieldDecorationElement): Added.
* page/ChromeClient.h:
(WebCore::ChromeClient::willAddTextFieldDecorationsTo): Add an empty implementation.
(WebCore::ChromeClient::addTextFieldDecorationsTo): ditto.
Modified Paths
Added Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (111929 => 111930)
--- trunk/Source/WebCore/ChangeLog 2012-03-23 23:31:49 UTC (rev 111929)
+++ trunk/Source/WebCore/ChangeLog 2012-03-23 23:41:22 UTC (rev 111930)
@@ -1,3 +1,53 @@
+2012-03-23 Kent Tamura <[email protected]>
+
+ Add TextFieldDecorator and TextFieldDecorationElement
+ https://bugs.webkit.org/show_bug.cgi?id=80580
+
+ Reviewed by Dimitri Glazkov.
+
+ These classes will be used to add a decoration icon to a text field
+ <input> from outside of WebCore. We have a plan to use them in Chromium
+ port. So this patch doesn't add TextFieldDecorationElement.{cpp,h} to
+ non-Chromium build files.
+
+ How it works:
+ When a shadow subtree for a text field is created, we ask ChromeClient
+ to decorate it. ChromeClient appends a TextFieldDecorationElement to the
+ existing shadow subtree or another shadow tree. A TextFieldDecorator is
+ associated to a TextFieldDecorationElement, and it provides decoration
+ icon images and a click handler.
+
+ No new tests. This patch won't make any behavior change for now.
+
+ * WebCore.gypi: Add TextFieldDecorationElement.cpp and TextFieldDecorationElement.h
+ * dom/Element.h:
+ (WebCore::Element::isTextFieldDecoration):
+ * html/TextFieldInputType.cpp:
+ (WebCore::TextFieldInputType::createShadowSubtree):
+ Calls ChromeClient::willAddTextFieldDecorationsTo() and addTextFieldDecorationsTo().
+ * html/shadow/TextFieldDecorationElement.cpp: Added.
+ (WebCore::TextFieldDecorator::~TextFieldDecorator):
+ (WebCore::TextFieldDecorationElement::TextFieldDecorationElement):
+ (WebCore::TextFieldDecorationElement::create):
+ (WebCore::TextFieldDecorationElement::isTextFieldDecoration):
+ (WebCore::TextFieldDecorationElement::updateImage):
+ (WebCore::TextFieldDecorationElement::customStyleForRenderer):
+ Sets the size to a square of the font-size.
+ (WebCore::TextFieldDecorationElement::createRenderer):
+ Always creates a RenderImage.
+ (WebCore::TextFieldDecorationElement::attach):
+ Sets an image for appropriate state.
+ (WebCore::TextFieldDecorationElement::isMouseFocusable):
+ (WebCore::TextFieldDecorationElement::defaultEventHandler):
+ Delegate a click event to the corresponding function of TextFieldDecorator.
+ * html/shadow/TextFieldDecorationElement.h: Added.
+ (TextFieldDecorator): Added.
+ (TextFieldDecorationElement): Added.
+ (WebCore::toTextFieldDecorationElement): Added.
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::willAddTextFieldDecorationsTo): Add an empty implementation.
+ (WebCore::ChromeClient::addTextFieldDecorationsTo): ditto.
+
2012-03-23 Adam Klein <[email protected]>
Match DOM4 spec with respect to DocumentFragment insertion
Modified: trunk/Source/WebCore/WebCore.gypi (111929 => 111930)
--- trunk/Source/WebCore/WebCore.gypi 2012-03-23 23:31:49 UTC (rev 111929)
+++ trunk/Source/WebCore/WebCore.gypi 2012-03-23 23:41:22 UTC (rev 111930)
@@ -5684,6 +5684,8 @@
'html/shadow/SliderThumbElement.h',
'html/shadow/TextControlInnerElements.cpp',
'html/shadow/TextControlInnerElements.h',
+ 'html/shadow/TextFieldDecorationElement.cpp',
+ 'html/shadow/TextFieldDecorationElement.h',
'html/track/LoadableTextTrack.cpp',
'html/track/LoadableTextTrack.h',
'html/track/TextTrack.cpp',
Modified: trunk/Source/WebCore/dom/Element.h (111929 => 111930)
--- trunk/Source/WebCore/dom/Element.h 2012-03-23 23:31:49 UTC (rev 111929)
+++ trunk/Source/WebCore/dom/Element.h 2012-03-23 23:41:22 UTC (rev 111930)
@@ -361,6 +361,7 @@
virtual bool isInRange() const { return false; }
virtual bool isOutOfRange() const { return false; }
virtual bool isFrameElementBase() const { return false; }
+ virtual bool isTextFieldDecoration() const { return false; }
virtual bool canContainRangeEndPoint() const { return true; }
Modified: trunk/Source/WebCore/html/TextFieldInputType.cpp (111929 => 111930)
--- trunk/Source/WebCore/html/TextFieldInputType.cpp 2012-03-23 23:31:49 UTC (rev 111929)
+++ trunk/Source/WebCore/html/TextFieldInputType.cpp 2012-03-23 23:41:22 UTC (rev 111930)
@@ -33,6 +33,8 @@
#include "TextFieldInputType.h"
#include "BeforeTextInsertedEvent.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
#include "FormDataList.h"
#include "Frame.h"
#include "HTMLInputElement.h"
@@ -220,8 +222,10 @@
Document* document = element()->document();
RefPtr<RenderTheme> theme = document->page() ? document->page()->theme() : RenderTheme::defaultTheme();
+ ChromeClient* chromeClient = document->page() ? document->page()->chrome()->client() : 0;
bool shouldHaveSpinButton = theme->shouldHaveSpinButton(element());
- bool createsContainer = shouldHaveSpinButton || needsContainer();
+ bool shouldAddDecorations = chromeClient && chromeClient->willAddTextFieldDecorationsTo(element());
+ bool createsContainer = shouldHaveSpinButton || needsContainer() || shouldAddDecorations;
ExceptionCode ec = 0;
m_innerText = TextControlInnerTextElement::create(document);
@@ -251,6 +255,9 @@
m_innerSpinButton = SpinButtonElement::create(document);
m_container->appendChild(m_innerSpinButton, ec);
}
+
+ if (shouldAddDecorations)
+ chromeClient->addTextFieldDecorationsTo(element());
}
HTMLElement* TextFieldInputType::containerElement() const
Added: trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp (0 => 111930)
--- trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp (rev 0)
+++ trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.cpp 2012-03-23 23:41:22 UTC (rev 111930)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TextFieldDecorationElement.h"
+
+#include "Event.h"
+#include "HTMLInputElement.h"
+#include "RenderImage.h"
+
+namespace WebCore {
+
+// TextFieldDecorator ----------------------------------------------------------------
+
+TextFieldDecorator::~TextFieldDecorator()
+{
+}
+
+// TextFieldDecorationElement ----------------------------------------------------------------
+
+TextFieldDecorationElement::TextFieldDecorationElement(Document* document, TextFieldDecorator* decorator)
+ : HTMLDivElement(HTMLNames::divTag, document)
+ , m_textFieldDecorator(decorator)
+{
+ ASSERT(decorator);
+ setHasCustomStyleForRenderer();
+}
+
+PassRefPtr<TextFieldDecorationElement> TextFieldDecorationElement::create(Document* document, TextFieldDecorator* decorator)
+{
+ return adoptRef(new TextFieldDecorationElement(document, decorator));
+}
+
+bool TextFieldDecorationElement::isTextFieldDecoration() const
+{
+ return true;
+}
+
+void TextFieldDecorationElement::updateImage()
+{
+ if (!renderer() || !renderer()->isImage())
+ return;
+ RenderImageResource* resource = toRenderImage(renderer())->imageResource();
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+ CachedImage* image;
+ if (input->disabled())
+ image = m_textFieldDecorator->imageForDisabledState();
+ else if (input->readOnly())
+ image = m_textFieldDecorator->imageForReadonlyState();
+ else
+ image = m_textFieldDecorator->imageForNormalState();
+ ASSERT(image);
+ resource->setCachedImage(image);
+}
+
+PassRefPtr<RenderStyle> TextFieldDecorationElement::customStyleForRenderer()
+{
+ RefPtr<RenderStyle> style = RenderStyle::create();
+ RenderStyle* inputStyle = shadowAncestorNode()->renderStyle();
+ ASSERT(inputStyle);
+ style->setWidth(Length(inputStyle->fontSize(), Fixed));
+ style->setHeight(Length(inputStyle->fontSize(), Fixed));
+ updateImage();
+ return style.release();
+}
+
+RenderObject* TextFieldDecorationElement::createRenderer(RenderArena* arena, RenderStyle*)
+{
+ RenderImage* image = new (arena) RenderImage(this);
+ image->setImageResource(RenderImageResource::create());
+ return image;
+}
+
+void TextFieldDecorationElement::attach()
+{
+ HTMLDivElement::attach();
+ updateImage();
+}
+
+bool TextFieldDecorationElement::isMouseFocusable() const
+{
+ return false;
+}
+
+void TextFieldDecorationElement::defaultEventHandler(Event* event)
+{
+ RefPtr<HTMLInputElement> input(static_cast<HTMLInputElement*>(shadowAncestorNode()));
+ if (input->disabled() || input->readOnly() || !event->isMouseEvent()) {
+ if (!event->defaultHandled())
+ HTMLDivElement::defaultEventHandler(event);
+ return;
+ }
+
+ RefPtr<TextFieldDecorationElement> protector(this);
+ if (event->type() == eventNames().clickEvent) {
+ m_textFieldDecorator->handleClick(input.get());
+ event->setDefaultHandled();
+ }
+
+ if (!event->defaultHandled())
+ HTMLDivElement::defaultEventHandler(event);
+}
+
+} // namespace WebCore
Added: trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.h (0 => 111930)
--- trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.h (rev 0)
+++ trunk/Source/WebCore/html/shadow/TextFieldDecorationElement.h 2012-03-23 23:41:22 UTC (rev 111930)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextFieldDecorationElement_h
+#define TextFieldDecorationElement_h
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class CachedImage;
+class HTMLInputElement;
+
+// A TextFieldDecorator object must live until all of text fields which were
+// decorated by it die.
+class TextFieldDecorator {
+public:
+ // Returns true if this TextFieldDecorator wants to add a
+ // decoration to the specified text field.
+ virtual bool willAddDecorationTo(HTMLInputElement*) = 0;
+
+ // A TextFieldDecorator object should own the CachedImage objects.
+ virtual CachedImage* imageForNormalState() = 0;
+ virtual CachedImage* imageForDisabledState() = 0;
+ virtual CachedImage* imageForReadonlyState() = 0;
+
+ virtual void handleClick(HTMLInputElement*) = 0;
+
+ virtual ~TextFieldDecorator();
+};
+
+// A TextFieldDecorationElement object must be in a shadow tree of an
+// HTMLInputElement.
+class TextFieldDecorationElement : public HTMLDivElement {
+public:
+ static PassRefPtr<TextFieldDecorationElement> create(Document*, TextFieldDecorator*);
+ TextFieldDecorator* textFieldDecorator() { return m_textFieldDecorator; }
+
+private:
+ TextFieldDecorationElement(Document*, TextFieldDecorator*);
+ virtual bool isTextFieldDecoration() const OVERRIDE;
+ virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
+ virtual RenderObject* createRenderer(RenderArena*, RenderStyle*) OVERRIDE;
+ virtual void attach() OVERRIDE;
+ virtual bool isMouseFocusable() const OVERRIDE;
+ virtual void defaultEventHandler(Event*) OVERRIDE;
+
+ void updateImage();
+
+ TextFieldDecorator* m_textFieldDecorator;
+};
+
+inline TextFieldDecorationElement* toTextFieldDecorationElement(Node* node)
+{
+ ASSERT(node);
+ ASSERT(node->isElementNode());
+ ASSERT(static_cast<Element*>(node)->isTextFieldDecoration());
+ return static_cast<TextFieldDecorationElement*>(node);
+}
+
+}
+#endif
Modified: trunk/Source/WebCore/page/ChromeClient.h (111929 => 111930)
--- trunk/Source/WebCore/page/ChromeClient.h 2012-03-23 23:31:49 UTC (rev 111929)
+++ trunk/Source/WebCore/page/ChromeClient.h 2012-03-23 23:41:22 UTC (rev 111930)
@@ -53,6 +53,7 @@
class Frame;
class Geolocation;
class GraphicsLayer;
+ class HTMLInputElement;
class HitTestResult;
class IntRect;
class NavigationAction;
@@ -307,6 +308,13 @@
virtual PagePopup* openPagePopup(PagePopupClient*, const IntRect& originBoundsInRootView) = 0;
virtual void closePagePopup(PagePopup*) = 0;
#endif
+ // This function is called whenever a text field <input> is
+ // created. The implementation should return true if it wants
+ // to do something in addTextFieldDecorationsTo().
+ // The argument is always non-0.
+ virtual bool willAddTextFieldDecorationsTo(HTMLInputElement*) { return false; }
+ // The argument is always non-0.
+ virtual void addTextFieldDecorationsTo(HTMLInputElement*) { }
virtual void postAccessibilityNotification(AccessibilityObject*, AXObjectCache::AXNotification) { }