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/NodeComputedStyle.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/input/EventHandler.h"
40 #include "core/layout/LayoutTextControlSingleLine.h"
41 #include "core/layout/LayoutView.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 LayoutObject
* TextControlInnerContainer::createLayoutObject(const ComputedStyle
&)
62 return new LayoutTextControlInnerContainer(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
<ComputedStyle
> EditingViewPortElement::customStyleForLayoutObject()
82 // FXIME: Move these styles to html.css.
84 RefPtr
<ComputedStyle
> style
= ComputedStyle::create();
85 style
->inheritFrom(shadowHost()->computedStyleRef());
87 style
->setFlexGrow(1);
88 style
->setMinWidth(Length(0, Fixed
));
89 style
->setDisplay(BLOCK
);
90 style
->setDirection(LTR
);
92 // We don't want the shadow dom to be editable, so we set this block to
93 // read-only in case the input itself is editable.
94 style
->setUserModify(READ_ONLY
);
97 return style
.release();
100 // ---------------------------
102 inline TextControlInnerEditorElement::TextControlInnerEditorElement(Document
& document
)
103 : HTMLDivElement(document
)
105 setHasCustomStyleCallbacks();
108 PassRefPtrWillBeRawPtr
<TextControlInnerEditorElement
> TextControlInnerEditorElement::create(Document
& document
)
110 RefPtrWillBeRawPtr
<TextControlInnerEditorElement
> element
= adoptRefWillBeNoop(new TextControlInnerEditorElement(document
));
111 element
->setAttribute(idAttr
, ShadowElementNames::innerEditor());
112 return element
.release();
115 void TextControlInnerEditorElement::defaultEventHandler(Event
* event
)
117 // FIXME: In the future, we should add a way to have default event listeners.
118 // Then we would add one to the text field's inner div, and we wouldn't need this subclass.
119 // Or possibly we could just use a normal event listener.
120 if (event
->isBeforeTextInsertedEvent() || event
->type() == EventTypeNames::webkitEditableContentChanged
) {
121 Element
* shadowAncestor
= shadowHost();
122 // A TextControlInnerTextElement can have no host if its been detached,
123 // but kept alive by an EditCommand. In this case, an undo/redo can
124 // cause events to be sent to the TextControlInnerTextElement. To
125 // prevent an infinite loop, we must check for this case before sending
126 // the event up the chain.
128 shadowAncestor
->defaultEventHandler(event
);
130 if (!event
->defaultHandled())
131 HTMLDivElement::defaultEventHandler(event
);
134 LayoutObject
* TextControlInnerEditorElement::createLayoutObject(const ComputedStyle
&)
136 return new LayoutTextControlInnerBlock(this);
139 PassRefPtr
<ComputedStyle
> TextControlInnerEditorElement::customStyleForLayoutObject()
141 LayoutObject
* parentLayoutObject
= shadowHost()->layoutObject();
142 if (!parentLayoutObject
|| !parentLayoutObject
->isTextControl())
143 return originalStyleForLayoutObject();
144 LayoutTextControl
* textControlLayoutObject
= toLayoutTextControl(parentLayoutObject
);
145 return textControlLayoutObject
->createInnerEditorStyle(textControlLayoutObject
->styleRef());
148 // ----------------------------
150 inline SearchFieldDecorationElement::SearchFieldDecorationElement(Document
& document
)
151 : HTMLDivElement(document
)
155 PassRefPtrWillBeRawPtr
<SearchFieldDecorationElement
> SearchFieldDecorationElement::create(Document
& document
)
157 RefPtrWillBeRawPtr
<SearchFieldDecorationElement
> element
= adoptRefWillBeNoop(new SearchFieldDecorationElement(document
));
158 element
->setAttribute(idAttr
, ShadowElementNames::searchDecoration());
159 return element
.release();
162 const AtomicString
& SearchFieldDecorationElement::shadowPseudoId() const
164 DEFINE_STATIC_LOCAL(AtomicString
, resultsDecorationId
, ("-webkit-search-results-decoration", AtomicString::ConstructFromLiteral
));
165 DEFINE_STATIC_LOCAL(AtomicString
, decorationId
, ("-webkit-search-decoration", AtomicString::ConstructFromLiteral
));
166 Element
* host
= shadowHost();
168 return resultsDecorationId
;
169 if (isHTMLInputElement(*host
)) {
170 if (toHTMLInputElement(host
)->maxResults() < 0)
172 return resultsDecorationId
;
174 return resultsDecorationId
;
177 void SearchFieldDecorationElement::defaultEventHandler(Event
* event
)
179 // On mousedown, focus the search field
180 HTMLInputElement
* input
= toHTMLInputElement(shadowHost());
181 if (input
&& event
->type() == EventTypeNames::mousedown
&& event
->isMouseEvent() && toMouseEvent(event
)->button() == LeftButton
) {
183 input
->select(NotDispatchSelectEvent
);
184 event
->setDefaultHandled();
187 if (!event
->defaultHandled())
188 HTMLDivElement::defaultEventHandler(event
);
191 bool SearchFieldDecorationElement::willRespondToMouseClickEvents()
196 // ----------------------------
198 inline SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document
& document
)
199 : HTMLDivElement(document
)
204 PassRefPtrWillBeRawPtr
<SearchFieldCancelButtonElement
> SearchFieldCancelButtonElement::create(Document
& document
)
206 RefPtrWillBeRawPtr
<SearchFieldCancelButtonElement
> element
= adoptRefWillBeNoop(new SearchFieldCancelButtonElement(document
));
207 element
->setShadowPseudoId(AtomicString("-webkit-search-cancel-button", AtomicString::ConstructFromLiteral
));
208 element
->setAttribute(idAttr
, ShadowElementNames::clearButton());
209 return element
.release();
212 void SearchFieldCancelButtonElement::detach(const AttachContext
& context
)
215 if (LocalFrame
* frame
= document().frame())
216 frame
->eventHandler().setCapturingMouseEventsNode(nullptr);
218 HTMLDivElement::detach(context
);
222 void SearchFieldCancelButtonElement::defaultEventHandler(Event
* event
)
224 // If the element is visible, on mouseup, clear the value, and set selection
225 RefPtrWillBeRawPtr
<HTMLInputElement
> input(toHTMLInputElement(shadowHost()));
226 if (!input
|| input
->isDisabledOrReadOnly()) {
227 if (!event
->defaultHandled())
228 HTMLDivElement::defaultEventHandler(event
);
233 if (event
->type() == EventTypeNames::click
&& event
->isMouseEvent() && toMouseEvent(event
)->button() == LeftButton
) {
234 input
->setValueForUser("");
235 input
->setAutofilled(false);
237 event
->setDefaultHandled();
240 if (!event
->defaultHandled())
241 HTMLDivElement::defaultEventHandler(event
);
244 bool SearchFieldCancelButtonElement::willRespondToMouseClickEvents()
246 const HTMLInputElement
* input
= toHTMLInputElement(shadowHost());
247 if (input
&& !input
->isDisabledOrReadOnly())
250 return HTMLDivElement::willRespondToMouseClickEvents();