2 * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "core/html/shadow/TextControlInnerElements.h"
30 #include "core/HTMLNames.h"
31 #include "core/dom/Document.h"
32 #include "core/dom/NodeRenderStyle.h"
33 #include "core/events/MouseEvent.h"
34 #include "core/events/TextEvent.h"
35 #include "core/events/TextEventInputType.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/html/HTMLInputElement.h"
38 #include "core/html/shadow/ShadowElementNames.h"
39 #include "core/page/EventHandler.h"
40 #include "core/rendering/RenderTextControlSingleLine.h"
41 #include "core/rendering/RenderView.h"
42 #include "platform/UserGestureIndicator.h"
46 using namespace HTMLNames;
48 TextControlInnerContainer::TextControlInnerContainer(Document& document)
49 : HTMLDivElement(document)
53 PassRefPtrWillBeRawPtr<TextControlInnerContainer> TextControlInnerContainer::create(Document& document)
55 RefPtrWillBeRawPtr<TextControlInnerContainer> element = adoptRefWillBeNoop(new TextControlInnerContainer(document));
56 element->setAttribute(idAttr, ShadowElementNames::textFieldContainer());
57 return element.release();
60 RenderObject* TextControlInnerContainer::createRenderer(RenderStyle*)
62 return new RenderTextControlInnerContainer(this);
65 // ---------------------------
67 EditingViewPortElement::EditingViewPortElement(Document& document)
68 : HTMLDivElement(document)
70 setHasCustomStyleCallbacks();
73 PassRefPtrWillBeRawPtr<EditingViewPortElement> EditingViewPortElement::create(Document& document)
75 RefPtrWillBeRawPtr<EditingViewPortElement> element = adoptRefWillBeNoop(new EditingViewPortElement(document));
76 element->setAttribute(idAttr, ShadowElementNames::editingViewPort());
77 return element.release();
80 PassRefPtr<RenderStyle> EditingViewPortElement::customStyleForRenderer()
82 // FXIME: Move these styles to html.css.
84 RefPtr<RenderStyle> style = RenderStyle::create();
85 style->inheritFrom(shadowHost()->renderStyle());
87 style->setFlexGrow(1);
88 style->setDisplay(BLOCK);
89 style->setDirection(LTR);
91 // We don't want the shadow dom to be editable, so we set this block to
92 // read-only in case the input itself is editable.
93 style->setUserModify(READ_ONLY);
96 return style.release();
99 // ---------------------------
101 inline TextControlInnerEditorElement::TextControlInnerEditorElement(Document& document)
102 : HTMLDivElement(document)
104 setHasCustomStyleCallbacks();
107 PassRefPtrWillBeRawPtr<TextControlInnerEditorElement> TextControlInnerEditorElement::create(Document& document)
109 RefPtrWillBeRawPtr<TextControlInnerEditorElement> element = adoptRefWillBeNoop(new TextControlInnerEditorElement(document));
110 element->setAttribute(idAttr, ShadowElementNames::innerEditor());
111 return element.release();
114 void TextControlInnerEditorElement::defaultEventHandler(Event* event)
116 // FIXME: In the future, we should add a way to have default event listeners.
117 // Then we would add one to the text field's inner div, and we wouldn't need this subclass.
118 // Or possibly we could just use a normal event listener.
119 if (event->isBeforeTextInsertedEvent() || event->type() == EventTypeNames::webkitEditableContentChanged) {
120 Element* shadowAncestor = shadowHost();
121 // A TextControlInnerTextElement can have no host if its been detached,
122 // but kept alive by an EditCommand. In this case, an undo/redo can
123 // cause events to be sent to the TextControlInnerTextElement. To
124 // prevent an infinite loop, we must check for this case before sending
125 // the event up the chain.
127 shadowAncestor->defaultEventHandler(event);
129 if (!event->defaultHandled())
130 HTMLDivElement::defaultEventHandler(event);
133 RenderObject* TextControlInnerEditorElement::createRenderer(RenderStyle*)
135 return new RenderTextControlInnerBlock(this);
138 PassRefPtr<RenderStyle> TextControlInnerEditorElement::customStyleForRenderer()
140 RenderObject* parentRenderer = shadowHost()->renderer();
141 if (!parentRenderer || !parentRenderer->isTextControl())
142 return originalStyleForRenderer();
143 RenderTextControl* textControlRenderer = toRenderTextControl(parentRenderer);
144 return textControlRenderer->createInnerEditorStyle(textControlRenderer->style());
147 // ----------------------------
149 inline SearchFieldDecorationElement::SearchFieldDecorationElement(Document& document)
150 : HTMLDivElement(document)
154 PassRefPtrWillBeRawPtr<SearchFieldDecorationElement> SearchFieldDecorationElement::create(Document& document)
156 RefPtrWillBeRawPtr<SearchFieldDecorationElement> element = adoptRefWillBeNoop(new SearchFieldDecorationElement(document));
157 element->setAttribute(idAttr, ShadowElementNames::searchDecoration());
158 return element.release();
161 const AtomicString& SearchFieldDecorationElement::shadowPseudoId() const
163 DEFINE_STATIC_LOCAL(AtomicString, resultsDecorationId, ("-webkit-search-results-decoration", AtomicString::ConstructFromLiteral));
164 DEFINE_STATIC_LOCAL(AtomicString, decorationId, ("-webkit-search-decoration", AtomicString::ConstructFromLiteral));
165 Element* host = shadowHost();
167 return resultsDecorationId;
168 if (isHTMLInputElement(*host)) {
169 if (toHTMLInputElement(host)->maxResults() < 0)
171 return resultsDecorationId;
173 return resultsDecorationId;
176 void SearchFieldDecorationElement::defaultEventHandler(Event* event)
178 // On mousedown, focus the search field
179 HTMLInputElement* input = toHTMLInputElement(shadowHost());
180 if (input && event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) {
183 event->setDefaultHandled();
186 if (!event->defaultHandled())
187 HTMLDivElement::defaultEventHandler(event);
190 bool SearchFieldDecorationElement::willRespondToMouseClickEvents()
195 // ----------------------------
197 inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document)
198 : HTMLDivElement(document)
203 PassRefPtrWillBeRawPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document)
205 RefPtrWillBeRawPtr<SearchFieldCancelButtonElement> element = adoptRefWillBeNoop(new SearchFieldCancelButtonElement(document));
206 element->setShadowPseudoId(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral));
207 element->setAttribute(idAttr, ShadowElementNames::clearButton());
208 return element.release();
211 void SearchFieldCancelButtonElement::detach(const AttachContext& context)
214 if (LocalFrame* frame = document().frame())
215 frame->eventHandler().setCapturingMouseEventsNode(nullptr);
217 HTMLDivElement::detach(context);
221 void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
223 // If the element is visible, on mouseup, clear the value, and set selection
224 RefPtrWillBeRawPtr<HTMLInputElement> input(toHTMLInputElement(shadowHost()));
225 if (!input || input->isDisabledOrReadOnly()) {
226 if (!event->defaultHandled())
227 HTMLDivElement::defaultEventHandler(event);
232 if (event->type() == EventTypeNames::click && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) {
233 input->setValueForUser("");
235 event->setDefaultHandled();
238 if (!event->defaultHandled())
239 HTMLDivElement::defaultEventHandler(event);
242 bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
244 const HTMLInputElement* input = toHTMLInputElement(shadowHost());
245 if (input && !input->isDisabledOrReadOnly())
248 return HTMLDivElement::willRespondToMouseClickEvents();