Purge PassRefPtr in WebCore/html - 3
[WebKit-https.git] / Source / WebCore / html / shadow / TextControlInnerElements.cpp
1 /*
2  * Copyright (C) 2006, 2008, 2010, 2014 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 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 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 "TextControlInnerElements.h"
29
30 #include "Document.h"
31 #include "EventHandler.h"
32 #include "EventNames.h"
33 #include "Frame.h"
34 #include "HTMLInputElement.h"
35 #include "HTMLNames.h"
36 #include "MouseEvent.h"
37 #include "RenderSearchField.h"
38 #include "RenderTextControl.h"
39 #include "RenderView.h"
40 #include "ScriptController.h"
41 #include "TextEvent.h"
42 #include "TextEventInputType.h"
43 #include <wtf/Ref.h>
44
45 namespace WebCore {
46
47 using namespace HTMLNames;
48
49 TextControlInnerContainer::TextControlInnerContainer(Document& document)
50     : HTMLDivElement(divTag, document)
51 {
52 }
53
54 Ref<TextControlInnerContainer> TextControlInnerContainer::create(Document& document)
55 {
56     return adoptRef(*new TextControlInnerContainer(document));
57 }
58     
59 RenderPtr<RenderElement> TextControlInnerContainer::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
60 {
61     return createRenderer<RenderTextControlInnerContainer>(*this, WTF::move(style));
62 }
63
64 TextControlInnerElement::TextControlInnerElement(Document& document)
65     : HTMLDivElement(divTag, document)
66 {
67     setHasCustomStyleResolveCallbacks();
68 }
69
70 Ref<TextControlInnerElement> TextControlInnerElement::create(Document& document)
71 {
72     return adoptRef(*new TextControlInnerElement(document));
73 }
74
75 RefPtr<RenderStyle> TextControlInnerElement::customStyleForRenderer(RenderStyle&)
76 {
77     RenderTextControlSingleLine& parentRenderer = downcast<RenderTextControlSingleLine>(*shadowHost()->renderer());
78     return parentRenderer.createInnerBlockStyle(&parentRenderer.style());
79 }
80
81 // ---------------------------
82
83 inline TextControlInnerTextElement::TextControlInnerTextElement(Document& document)
84     : HTMLDivElement(divTag, document)
85 {
86     setHasCustomStyleResolveCallbacks();
87 }
88
89 Ref<TextControlInnerTextElement> TextControlInnerTextElement::create(Document& document)
90 {
91     return adoptRef(*new TextControlInnerTextElement(document));
92 }
93
94 void TextControlInnerTextElement::defaultEventHandler(Event* event)
95 {
96     // FIXME: In the future, we should add a way to have default event listeners.
97     // Then we would add one to the text field's inner div, and we wouldn't need this subclass.
98     // Or possibly we could just use a normal event listener.
99     if (event->isBeforeTextInsertedEvent() || event->type() == eventNames().webkitEditableContentChangedEvent) {
100         Element* shadowAncestor = shadowHost();
101         // A TextControlInnerTextElement can have no host if its been detached,
102         // but kept alive by an EditCommand. In this case, an undo/redo can
103         // cause events to be sent to the TextControlInnerTextElement. To
104         // prevent an infinite loop, we must check for this case before sending
105         // the event up the chain.
106         if (shadowAncestor)
107             shadowAncestor->defaultEventHandler(event);
108     }
109     if (!event->defaultHandled())
110         HTMLDivElement::defaultEventHandler(event);
111 }
112
113 RenderPtr<RenderElement> TextControlInnerTextElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
114 {
115     return createRenderer<RenderTextControlInnerBlock>(*this, WTF::move(style));
116 }
117
118 RenderTextControlInnerBlock* TextControlInnerTextElement::renderer() const
119 {
120     return downcast<RenderTextControlInnerBlock>(HTMLDivElement::renderer());
121 }
122
123 RefPtr<RenderStyle> TextControlInnerTextElement::customStyleForRenderer(RenderStyle&)
124 {
125     RenderTextControl& parentRenderer = downcast<RenderTextControl>(*shadowHost()->renderer());
126     return parentRenderer.createInnerTextStyle(&parentRenderer.style());
127 }
128
129 // ----------------------------
130
131 inline SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document& document)
132     : HTMLDivElement(divTag, document)
133 {
134 }
135
136 Ref<SearchFieldResultsButtonElement> SearchFieldResultsButtonElement::create(Document& document)
137 {
138     return adoptRef(*new SearchFieldResultsButtonElement(document));
139 }
140
141 void SearchFieldResultsButtonElement::defaultEventHandler(Event* event)
142 {
143     // On mousedown, bring up a menu, if needed
144     HTMLInputElement* input = downcast<HTMLInputElement>(shadowHost());
145     if (input && event->type() == eventNames().mousedownEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton) {
146         input->focus();
147         input->select();
148 #if !PLATFORM(IOS)
149         RenderSearchField& renderer = downcast<RenderSearchField>(*input->renderer());
150         if (renderer.popupIsVisible())
151             renderer.hidePopup();
152         else if (input->maxResults() > 0)
153             renderer.showPopup();
154 #endif
155         event->setDefaultHandled();
156     }
157
158     if (!event->defaultHandled())
159         HTMLDivElement::defaultEventHandler(event);
160 }
161
162 #if !PLATFORM(IOS)
163 bool SearchFieldResultsButtonElement::willRespondToMouseClickEvents()
164 {
165     return true;
166 }
167 #endif
168
169 // ----------------------------
170
171 inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document& document)
172     : HTMLDivElement(divTag, document)
173     , m_capturing(false)
174 {
175     setPseudo(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral));
176     setHasCustomStyleResolveCallbacks();
177 }
178
179 Ref<SearchFieldCancelButtonElement> SearchFieldCancelButtonElement::create(Document& document)
180 {
181     return adoptRef(*new SearchFieldCancelButtonElement(document));
182 }
183
184 void SearchFieldCancelButtonElement::willDetachRenderers()
185 {
186     if (m_capturing) {
187         if (Frame* frame = document().frame())
188             frame->eventHandler().setCapturingMouseEventsElement(nullptr);
189     }
190 }
191
192 void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
193 {
194     // If the element is visible, on mouseup, clear the value, and set selection
195     RefPtr<HTMLInputElement> input(downcast<HTMLInputElement>(shadowHost()));
196     if (!input || input->isDisabledOrReadOnly()) {
197         if (!event->defaultHandled())
198             HTMLDivElement::defaultEventHandler(event);
199         return;
200     }
201
202     if (event->type() == eventNames().mousedownEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton) {
203         if (renderer() && renderer()->visibleToHitTesting()) {
204             if (Frame* frame = document().frame()) {
205                 frame->eventHandler().setCapturingMouseEventsElement(this);
206                 m_capturing = true;
207             }
208         }
209         input->focus();
210         input->select();
211         event->setDefaultHandled();
212     }
213     if (event->type() == eventNames().mouseupEvent && is<MouseEvent>(*event) && downcast<MouseEvent>(*event).button() == LeftButton) {
214         if (m_capturing) {
215             if (Frame* frame = document().frame()) {
216                 frame->eventHandler().setCapturingMouseEventsElement(nullptr);
217                 m_capturing = false;
218             }
219             if (hovered()) {
220                 String oldValue = input->value();
221                 input->setValueForUser("");
222                 input->onSearch();
223                 event->setDefaultHandled();
224             }
225         }
226     }
227
228     if (!event->defaultHandled())
229         HTMLDivElement::defaultEventHandler(event);
230 }
231
232 #if !PLATFORM(IOS)
233 bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
234 {
235     const HTMLInputElement* input = downcast<HTMLInputElement>(shadowHost());
236     if (input && !input->isDisabledOrReadOnly())
237         return true;
238
239     return HTMLDivElement::willRespondToMouseClickEvents();
240 }
241 #endif
242
243 }