Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / shadow / TextControlInnerElements.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 #include "config.h"
28 #include "core/html/shadow/TextControlInnerElements.h"
29
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"
43
44 namespace blink {
45
46 using namespace HTMLNames;
47
48 TextControlInnerContainer::TextControlInnerContainer(Document& document)
49     : HTMLDivElement(document)
50 {
51 }
52
53 PassRefPtrWillBeRawPtr<TextControlInnerContainer> TextControlInnerContainer::create(Document& document)
54 {
55     RefPtrWillBeRawPtr<TextControlInnerContainer> element = adoptRefWillBeNoop(new TextControlInnerContainer(document));
56     element->setAttribute(idAttr, ShadowElementNames::textFieldContainer());
57     return element.release();
58 }
59
60 RenderObject* TextControlInnerContainer::createRenderer(RenderStyle*)
61 {
62     return new RenderTextControlInnerContainer(this);
63 }
64
65 // ---------------------------
66
67 EditingViewPortElement::EditingViewPortElement(Document& document)
68     : HTMLDivElement(document)
69 {
70     setHasCustomStyleCallbacks();
71 }
72
73 PassRefPtrWillBeRawPtr<EditingViewPortElement> EditingViewPortElement::create(Document& document)
74 {
75     RefPtrWillBeRawPtr<EditingViewPortElement> element = adoptRefWillBeNoop(new EditingViewPortElement(document));
76     element->setAttribute(idAttr, ShadowElementNames::editingViewPort());
77     return element.release();
78 }
79
80 PassRefPtr<RenderStyle> EditingViewPortElement::customStyleForRenderer()
81 {
82     // FXIME: Move these styles to html.css.
83
84     RefPtr<RenderStyle> style = RenderStyle::create();
85     style->inheritFrom(shadowHost()->renderStyle());
86
87     style->setFlexGrow(1);
88     style->setDisplay(BLOCK);
89     style->setDirection(LTR);
90
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);
94     style->setUnique();
95
96     return style.release();
97 }
98
99 // ---------------------------
100
101 inline TextControlInnerEditorElement::TextControlInnerEditorElement(Document& document)
102     : HTMLDivElement(document)
103 {
104     setHasCustomStyleCallbacks();
105 }
106
107 PassRefPtrWillBeRawPtr<TextControlInnerEditorElement> TextControlInnerEditorElement::create(Document& document)
108 {
109     RefPtrWillBeRawPtr<TextControlInnerEditorElement> element = adoptRefWillBeNoop(new TextControlInnerEditorElement(document));
110     element->setAttribute(idAttr, ShadowElementNames::innerEditor());
111     return element.release();
112 }
113
114 void TextControlInnerEditorElement::defaultEventHandler(Event* event)
115 {
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.
126         if (shadowAncestor)
127             shadowAncestor->defaultEventHandler(event);
128     }
129     if (!event->defaultHandled())
130         HTMLDivElement::defaultEventHandler(event);
131 }
132
133 RenderObject* TextControlInnerEditorElement::createRenderer(RenderStyle*)
134 {
135     return new RenderTextControlInnerBlock(this);
136 }
137
138 PassRefPtr<RenderStyle> TextControlInnerEditorElement::customStyleForRenderer()
139 {
140     RenderObject* parentRenderer = shadowHost()->renderer();
141     if (!parentRenderer || !parentRenderer->isTextControl())
142         return originalStyleForRenderer();
143     RenderTextControl* textControlRenderer = toRenderTextControl(parentRenderer);
144     return textControlRenderer->createInnerEditorStyle(textControlRenderer->style());
145 }
146
147 // ----------------------------
148
149 inline SearchFieldDecorationElement::SearchFieldDecorationElement(Document& document)
150     : HTMLDivElement(document)
151 {
152 }
153
154 PassRefPtrWillBeRawPtr<SearchFieldDecorationElement> SearchFieldDecorationElement::create(Document& document)
155 {
156     RefPtrWillBeRawPtr<SearchFieldDecorationElement> element = adoptRefWillBeNoop(new SearchFieldDecorationElement(document));
157     element->setAttribute(idAttr, ShadowElementNames::searchDecoration());
158     return element.release();
159 }
160
161 const AtomicString& SearchFieldDecorationElement::shadowPseudoId() const
162 {
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();
166     if (!host)
167         return resultsDecorationId;
168     if (isHTMLInputElement(*host)) {
169         if (toHTMLInputElement(host)->maxResults() < 0)
170             return decorationId;
171         return resultsDecorationId;
172     }
173     return resultsDecorationId;
174 }
175
176 void SearchFieldDecorationElement::defaultEventHandler(Event* event)
177 {
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) {
181         input->focus();
182         input->select();
183         event->setDefaultHandled();
184     }
185
186     if (!event->defaultHandled())
187         HTMLDivElement::defaultEventHandler(event);
188 }
189
190 bool SearchFieldDecorationElement::willRespondToMouseClickEvents()
191 {
192     return true;
193 }
194
195 // ----------------------------
196
197 inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document)
198     : HTMLDivElement(document)
199     , m_capturing(false)
200 {
201 }
202
203 PassRefPtrWillBeRawPtr<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document)
204 {
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();
209 }
210
211 void SearchFieldCancelButtonElement::detach(const AttachContext& context)
212 {
213     if (m_capturing) {
214         if (LocalFrame* frame = document().frame())
215             frame->eventHandler().setCapturingMouseEventsNode(nullptr);
216     }
217     HTMLDivElement::detach(context);
218 }
219
220
221 void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
222 {
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);
228         return;
229     }
230
231
232     if (event->type() == EventTypeNames::click && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) {
233         input->setValueForUser("");
234         input->onSearch();
235         event->setDefaultHandled();
236     }
237
238     if (!event->defaultHandled())
239         HTMLDivElement::defaultEventHandler(event);
240 }
241
242 bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
243 {
244     const HTMLInputElement* input = toHTMLInputElement(shadowHost());
245     if (input && !input->isDisabledOrReadOnly())
246         return true;
247
248     return HTMLDivElement::willRespondToMouseClickEvents();
249 }
250
251 }