OSDN Git Service

Merge "merge from honeycomb mr2"
[android-x86/external-webkit.git] / Source / WebCore / rendering / RenderTextControlSingleLine.cpp
1 /**
2  * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
3  *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
4  * Copyright (C) 2010 Google Inc. All rights reserved.
5  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "RenderTextControlSingleLine.h"
26
27 #include "Chrome.h"
28 #include "CSSStyleSelector.h"
29 #include "Event.h"
30 #include "EventNames.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "HTMLInputElement.h"
34 #include "HTMLNames.h"
35 #include "HitTestResult.h"
36 #include "InputElement.h"
37 #include "LocalizedStrings.h"
38 #include "MouseEvent.h"
39 #include "PlatformKeyboardEvent.h"
40 #include "RenderLayer.h"
41 #include "RenderScrollbar.h"
42 #include "RenderTheme.h"
43 #include "SelectionController.h"
44 #include "Settings.h"
45 #include "SimpleFontData.h"
46 #include "TextControlInnerElements.h"
47
48 using namespace std;
49
50 namespace WebCore {
51
52 using namespace HTMLNames;
53
54 RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node, bool placeholderVisible)
55     : RenderTextControl(node, placeholderVisible)
56     , m_searchPopupIsVisible(false)
57     , m_shouldDrawCapsLockIndicator(false)
58     , m_searchEventTimer(this, &RenderTextControlSingleLine::searchEventTimerFired)
59     , m_searchPopup(0)
60 {
61 }
62
63 RenderTextControlSingleLine::~RenderTextControlSingleLine()
64 {
65     if (m_searchPopup) {
66         m_searchPopup->popupMenu()->disconnectClient();
67         m_searchPopup = 0;
68     }
69  
70     if (m_innerBlock) {
71         m_innerBlock->detach();
72         m_innerBlock = 0;
73     }
74
75     if (m_innerSpinButton)
76         m_innerSpinButton->detach();
77     if (m_outerSpinButton)
78         m_outerSpinButton->detach();
79 #if ENABLE(INPUT_SPEECH)
80     if (m_speechButton)
81         m_speechButton->detach();
82 #endif
83 }
84
85 RenderStyle* RenderTextControlSingleLine::textBaseStyle() const
86 {
87     return m_innerBlock ? m_innerBlock->renderer()->style() : style();
88 }
89
90 void RenderTextControlSingleLine::addSearchResult()
91 {
92     ASSERT(node()->isHTMLElement());
93     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
94     if (input->maxResults() <= 0)
95         return;
96
97     String value = input->value();
98     if (value.isEmpty())
99         return;
100
101     Settings* settings = document()->settings();
102     if (!settings || settings->privateBrowsingEnabled())
103         return;
104
105     int size = static_cast<int>(m_recentSearches.size());
106     for (int i = size - 1; i >= 0; --i) {
107         if (m_recentSearches[i] == value)
108             m_recentSearches.remove(i);
109     }
110
111     m_recentSearches.insert(0, value);
112     while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
113         m_recentSearches.removeLast();
114
115     const AtomicString& name = autosaveName();
116     if (!m_searchPopup)
117         m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
118
119     m_searchPopup->saveRecentSearches(name, m_recentSearches);
120 }
121
122 void RenderTextControlSingleLine::stopSearchEventTimer()
123 {
124     ASSERT(node()->isHTMLElement());
125     m_searchEventTimer.stop();
126 }
127
128 void RenderTextControlSingleLine::showPopup()
129 {
130     ASSERT(node()->isHTMLElement());
131     if (m_searchPopupIsVisible)
132         return;
133
134     if (!m_searchPopup)
135         m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
136
137     if (!m_searchPopup->enabled())
138         return;
139
140     m_searchPopupIsVisible = true;
141
142     const AtomicString& name = autosaveName();
143     m_searchPopup->loadRecentSearches(name, m_recentSearches);
144
145     // Trim the recent searches list if the maximum size has changed since we last saved.
146     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
147     if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
148         do {
149             m_recentSearches.removeLast();
150         } while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
151
152         m_searchPopup->saveRecentSearches(name, m_recentSearches);
153     }
154
155     m_searchPopup->popupMenu()->show(absoluteBoundingBoxRect(true), document()->view(), -1);
156 }
157
158 void RenderTextControlSingleLine::hidePopup()
159 {
160     ASSERT(node()->isHTMLElement());
161     if (m_searchPopup)
162         m_searchPopup->popupMenu()->hide();
163 }
164
165 void RenderTextControlSingleLine::subtreeHasChanged()
166 {
167     bool wasChanged = wasChangedSinceLastChangeEvent();
168     RenderTextControl::subtreeHasChanged();
169
170     InputElement* input = inputElement();
171     // We don't need to call sanitizeUserInputValue() function here because
172     // InputElement::handleBeforeTextInsertedEvent() has already called
173     // sanitizeUserInputValue().
174     // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
175     String value = text();
176     if (input->isAcceptableValue(value))
177         input->setValueFromRenderer(input->sanitizeValue(value));
178     if (node()->isHTMLElement()) {
179         // Recalc for :invalid and hasUnacceptableValue() change.
180         static_cast<HTMLInputElement*>(input)->setNeedsStyleRecalc();
181     }
182
183     if (m_cancelButton)
184         updateCancelButtonVisibility();
185
186     // If the incremental attribute is set, then dispatch the search event
187     if (input->searchEventsShouldBeDispatched())
188         startSearchEventTimer();
189
190     if (!wasChanged && node()->focused()) {
191         if (Frame* frame = this->frame())
192             frame->editor()->textFieldDidBeginEditing(static_cast<Element*>(node()));
193     }
194
195     if (node()->focused()) {
196         if (Frame* frame = document()->frame())
197             frame->editor()->textDidChangeInTextField(static_cast<Element*>(node()));
198     }
199 }
200
201 void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty)
202 {
203     RenderTextControl::paint(paintInfo, tx, ty);
204
205     if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
206         IntRect contentsRect = contentBoxRect();
207
208         // Center vertically like the text.
209         contentsRect.setY((height() - contentsRect.height()) / 2);
210
211         // Convert the rect into the coords used for painting the content
212         contentsRect.move(tx + x(), ty + y());
213         theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);
214     }
215 }
216
217 void RenderTextControlSingleLine::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
218 {
219     paintBoxDecorationsWithSize(paintInfo, tx, ty, width() - decorationWidthRight(), height());
220 }
221
222 void RenderTextControlSingleLine::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
223 {
224     int w = width() - decorationWidthRight();
225     if (w && height())
226         rects.append(IntRect(tx, ty, w, height()));
227 }
228
229 void RenderTextControlSingleLine::layout()
230 {
231     int oldHeight = height();
232     computeLogicalHeight();
233
234     int oldWidth = width();
235     computeLogicalWidth();
236
237     bool relayoutChildren = oldHeight != height() || oldWidth != width();
238
239 #ifdef ANDROID_LAYOUT
240     checkAndSetRelayoutChildren(&relayoutChildren);
241 #endif
242
243     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
244     RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0;
245
246     // Set the text block height
247     int desiredHeight = textBlockHeight();
248     int currentHeight = innerTextRenderer->height();
249
250     if (currentHeight > height()) {
251         if (desiredHeight != currentHeight)
252             relayoutChildren = true;
253         innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
254         if (m_innerBlock)
255             innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
256     }
257
258     // Set the text block width
259     int desiredWidth = textBlockWidth();
260     if (desiredWidth != innerTextRenderer->width())
261         relayoutChildren = true;
262     innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));
263
264     if (m_innerBlock) {
265         int innerBlockWidth = width() - borderAndPaddingWidth();
266         if (innerBlockWidth != innerBlockRenderer->width())
267             relayoutChildren = true;
268         innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));
269     }
270
271     RenderBlock::layoutBlock(relayoutChildren);
272
273     // Center the child block vertically
274     RenderBox* childBlock = innerBlockRenderer ? innerBlockRenderer : innerTextRenderer;
275     currentHeight = childBlock->height();
276     if (currentHeight < height())
277         childBlock->setY((height() - currentHeight) / 2);
278
279     // Ignores the paddings for the inner spin button.
280     if (RenderBox* spinBox = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
281         spinBox->setLocation(spinBox->x() + paddingRight(), borderTop());
282         spinBox->setHeight(height() - borderTop() - borderBottom());
283     }
284
285 #if ENABLE(INPUT_SPEECH)
286     if (RenderBox* button = m_speechButton ? m_speechButton->renderBox() : 0) {
287         if (m_innerBlock) {
288             // This is mostly the case where this is a search field. The speech button is a sibling
289             // of the inner block and laid out at the far right.
290             int x = width() - borderAndPaddingWidth() - button->width() - button->borderAndPaddingWidth();
291             int y = (height() - button->height()) / 2;
292             button->setLocation(x, y);
293         } else {
294             // For non-search fields which are simpler and we let the defaut layout handle things
295             // except for small tweaking below.
296             button->setLocation(button->x() + paddingRight(), (height() - button->height()) / 2);
297         }
298     }
299 #endif
300
301     // Center the spin button vertically, and move it to the right by
302     // padding + border of the text fields.
303     if (RenderBox* spinBox = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
304         int diff = height() - spinBox->height();
305         // If the diff is odd, the top area over the spin button takes the
306         // remaining one pixel. It's good for Mac NSStepper because it has
307         // shadow at the bottom.
308         int y = (diff / 2) + (diff % 2);
309         int x = width() - borderRight() - paddingRight() - spinBox->width();
310         spinBox->setLocation(x, y);
311     }
312 }
313
314 bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction)
315 {
316     // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
317     // was on the control but not on the inner element (see Radar 4617841).
318
319     // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
320     // and act as if we've hit the close block if we're to the right of the inner text block.
321
322     if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction))
323         return false;
324
325     // If we hit a node inside the inner text element, say that we hit that element,
326     // and if we hit our node (e.g. we're over the border or padding), also say that we hit the
327     // inner text element so that it gains focus.
328     if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node())
329         hitInnerTextElement(result, xPos, yPos, tx, ty);
330
331     // If we found a spin button, we're done.
332     if (m_innerSpinButton && result.innerNode() == m_innerSpinButton)
333         return true;
334     if (m_outerSpinButton && result.innerNode() == m_outerSpinButton)
335         return true;
336 #if ENABLE(INPUT_SPEECH)
337     if (m_speechButton && result.innerNode() == m_speechButton)
338         return true;
339 #endif
340     // If we're not a search field, or we already found the speech, results or cancel buttons, we're done.
341     if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton)
342         return true;
343
344     Node* innerNode = 0;
345     RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
346     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
347
348     IntPoint localPoint = result.localPoint();
349     localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());
350
351     int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();
352     if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)
353         innerNode = m_resultsButton.get();
354
355     if (!innerNode) {
356         int textRight = textLeft + innerTextRenderer->width();
357         if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)
358             innerNode = m_cancelButton.get();
359     }
360
361     if (innerNode) {
362         result.setInnerNode(innerNode);
363         localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
364     }
365
366     result.setLocalPoint(localPoint);
367     return true;
368 }
369
370 void RenderTextControlSingleLine::forwardEvent(Event* event)
371 {
372     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
373
374     if (event->type() == eventNames().blurEvent) {
375         if (innerTextRenderer) {
376             if (RenderLayer* innerLayer = innerTextRenderer->layer())
377                 innerLayer->scrollToOffset(!style()->isLeftToRightDirection() ? innerLayer->scrollWidth() : 0, 0);
378         }
379
380         capsLockStateMayHaveChanged();
381     } else if (event->type() == eventNames().focusEvent)
382         capsLockStateMayHaveChanged();
383
384     if (!event->isMouseEvent()) {
385         RenderTextControl::forwardEvent(event);
386         return;
387     }
388
389 #if ENABLE(INPUT_SPEECH)
390     if (RenderBox* speechBox = m_speechButton ? m_speechButton->renderBox() : 0) {
391         FloatPoint pointInTextControlCoords = absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
392         if (speechBox->frameRect().contains(roundedIntPoint(pointInTextControlCoords))) {
393             m_speechButton->defaultEventHandler(event);
394             return;
395         }
396     }
397 #endif
398
399     FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
400     int textRight = innerTextRenderer->borderBoxRect().maxX();
401
402     if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())
403         m_resultsButton->defaultEventHandler(event);
404     else if (m_cancelButton && localPoint.x() > textRight)
405         m_cancelButton->defaultEventHandler(event);
406     else if (m_innerSpinButton && localPoint.x() > textRight && m_innerSpinButton->renderBox() && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width())
407         m_innerSpinButton->defaultEventHandler(event);
408     else if (m_outerSpinButton && localPoint.x() > textRight)
409         m_outerSpinButton->defaultEventHandler(event);
410     else
411         RenderTextControl::forwardEvent(event);
412 }
413
414 void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
415 {
416     RenderTextControl::styleDidChange(diff, oldStyle);
417
418     if (RenderObject* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderer() : 0) {
419         // We may have set the width and the height in the old style in layout().
420         // Reset them now to avoid getting a spurious layout hint.
421         innerBlockRenderer->style()->setHeight(Length());
422         innerBlockRenderer->style()->setWidth(Length());
423         innerBlockRenderer->setStyle(createInnerBlockStyle(style()));
424     }
425
426     if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)
427         resultsRenderer->setStyle(createResultsButtonStyle(style()));
428
429     if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
430         cancelRenderer->setStyle(createCancelButtonStyle(style()));
431
432     if (RenderObject* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderer() : 0)
433         spinRenderer->setStyle(createOuterSpinButtonStyle());
434
435 #if ENABLE(INPUT_SPEECH)
436     if (RenderObject* speechRenderer = m_speechButton ? m_speechButton->renderer() : 0)
437         speechRenderer->setStyle(createSpeechButtonStyle());
438 #endif
439
440     setHasOverflowClip(false);
441 }
442
443 void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
444 {
445     if (!node() || !document())
446         return;
447
448     // Only draw the caps lock indicator if these things are true:
449     // 1) The field is a password field
450     // 2) The frame is active
451     // 3) The element is focused
452     // 4) The caps lock is on
453     bool shouldDrawCapsLockIndicator = false;
454
455     if (Frame* frame = document()->frame())
456         shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
457                                       && frame->selection()->isFocusedAndActive()
458                                       && document()->focusedNode() == node()
459                                       && PlatformKeyboardEvent::currentCapsLockState();
460
461     if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
462         m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
463         repaint();
464     }
465 }
466
467 bool RenderTextControlSingleLine::hasControlClip() const
468 {
469     bool clip = m_cancelButton;
470     return clip;
471 }
472
473 IntRect RenderTextControlSingleLine::controlClipRect(int tx, int ty) const
474 {
475     // This should only get called for search & speech inputs.
476     ASSERT(hasControlClip());
477
478     IntRect clipRect = IntRect(m_innerBlock->renderBox()->frameRect());
479     clipRect.move(tx, ty);
480     return clipRect;
481 }
482
483 int RenderTextControlSingleLine::textBlockWidth() const
484 {
485     int width = RenderTextControl::textBlockWidth();
486
487     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
488         resultsRenderer->computeLogicalWidth();
489         width -= resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->marginRight();
490     }
491
492     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
493         cancelRenderer->computeLogicalWidth();
494         width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
495     }
496
497     if (RenderBox* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
498         spinRenderer->computeLogicalWidth();
499         width -= spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight();
500     }
501
502 #if ENABLE(INPUT_SPEECH)
503     if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
504         speechRenderer->computeLogicalWidth();
505         width -= speechRenderer->width() + speechRenderer->marginLeft() + speechRenderer->marginRight();
506     }
507 #endif
508
509     return width - decorationWidthRight();
510 }
511
512 int RenderTextControlSingleLine::decorationWidthRight() const
513 {
514     int width = 0;
515     if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
516         spinRenderer->computeLogicalWidth();
517         width += spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight();
518     }
519     if (width > 0)
520         width += paddingRight() + borderRight();
521     return width;
522 }
523     
524 float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
525 {
526     // Since Lucida Grande is the default font, we want this to match the width
527     // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
528     // IE for some encodings (in IE, the default font is encoding specific).
529     // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg.
530     if (family == AtomicString("Lucida Grande"))
531         return scaleEmToUnits(901);
532
533     return RenderTextControl::getAvgCharWidth(family);
534 }
535     
536 int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
537 {
538     int factor = inputElement()->size();
539     if (factor <= 0)
540         factor = 20;
541
542     int result = static_cast<int>(ceilf(charWidth * factor));
543
544     float maxCharWidth = 0.f;
545     AtomicString family = style()->font().family().family();
546     // Since Lucida Grande is the default font, we want this to match the width
547     // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
548     // IE for some encodings (in IE, the default font is encoding specific).
549     // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg.
550     if (family == AtomicString("Lucida Grande"))
551         maxCharWidth = scaleEmToUnits(4027);
552     else if (hasValidAvgCharWidth(family))
553         maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth());
554
555     // For text inputs, IE adds some extra width.
556     if (maxCharWidth > 0.f)
557         result += maxCharWidth - charWidth;
558
559     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
560         result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() +
561                   resultsRenderer->paddingLeft() + resultsRenderer->paddingRight();
562
563     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
564         result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
565                   cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
566
567 #if ENABLE(INPUT_SPEECH)
568     if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
569         result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
570                   speechRenderer->paddingLeft() + speechRenderer->paddingRight();
571     }
572 #endif
573     return result;
574 }
575
576 int RenderTextControlSingleLine::preferredDecorationWidthRight() const
577 {
578     int width = 0;
579     if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
580         spinRenderer->computeLogicalWidth();
581         width += spinRenderer->minPreferredLogicalWidth() + spinRenderer->marginLeft() + spinRenderer->marginRight();
582     }
583     if (width > 0)
584         width += paddingRight() + borderRight();
585     return width;
586 }
587
588 void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
589 {
590     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
591         resultsRenderer->computeLogicalHeight();
592         setHeight(max(height(),
593                   resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
594                   resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
595                   resultsRenderer->marginTop() + resultsRenderer->marginBottom()));
596         lineHeight = max(lineHeight, resultsRenderer->height());
597     }
598     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
599         cancelRenderer->computeLogicalHeight();
600         setHeight(max(height(),
601                   cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
602                   cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
603                   cancelRenderer->marginTop() + cancelRenderer->marginBottom()));
604         lineHeight = max(lineHeight, cancelRenderer->height());
605     }
606
607     setHeight(height() + lineHeight);
608 }
609
610 void RenderTextControlSingleLine::createSubtreeIfNeeded()
611 {
612     bool createSubtree = inputElement()->isSearchField();
613     if (!createSubtree) {
614         RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
615 #if ENABLE(INPUT_SPEECH)
616         if (inputElement()->isSpeechEnabled() && !m_speechButton) {
617             // Create the speech button element.
618             m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
619             m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
620         }
621 #endif
622         bool hasSpinButton = inputElement()->hasSpinButton();
623         if (hasSpinButton && !m_innerSpinButton) {
624             m_innerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
625             m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena());
626         }
627         if (hasSpinButton && !m_outerSpinButton) {
628             m_outerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
629             m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
630         }
631         return;
632     }
633
634     if (!m_innerBlock) {
635         // Create the inner block element
636         m_innerBlock = TextControlInnerElement::create(toHTMLElement(node()));
637         m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
638     }
639 #if ENABLE(INPUT_SPEECH)
640     if (inputElement()->isSpeechEnabled() && !m_speechButton) {
641         // Create the speech button element.
642         m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
643         m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
644     }
645 #endif
646     if (inputElement()->hasSpinButton() && !m_outerSpinButton) {
647         m_outerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
648         m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
649     }
650
651     if (inputElement()->isSearchField()) {
652         if (!m_resultsButton) {
653             // Create the search results button element.
654             m_resultsButton = SearchFieldResultsButtonElement::create(document());
655             m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
656         }
657     }
658
659     // Create innerText element before adding the other buttons.
660     RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
661
662     if (inputElement()->isSearchField()) {
663         if (!m_cancelButton) {
664             // Create the cancel button element.
665             m_cancelButton = SearchFieldCancelButtonElement::create(document());
666             m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
667         }
668     }
669 }
670
671 void RenderTextControlSingleLine::updateFromElement()
672 {
673     createSubtreeIfNeeded();
674     RenderTextControl::updateFromElement();
675
676     if (m_cancelButton)
677         updateCancelButtonVisibility();
678
679     if (!inputElement()->suggestedValue().isNull())
680         setInnerTextValue(inputElement()->suggestedValue());
681     else {
682         if (node()->hasTagName(inputTag)) {
683             // For HTMLInputElement, update the renderer value if the formControlValueMatchesRenderer()
684             // flag is false. It protects an unacceptable renderer value from
685             // being overwritten with the DOM value.
686             if (!static_cast<HTMLInputElement*>(node())->formControlValueMatchesRenderer())
687                 setInnerTextValue(inputElement()->visibleValue());
688         }
689     }
690
691     if (m_searchPopupIsVisible)
692         m_searchPopup->popupMenu()->updateFromElement();
693 }
694
695 void RenderTextControlSingleLine::cacheSelection(int start, int end)
696 {
697     inputElement()->cacheSelection(start, end);
698 }
699
700 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
701 {
702     RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();   
703     textBlockStyle->inheritFrom(startStyle);
704     adjustInnerTextStyle(startStyle, textBlockStyle.get());
705
706     textBlockStyle->setWhiteSpace(PRE);
707     textBlockStyle->setWordWrap(NormalWordWrap);
708     textBlockStyle->setOverflowX(OHIDDEN);
709     textBlockStyle->setOverflowY(OHIDDEN);
710
711     // Do not allow line-height to be smaller than our default.
712     if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
713         textBlockStyle->setLineHeight(Length(-100.0f, Percent));
714
715     WebCore::EDisplay display = (m_innerBlock || inputElement()->hasSpinButton() ? INLINE_BLOCK : BLOCK);
716 #if ENABLE(INPUT_SPEECH)
717     if (inputElement()->isSpeechEnabled())
718       display = INLINE_BLOCK;
719 #endif
720     textBlockStyle->setDisplay(display);
721
722     // We're adding one extra pixel of padding to match WinIE.
723     textBlockStyle->setPaddingLeft(Length(1, Fixed));
724     textBlockStyle->setPaddingRight(Length(1, Fixed));
725
726     return textBlockStyle.release();
727 }
728
729 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
730 {
731     ASSERT(node()->isHTMLElement());
732
733     RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
734     innerBlockStyle->inheritFrom(startStyle);
735
736     innerBlockStyle->setDisplay(inputElement()->hasSpinButton() ? INLINE_BLOCK : BLOCK);
737     innerBlockStyle->setDirection(LTR);
738
739     // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
740     innerBlockStyle->setUserModify(READ_ONLY);
741
742     return innerBlockStyle.release();
743 }
744
745 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createResultsButtonStyle(const RenderStyle* startStyle) const
746 {
747     ASSERT(node()->isHTMLElement());
748     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
749
750     RefPtr<RenderStyle> resultsBlockStyle;
751     if (input->maxResults() < 0)
752         resultsBlockStyle = getCachedPseudoStyle(SEARCH_DECORATION);
753     else if (!input->maxResults())
754         resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_DECORATION);
755     else
756         resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_BUTTON);
757
758     if (!resultsBlockStyle)
759         resultsBlockStyle = RenderStyle::create();
760
761     if (startStyle)
762         resultsBlockStyle->inheritFrom(startStyle);
763
764     return resultsBlockStyle.release();
765 }
766
767 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(const RenderStyle* startStyle) const
768 {
769     ASSERT(node()->isHTMLElement());
770     RefPtr<RenderStyle> cancelBlockStyle;
771     
772     if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(SEARCH_CANCEL_BUTTON))
773         // We may be sharing style with another search field, but we must not share the cancel button style.
774         cancelBlockStyle = RenderStyle::clone(pseudoStyle.get());
775     else
776         cancelBlockStyle = RenderStyle::create();
777
778     if (startStyle)
779         cancelBlockStyle->inheritFrom(startStyle);
780
781     cancelBlockStyle->setVisibility(visibilityForCancelButton());
782     return cancelBlockStyle.release();
783 }
784
785 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerSpinButtonStyle() const
786 {
787     ASSERT(node()->isHTMLElement());
788     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INNER_SPIN_BUTTON);
789     if (!buttonStyle)
790         buttonStyle = RenderStyle::create();
791     buttonStyle->inheritFrom(style());
792     return buttonStyle.release();
793 }
794
795 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createOuterSpinButtonStyle() const
796 {
797     ASSERT(node()->isHTMLElement());
798     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(OUTER_SPIN_BUTTON);
799     if (!buttonStyle)
800         buttonStyle = RenderStyle::create();
801     buttonStyle->inheritFrom(style());
802     return buttonStyle.release();
803 }
804
805 #if ENABLE(INPUT_SPEECH)
806 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createSpeechButtonStyle() const
807 {
808     ASSERT(node()->isHTMLElement());
809     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INPUT_SPEECH_BUTTON);
810     if (!buttonStyle)
811         buttonStyle = RenderStyle::create();
812     buttonStyle->inheritFrom(style());
813     return buttonStyle.release();
814 }
815 #endif
816
817 void RenderTextControlSingleLine::updateCancelButtonVisibility() const
818 {
819     if (!m_cancelButton->renderer())
820         return;
821
822     const RenderStyle* curStyle = m_cancelButton->renderer()->style();
823     EVisibility buttonVisibility = visibilityForCancelButton();
824     if (curStyle->visibility() == buttonVisibility)
825         return;
826
827     RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle);
828     cancelButtonStyle->setVisibility(buttonVisibility);
829     m_cancelButton->renderer()->setStyle(cancelButtonStyle);
830 }
831
832 EVisibility RenderTextControlSingleLine::visibilityForCancelButton() const
833 {
834     ASSERT(node()->isHTMLElement());
835     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
836     return input->value().isEmpty() ? HIDDEN : VISIBLE;
837 }
838
839 const AtomicString& RenderTextControlSingleLine::autosaveName() const
840 {
841     return static_cast<Element*>(node())->getAttribute(autosaveAttr);
842 }
843
844 void RenderTextControlSingleLine::startSearchEventTimer()
845 {
846     ASSERT(node()->isHTMLElement());
847     unsigned length = text().length();
848
849     // If there's no text, fire the event right away.
850     if (!length) {
851         stopSearchEventTimer();
852         static_cast<HTMLInputElement*>(node())->onSearch();
853         return;
854     }
855
856     // After typing the first key, we wait 0.5 seconds.
857     // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
858     m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
859 }
860
861 void RenderTextControlSingleLine::searchEventTimerFired(Timer<RenderTextControlSingleLine>*)
862 {
863     ASSERT(node()->isHTMLElement());
864     static_cast<HTMLInputElement*>(node())->onSearch();
865 }
866
867 // PopupMenuClient methods
868 void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents)
869 {
870     ASSERT(node()->isHTMLElement());
871     ASSERT(static_cast<int>(listIndex) < listSize());
872     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
873     if (static_cast<int>(listIndex) == (listSize() - 1)) {
874         if (fireEvents) {
875             m_recentSearches.clear();
876             const AtomicString& name = autosaveName();
877             if (!name.isEmpty()) {
878                 if (!m_searchPopup)
879                     m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
880                 m_searchPopup->saveRecentSearches(name, m_recentSearches);
881             }
882         }
883     } else {
884         input->setValue(itemText(listIndex));
885         if (fireEvents)
886             input->onSearch();
887         input->select();
888     }
889 }
890
891 String RenderTextControlSingleLine::itemText(unsigned listIndex) const
892 {
893     int size = listSize();
894     if (size == 1) {
895         ASSERT(!listIndex);
896         return searchMenuNoRecentSearchesText();
897     }
898     if (!listIndex)
899         return searchMenuRecentSearchesText();
900     if (itemIsSeparator(listIndex))
901         return String();
902     if (static_cast<int>(listIndex) == (size - 1))
903         return searchMenuClearRecentSearchesText();
904     return m_recentSearches[listIndex - 1];
905 }
906
907 String RenderTextControlSingleLine::itemLabel(unsigned) const
908 {
909     return String();
910 }
911
912 String RenderTextControlSingleLine::itemIcon(unsigned) const
913 {
914     return String();
915 }
916
917 bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const
918 {
919      if (!listIndex || itemIsSeparator(listIndex))
920         return false;
921     return true;
922 }
923
924 PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
925 {
926     return menuStyle();
927 }
928
929 PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
930 {
931     return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction(), style()->unicodeBidi() == Override);
932 }
933
934 int RenderTextControlSingleLine::clientInsetLeft() const
935 {
936     // Inset the menu by the radius of the cap on the left so that
937     // it only runs along the straight part of the bezel.
938     return height() / 2;
939 }
940
941 int RenderTextControlSingleLine::clientInsetRight() const
942 {
943     // Inset the menu by the radius of the cap on the right so that
944     // it only runs along the straight part of the bezel (unless it needs
945     // to be wider).
946     return height() / 2;
947 }
948
949 int RenderTextControlSingleLine::clientPaddingLeft() const
950 {
951     int padding = paddingLeft();
952
953     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
954         padding += resultsRenderer->width();
955
956     return padding;
957 }
958
959 int RenderTextControlSingleLine::clientPaddingRight() const
960 {
961     int padding = paddingRight();
962
963     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
964         padding += cancelRenderer->width();
965
966     return padding;
967 }
968
969 int RenderTextControlSingleLine::listSize() const
970 {
971     // If there are no recent searches, then our menu will have 1 "No recent searches" item.
972     if (!m_recentSearches.size())
973         return 1;
974     // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
975     return m_recentSearches.size() + 3;
976 }
977
978 int RenderTextControlSingleLine::selectedIndex() const
979 {
980     return -1;
981 }
982
983 void RenderTextControlSingleLine::popupDidHide()
984 {
985     m_searchPopupIsVisible = false;
986 }
987
988 bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const
989 {
990     // The separator will be the second to last item in our list.
991     return static_cast<int>(listIndex) == (listSize() - 2);
992 }
993
994 bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const
995 {
996     return listIndex == 0;
997 }
998
999 bool RenderTextControlSingleLine::itemIsSelected(unsigned) const
1000 {
1001     return false;
1002 }
1003
1004 void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
1005 {
1006     ASSERT(node()->isHTMLElement());
1007     static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
1008 }
1009
1010 FontSelector* RenderTextControlSingleLine::fontSelector() const
1011 {
1012     return document()->styleSelector()->fontSelector();
1013 }
1014
1015 HostWindow* RenderTextControlSingleLine::hostWindow() const
1016 {
1017     return document()->view()->hostWindow();
1018 }
1019
1020 void RenderTextControlSingleLine::autoscroll()
1021 {
1022     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1023     if (layer)
1024         layer->autoscroll();
1025 }
1026
1027 int RenderTextControlSingleLine::scrollWidth() const
1028 {
1029     if (innerTextElement())
1030         return innerTextElement()->scrollWidth();
1031     return RenderBlock::scrollWidth();
1032 }
1033
1034 int RenderTextControlSingleLine::scrollHeight() const
1035 {
1036     if (innerTextElement())
1037         return innerTextElement()->scrollHeight();
1038     return RenderBlock::scrollHeight();
1039 }
1040
1041 int RenderTextControlSingleLine::scrollLeft() const
1042 {
1043     if (innerTextElement())
1044         return innerTextElement()->scrollLeft();
1045     return RenderBlock::scrollLeft();
1046 }
1047
1048 int RenderTextControlSingleLine::scrollTop() const
1049 {
1050     if (innerTextElement())
1051         return innerTextElement()->scrollTop();
1052     return RenderBlock::scrollTop();
1053 }
1054
1055 void RenderTextControlSingleLine::setScrollLeft(int newLeft)
1056 {
1057     if (innerTextElement())
1058         innerTextElement()->setScrollLeft(newLeft);
1059 }
1060
1061 void RenderTextControlSingleLine::setScrollTop(int newTop)
1062 {
1063     if (innerTextElement())
1064         innerTextElement()->setScrollTop(newTop);
1065 }
1066
1067 bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
1068 {
1069     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1070     if (layer && layer->scroll(direction, granularity, multiplier))
1071         return true;
1072     return RenderBlock::scroll(direction, granularity, multiplier, stopNode);
1073 }
1074
1075 bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
1076 {
1077     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1078     if (layer && layer->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
1079         return true;
1080     return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode);
1081 }
1082
1083 PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
1084 {
1085     RefPtr<Scrollbar> widget;
1086     bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
1087     if (hasCustomScrollbarStyle)
1088         widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this);
1089     else
1090         widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
1091     return widget.release();
1092 }
1093
1094 InputElement* RenderTextControlSingleLine::inputElement() const
1095 {
1096     return toInputElement(static_cast<Element*>(node()));
1097 }
1098
1099 int RenderTextControlSingleLine::textBlockInsetLeft() const
1100 {
1101     int inset = borderLeft() + clientPaddingLeft();
1102     if (HTMLElement* innerText = innerTextElement()) {
1103         if (RenderBox* innerTextRenderer = innerText->renderBox())
1104             inset += innerTextRenderer->paddingLeft();
1105     }
1106     return inset;
1107 }
1108     
1109 int RenderTextControlSingleLine::textBlockInsetRight() const
1110 {
1111     int inset = borderRight() + clientPaddingRight();
1112     if (HTMLElement* innerText = innerTextElement()) {
1113         if (RenderBox* innerTextRenderer = innerText->renderBox())
1114             inset += innerTextRenderer->paddingRight();
1115     }
1116     return inset;
1117 }
1118
1119 int RenderTextControlSingleLine::textBlockInsetTop() const
1120 {
1121     RenderBox* innerRenderer = 0;
1122     if (m_innerBlock)
1123         innerRenderer = m_innerBlock->renderBox();
1124     else if (HTMLElement* innerText = innerTextElement())
1125         innerRenderer = innerText->renderBox();
1126     
1127     if (innerRenderer)
1128         return innerRenderer->y();
1129     
1130     return borderTop() + paddingTop();
1131 }    
1132
1133 }