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).
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.
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.
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.
25 #include "RenderTextControlSingleLine.h"
27 #include "CSSFontSelector.h"
28 #include "CSSStyleSelector.h"
31 #include "FrameSelection.h"
32 #include "FrameView.h"
33 #include "HTMLInputElement.h"
34 #include "HTMLNames.h"
35 #include "HitTestResult.h"
36 #include "LocalizedStrings.h"
38 #include "PlatformKeyboardEvent.h"
39 #include "RenderLayer.h"
40 #include "RenderScrollbar.h"
41 #include "RenderTheme.h"
42 #include "SearchPopupMenu.h"
44 #include "SimpleFontData.h"
45 #include "TextControlInnerElements.h"
51 using namespace HTMLNames;
53 VisiblePosition RenderTextControlInnerBlock::positionForPoint(const LayoutPoint& point)
55 LayoutPoint contentsPoint(point);
57 // Multiline text controls have the scroll on shadowAncestorNode, so we need to take that
60 RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer());
61 if (renderer->hasOverflowClip())
62 contentsPoint += renderer->layer()->scrolledContentOffset();
65 return RenderBlock::positionForPoint(contentsPoint);
68 // ----------------------------
70 RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node)
71 : RenderTextControl(node)
72 , m_searchPopupIsVisible(false)
73 , m_shouldDrawCapsLockIndicator(false)
74 , m_desiredInnerTextHeight(-1)
77 ASSERT(node->isHTMLElement());
78 ASSERT(node->toInputElement());
81 RenderTextControlSingleLine::~RenderTextControlSingleLine()
84 m_searchPopup->popupMenu()->disconnectClient();
89 inline HTMLElement* RenderTextControlSingleLine::containerElement() const
91 return inputElement()->containerElement();
94 inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const
96 return inputElement()->innerBlockElement();
99 inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const
101 return inputElement()->innerSpinButtonElement();
104 inline HTMLElement* RenderTextControlSingleLine::resultsButtonElement() const
106 return inputElement()->resultsButtonElement();
109 inline HTMLElement* RenderTextControlSingleLine::cancelButtonElement() const
111 return inputElement()->cancelButtonElement();
114 RenderStyle* RenderTextControlSingleLine::textBaseStyle() const
116 HTMLElement* innerBlock = innerBlockElement();
117 return innerBlock ? innerBlock->renderer()->style() : style();
120 void RenderTextControlSingleLine::addSearchResult()
122 HTMLInputElement* input = inputElement();
123 if (input->maxResults() <= 0)
126 String value = input->value();
130 Settings* settings = document()->settings();
131 if (!settings || settings->privateBrowsingEnabled())
134 int size = static_cast<int>(m_recentSearches.size());
135 for (int i = size - 1; i >= 0; --i) {
136 if (m_recentSearches[i] == value)
137 m_recentSearches.remove(i);
140 m_recentSearches.insert(0, value);
141 while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
142 m_recentSearches.removeLast();
144 const AtomicString& name = autosaveName();
146 m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
148 m_searchPopup->saveRecentSearches(name, m_recentSearches);
151 void RenderTextControlSingleLine::showPopup()
153 if (m_searchPopupIsVisible)
157 m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
159 if (!m_searchPopup->enabled())
162 m_searchPopupIsVisible = true;
164 const AtomicString& name = autosaveName();
165 m_searchPopup->loadRecentSearches(name, m_recentSearches);
167 // Trim the recent searches list if the maximum size has changed since we last saved.
168 HTMLInputElement* input = inputElement();
169 if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
171 m_recentSearches.removeLast();
172 } while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
174 m_searchPopup->saveRecentSearches(name, m_recentSearches);
177 m_searchPopup->popupMenu()->show(absoluteBoundingBoxRect(true), document()->view(), -1);
180 void RenderTextControlSingleLine::hidePopup()
183 m_searchPopup->popupMenu()->hide();
186 void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
188 RenderTextControl::paint(paintInfo, paintOffset);
190 if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
191 LayoutRect contentsRect = contentBoxRect();
193 // Center vertically like the text.
194 contentsRect.setY((height() - contentsRect.height()) / 2);
196 // Convert the rect into the coords used for painting the content
197 contentsRect.moveBy(paintOffset + location());
198 theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);
202 void RenderTextControlSingleLine::layout()
204 // FIXME: We should remove the height-related hacks in layout() and
205 // styleDidChange(). We need them because
206 // - Center the inner elements vertically if the input height is taller than
207 // the intrinsic height of the inner elements.
208 // - Shrink the inner elment heights if the input height is samller than the
209 // intrinsic heights of the inner elements.
211 // We don't honor paddings and borders for textfields without decorations
212 // and type=search if the text height is taller than the contentHeight()
213 // because of compability.
215 LayoutUnit oldHeight = height();
216 computeLogicalHeight();
218 LayoutUnit oldWidth = width();
219 computeLogicalWidth();
221 bool relayoutChildren = oldHeight != height() || oldWidth != width();
223 RenderBox* innerTextRenderer = innerTextElement()->renderBox();
224 ASSERT(innerTextRenderer);
225 RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;
226 HTMLElement* container = containerElement();
227 RenderBox* containerRenderer = container ? container->renderBox() : 0;
229 // Set the text block height
230 LayoutUnit desiredHeight = textBlockHeight();
231 LayoutUnit currentHeight = innerTextRenderer->height();
233 LayoutUnit heightLimit = (inputElement()->isSearchField() || !container) ? height() : contentHeight();
234 if (currentHeight > heightLimit) {
235 if (desiredHeight != currentHeight)
236 relayoutChildren = true;
237 innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
238 m_desiredInnerTextHeight = desiredHeight;
239 if (innerBlockRenderer)
240 innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
242 // The container might be taller because of decoration elements.
243 if (containerRenderer) {
244 containerRenderer->layoutIfNeeded();
245 LayoutUnit containerHeight = containerRenderer->height();
246 if (containerHeight > heightLimit) {
247 containerRenderer->style()->setHeight(Length(heightLimit, Fixed));
248 relayoutChildren = true;
249 } else if (containerRenderer->height() < contentHeight()) {
250 containerRenderer->style()->setHeight(Length(contentHeight(), Fixed));
251 relayoutChildren = true;
255 RenderBlock::layoutBlock(relayoutChildren);
257 // Center the child block vertically
258 currentHeight = innerTextRenderer->height();
259 if (!container && currentHeight != contentHeight()) {
260 LayoutUnit heightDiff = currentHeight - contentHeight();
261 innerTextRenderer->setY(innerTextRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
262 } else if (inputElement()->isSearchField() && containerRenderer && containerRenderer->height() > contentHeight()) {
263 // A quirk for find-in-page box on Safari Windows.
264 // http://webkit.org/b/63157
265 LayoutUnit heightDiff = containerRenderer->height() - contentHeight();
266 containerRenderer->setY(containerRenderer->y() - (heightDiff / 2 + layoutMod(heightDiff, 2)));
269 // Ignores the paddings for the inner spin button.
270 if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
271 RenderBox* parentBox = innerSpinBox->parentBox();
272 if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
273 innerSpinBox->setLocation(LayoutPoint(-paddingLeft(), -paddingTop()));
275 innerSpinBox->setLocation(LayoutPoint(parentBox->width() - innerSpinBox->width() + paddingRight(), -paddingTop()));
276 innerSpinBox->setHeight(height() - borderTop() - borderBottom());
279 HTMLElement* placeholderElement = inputElement()->placeholderElement();
280 if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
281 placeholderBox->style()->setWidth(Length(innerTextRenderer->width() - placeholderBox->borderAndPaddingWidth(), Fixed));
282 placeholderBox->style()->setHeight(Length(innerTextRenderer->height() - placeholderBox->borderAndPaddingHeight(), Fixed));
283 placeholderBox->layoutIfNeeded();
284 LayoutPoint textOffset = innerTextRenderer->location();
285 if (innerBlockElement() && innerBlockElement()->renderBox())
286 textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
287 if (containerRenderer)
288 textOffset += toLayoutSize(containerRenderer->location());
289 placeholderBox->setLocation(textOffset);
293 bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
295 if (!RenderTextControl::nodeAtPoint(request, result, pointInContainer, accumulatedOffset, hitTestAction))
298 // Say that we hit the inner text element if
299 // - we hit a node inside the inner text element,
300 // - we hit the <input> element (e.g. we're over the border or padding), or
301 // - we hit regions not in any decoration buttons.
302 HTMLElement* container = containerElement();
303 if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node() || (container && container == result.innerNode())) {
304 LayoutPoint pointInParent = pointInContainer;
305 if (container && innerBlockElement()) {
306 if (innerBlockElement()->renderBox())
307 pointInParent -= toLayoutSize(innerBlockElement()->renderBox()->location());
308 if (container->renderBox())
309 pointInParent -= toLayoutSize(container->renderBox()->location());
311 hitInnerTextElement(result, pointInParent, accumulatedOffset);
316 void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
318 m_desiredInnerTextHeight = -1;
319 RenderTextControl::styleDidChange(diff, oldStyle);
321 // We may have set the width and the height in the old style in layout().
322 // Reset them now to avoid getting a spurious layout hint.
323 HTMLElement* innerBlock = innerBlockElement();
324 if (RenderObject* innerBlockRenderer = innerBlock ? innerBlock->renderer() : 0) {
325 innerBlockRenderer->style()->setHeight(Length());
326 innerBlockRenderer->style()->setWidth(Length());
328 HTMLElement* container = containerElement();
329 if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
330 containerRenderer->style()->setHeight(Length());
331 containerRenderer->style()->setWidth(Length());
333 setHasOverflowClip(false);
336 void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
338 if (!node() || !document())
341 // Only draw the caps lock indicator if these things are true:
342 // 1) The field is a password field
343 // 2) The frame is active
344 // 3) The element is focused
345 // 4) The caps lock is on
346 bool shouldDrawCapsLockIndicator = false;
348 if (Frame* frame = document()->frame())
349 shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
350 && frame->selection()->isFocusedAndActive()
351 && document()->focusedNode() == node()
352 && PlatformKeyboardEvent::currentCapsLockState();
354 if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
355 m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
360 #if ENABLE(INPUT_SPEECH)
361 HTMLElement* RenderTextControlSingleLine::speechButtonElement() const
363 return inputElement()->speechButtonElement();
367 bool RenderTextControlSingleLine::hasControlClip() const
369 // Apply control clip for text fields with decorations.
370 return !!containerElement();
373 LayoutRect RenderTextControlSingleLine::controlClipRect(const LayoutPoint& additionalOffset) const
375 ASSERT(hasControlClip());
376 LayoutRect clipRect = LayoutRect(containerElement()->renderBox()->frameRect());
377 clipRect.moveBy(additionalOffset);
381 float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
383 // Since Lucida Grande is the default font, we want this to match the width
384 // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
385 // IE for some encodings (in IE, the default font is encoding specific).
386 // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg.
387 if (family == AtomicString("Lucida Grande"))
388 return scaleEmToUnits(901);
390 return RenderTextControl::getAvgCharWidth(family);
393 LayoutUnit RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
396 bool includesDecoration = inputElement()->sizeShouldIncludeDecoration(factor);
400 LayoutUnit result = static_cast<LayoutUnit>(ceiledLayoutUnit(charWidth * factor));
402 float maxCharWidth = 0.f;
403 AtomicString family = style()->font().family().family();
404 // Since Lucida Grande is the default font, we want this to match the width
405 // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
406 // IE for some encodings (in IE, the default font is encoding specific).
407 // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg.
408 if (family == AtomicString("Lucida Grande"))
409 maxCharWidth = scaleEmToUnits(4027);
410 else if (hasValidAvgCharWidth(family))
411 maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth());
413 // For text inputs, IE adds some extra width.
414 if (maxCharWidth > 0.f)
415 result += maxCharWidth - charWidth;
417 HTMLElement* resultsButton = resultsButtonElement();
418 if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0)
419 result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() +
420 resultsRenderer->paddingLeft() + resultsRenderer->paddingRight();
422 HTMLElement* cancelButton = cancelButtonElement();
423 if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0)
424 result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
425 cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
427 if (includesDecoration) {
428 HTMLElement* spinButton = innerSpinButtonElement();
429 if (RenderBox* spinRenderer = spinButton ? spinButton->renderBox() : 0) {
430 result += spinRenderer->borderLeft() + spinRenderer->borderRight() +
431 spinRenderer->paddingLeft() + spinRenderer->paddingRight();
432 // Since the width of spinRenderer is not calculated yet, spinRenderer->width() returns 0.
433 // So computedStyle()->width() is used instead.
434 result += spinButton->computedStyle()->width().value();
438 #if ENABLE(INPUT_SPEECH)
439 HTMLElement* speechButton = speechButtonElement();
440 if (RenderBox* speechRenderer = speechButton ? speechButton->renderBox() : 0) {
441 result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
442 speechRenderer->paddingLeft() + speechRenderer->paddingRight();
448 void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(LayoutUnit lineHeight)
450 HTMLElement* resultsButton = resultsButtonElement();
451 if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0) {
452 resultsRenderer->computeLogicalHeight();
453 setHeight(max(height(),
454 resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
455 resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
456 resultsRenderer->marginTop() + resultsRenderer->marginBottom()));
457 lineHeight = max(lineHeight, resultsRenderer->height());
459 HTMLElement* cancelButton = cancelButtonElement();
460 if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0) {
461 cancelRenderer->computeLogicalHeight();
462 setHeight(max(height(),
463 cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
464 cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
465 cancelRenderer->marginTop() + cancelRenderer->marginBottom()));
466 lineHeight = max(lineHeight, cancelRenderer->height());
469 setHeight(height() + lineHeight);
472 void RenderTextControlSingleLine::updateFromElement()
474 RenderTextControl::updateFromElement();
476 if (cancelButtonElement())
477 updateCancelButtonVisibility();
479 if (m_searchPopupIsVisible)
480 m_searchPopup->popupMenu()->updateFromElement();
483 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
485 RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
486 textBlockStyle->inheritFrom(startStyle);
487 adjustInnerTextStyle(startStyle, textBlockStyle.get());
489 textBlockStyle->setWhiteSpace(PRE);
490 textBlockStyle->setWordWrap(NormalWordWrap);
491 textBlockStyle->setOverflowX(OHIDDEN);
492 textBlockStyle->setOverflowY(OHIDDEN);
494 if (m_desiredInnerTextHeight >= 0)
495 textBlockStyle->setHeight(Length(m_desiredInnerTextHeight, Fixed));
496 // Do not allow line-height to be smaller than our default.
497 if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
498 textBlockStyle->setLineHeight(Length(-100.0f, Percent));
500 textBlockStyle->setDisplay(BLOCK);
502 // We're adding one extra pixel of padding to match WinIE.
503 textBlockStyle->setPaddingLeft(Length(1, Fixed));
504 textBlockStyle->setPaddingRight(Length(1, Fixed));
506 return textBlockStyle.release();
509 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
511 RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
512 innerBlockStyle->inheritFrom(startStyle);
514 innerBlockStyle->setBoxFlex(1);
515 innerBlockStyle->setDisplay(BLOCK);
516 innerBlockStyle->setDirection(LTR);
518 // 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.
519 innerBlockStyle->setUserModify(READ_ONLY);
521 return innerBlockStyle.release();
524 void RenderTextControlSingleLine::updateCancelButtonVisibility() const
526 RenderObject* cancelButtonRenderer = cancelButtonElement()->renderer();
527 if (!cancelButtonRenderer)
530 const RenderStyle* curStyle = cancelButtonRenderer->style();
531 EVisibility buttonVisibility = visibilityForCancelButton();
532 if (curStyle->visibility() == buttonVisibility)
535 RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle);
536 cancelButtonStyle->setVisibility(buttonVisibility);
537 cancelButtonRenderer->setStyle(cancelButtonStyle);
540 EVisibility RenderTextControlSingleLine::visibilityForCancelButton() const
542 return (style()->visibility() == HIDDEN || inputElement()->value().isEmpty()) ? HIDDEN : VISIBLE;
545 const AtomicString& RenderTextControlSingleLine::autosaveName() const
547 return static_cast<Element*>(node())->getAttribute(autosaveAttr);
550 // PopupMenuClient methods
551 void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents)
553 ASSERT(static_cast<int>(listIndex) < listSize());
554 HTMLInputElement* input = inputElement();
555 if (static_cast<int>(listIndex) == (listSize() - 1)) {
557 m_recentSearches.clear();
558 const AtomicString& name = autosaveName();
559 if (!name.isEmpty()) {
561 m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
562 m_searchPopup->saveRecentSearches(name, m_recentSearches);
566 input->setValue(itemText(listIndex));
573 String RenderTextControlSingleLine::itemText(unsigned listIndex) const
575 int size = listSize();
578 return searchMenuNoRecentSearchesText();
581 return searchMenuRecentSearchesText();
582 if (itemIsSeparator(listIndex))
584 if (static_cast<int>(listIndex) == (size - 1))
585 return searchMenuClearRecentSearchesText();
586 return m_recentSearches[listIndex - 1];
589 String RenderTextControlSingleLine::itemLabel(unsigned) const
594 String RenderTextControlSingleLine::itemIcon(unsigned) const
599 bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const
601 if (!listIndex || itemIsSeparator(listIndex))
606 PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
611 PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
613 return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction(), style()->unicodeBidi() == Override);
616 int RenderTextControlSingleLine::clientInsetLeft() const
618 // Inset the menu by the radius of the cap on the left so that
619 // it only runs along the straight part of the bezel.
623 int RenderTextControlSingleLine::clientInsetRight() const
625 // Inset the menu by the radius of the cap on the right so that
626 // it only runs along the straight part of the bezel (unless it needs
631 int RenderTextControlSingleLine::clientPaddingLeft() const
633 int padding = paddingLeft();
635 HTMLElement* resultsButton = resultsButtonElement();
636 if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0)
637 padding += resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->paddingLeft() + resultsRenderer->marginRight() + resultsRenderer->paddingRight();
642 int RenderTextControlSingleLine::clientPaddingRight() const
644 int padding = paddingRight();
646 HTMLElement* cancelButton = cancelButtonElement();
647 if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0)
648 padding += cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->paddingLeft() + cancelRenderer->marginRight() + cancelRenderer->paddingRight();
653 int RenderTextControlSingleLine::listSize() const
655 // If there are no recent searches, then our menu will have 1 "No recent searches" item.
656 if (!m_recentSearches.size())
658 // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
659 return m_recentSearches.size() + 3;
662 int RenderTextControlSingleLine::selectedIndex() const
667 void RenderTextControlSingleLine::popupDidHide()
669 m_searchPopupIsVisible = false;
672 bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const
674 // The separator will be the second to last item in our list.
675 return static_cast<int>(listIndex) == (listSize() - 2);
678 bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const
680 return listIndex == 0;
683 bool RenderTextControlSingleLine::itemIsSelected(unsigned) const
688 void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
690 inputElement()->setValue(itemText(listIndex));
693 FontSelector* RenderTextControlSingleLine::fontSelector() const
695 return document()->styleSelector()->fontSelector();
698 HostWindow* RenderTextControlSingleLine::hostWindow() const
700 return document()->view()->hostWindow();
703 void RenderTextControlSingleLine::autoscroll()
705 RenderLayer* layer = innerTextElement()->renderBox()->layer();
710 LayoutUnit RenderTextControlSingleLine::scrollWidth() const
712 if (innerTextElement())
713 return innerTextElement()->scrollWidth();
714 return RenderBlock::scrollWidth();
717 LayoutUnit RenderTextControlSingleLine::scrollHeight() const
719 if (innerTextElement())
720 return innerTextElement()->scrollHeight();
721 return RenderBlock::scrollHeight();
724 LayoutUnit RenderTextControlSingleLine::scrollLeft() const
726 if (innerTextElement())
727 return innerTextElement()->scrollLeft();
728 return RenderBlock::scrollLeft();
731 LayoutUnit RenderTextControlSingleLine::scrollTop() const
733 if (innerTextElement())
734 return innerTextElement()->scrollTop();
735 return RenderBlock::scrollTop();
738 void RenderTextControlSingleLine::setScrollLeft(LayoutUnit newLeft)
740 if (innerTextElement())
741 innerTextElement()->setScrollLeft(newLeft);
744 void RenderTextControlSingleLine::setScrollTop(LayoutUnit newTop)
746 if (innerTextElement())
747 innerTextElement()->setScrollTop(newTop);
750 bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
752 RenderLayer* layer = innerTextElement()->renderBox()->layer();
753 if (layer && layer->scroll(direction, granularity, multiplier))
755 return RenderBlock::scroll(direction, granularity, multiplier, stopNode);
758 bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
760 RenderLayer* layer = innerTextElement()->renderBox()->layer();
761 if (layer && layer->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
763 return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode);
766 PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
768 RefPtr<Scrollbar> widget;
769 bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
770 if (hasCustomScrollbarStyle)
771 widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this);
773 widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
774 return widget.release();
777 HTMLInputElement* RenderTextControlSingleLine::inputElement() const
779 return node()->toInputElement();