using namespace HTMLNames;
+VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& point)
+{
+ IntPoint contentsPoint(point);
+
+ // Multiline text controls have the scroll on shadowAncestorNode, so we need to take that
+ // into account here.
+ if (m_multiLine) {
+ RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer());
+ if (renderer->hasOverflowClip())
+ contentsPoint += renderer->layer()->scrolledContentOffset();
+ }
+
+ return RenderBlock::positionForPoint(contentsPoint);
+}
+
+// ----------------------------
+
RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node, bool placeholderVisible)
: RenderTextControl(node, placeholderVisible)
, m_searchPopupIsVisible(false)
void RenderTextControlSingleLine::subtreeHasChanged()
{
- bool wasChanged = wasChangedSinceLastChangeEvent();
RenderTextControl::subtreeHasChanged();
+ ASSERT(node()->isElementNode());
+ Element* element = static_cast<Element*>(node());
+ bool wasChanged = element->wasChangedSinceLastFormControlChangeEvent();
+ element->setChangedSinceLastFormControlChangeEvent(true);
+
InputElement* input = inputElement();
// We don't need to call sanitizeUserInputValue() function here because
// InputElement::handleBeforeTextInsertedEvent() has already called
// sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
String value = text();
if (input->isAcceptableValue(value))
- input->setValueFromRenderer(input->sanitizeValue(value));
+ input->setValueFromRenderer(input->sanitizeValue(input->convertFromVisibleValue(value)));
if (node()->isHTMLElement()) {
// Recalc for :invalid and hasUnacceptableValue() change.
static_cast<HTMLInputElement*>(input)->setNeedsStyleRecalc();
#endif
FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
- int textRight = innerTextRenderer->borderBoxRect().right();
+ int textRight = innerTextRenderer->borderBoxRect().maxX();
if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())
m_resultsButton->defaultEventHandler(event);
else if (m_cancelButton && localPoint.x() > textRight)
m_cancelButton->defaultEventHandler(event);
- else if (m_innerSpinButton && localPoint.x() > textRight && m_innerSpinButton->renderBox() && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width())
- m_innerSpinButton->defaultEventHandler(event);
- else if (m_outerSpinButton && localPoint.x() > textRight)
- m_outerSpinButton->defaultEventHandler(event);
else
RenderTextControl::forwardEvent(event);
}
if (RenderObject* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderer() : 0)
spinRenderer->setStyle(createOuterSpinButtonStyle());
+ if (RenderObject* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderer() : 0)
+ spinRenderer->setStyle(createInnerSpinButtonStyle());
+
#if ENABLE(INPUT_SPEECH)
if (RenderObject* speechRenderer = m_speechButton ? m_speechButton->renderer() : 0)
speechRenderer->setStyle(createSpeechButtonStyle());
result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
- if (RenderBox* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0)
- result += spinRenderer->minPreferredLogicalWidth();
-
#if ENABLE(INPUT_SPEECH)
if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
void RenderTextControlSingleLine::createSubtreeIfNeeded()
{
- bool createSubtree = inputElement()->isSearchField();
- if (!createSubtree) {
- RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
+ if (inputElement()->isSearchField()) {
+ if (!m_innerBlock) {
+ // Create the inner block element
+ m_innerBlock = TextControlInnerElement::create(toHTMLElement(node()));
+ m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
+ }
+
#if ENABLE(INPUT_SPEECH)
if (inputElement()->isSpeechEnabled() && !m_speechButton) {
// Create the speech button element.
- m_speechButton = InputFieldSpeechButtonElement::create(static_cast<HTMLElement*>(node()));
+ m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
}
#endif
- bool hasSpinButton = inputElement()->hasSpinButton();
- if (hasSpinButton && !m_innerSpinButton) {
- m_innerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node()));
- m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena());
- }
- if (hasSpinButton && !m_outerSpinButton) {
- m_outerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node()));
- m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
- }
- return;
- }
- if (!m_innerBlock) {
- // Create the inner block element
- m_innerBlock = TextControlInnerElement::create(static_cast<HTMLElement*>(node()));
- m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
- }
-#if ENABLE(INPUT_SPEECH)
- if (inputElement()->isSpeechEnabled() && !m_speechButton) {
- // Create the speech button element.
- m_speechButton = InputFieldSpeechButtonElement::create(static_cast<HTMLElement*>(node()));
- m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
- }
-#endif
- if (inputElement()->hasSpinButton() && !m_outerSpinButton) {
- m_outerSpinButton = SpinButtonElement::create(static_cast<HTMLElement*>(node()));
- m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
- }
-
- if (inputElement()->isSearchField()) {
if (!m_resultsButton) {
// Create the search results button element.
m_resultsButton = SearchFieldResultsButtonElement::create(document());
m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
}
- }
- // Create innerText element before adding the other buttons.
- RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
+ // Create innerText element before adding the other buttons.
+ RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
- if (inputElement()->isSearchField()) {
if (!m_cancelButton) {
// Create the cancel button element.
m_cancelButton = SearchFieldCancelButtonElement::create(document());
m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
}
- }
-}
+ } else {
+ RenderTextControl::createSubtreeIfNeeded(0);
#if ENABLE(INPUT_SPEECH)
-void RenderTextControlSingleLine::speechAttributeChanged()
-{
- // The inner text element of this renderer has different styles depending on whether the
- // speech button is visible or not. So when the speech attribute changes, we reset the
- // whole thing and recreate to get the right styles and layout.
- if (m_speechButton)
- m_speechButton->detach();
- setChildrenInline(true);
- RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();
- setStyle(createInnerTextStyle(parentStyle));
- updateFromElement();
-}
+ if (inputElement()->isSpeechEnabled() && !m_speechButton) {
+ // Create the speech button element.
+ m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
+ m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
+ }
#endif
+ bool hasSpinButton = inputElement()->hasSpinButton();
+
+ if (hasSpinButton && !m_innerSpinButton) {
+ m_innerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
+ m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena());
+ }
+ if (hasSpinButton && !m_outerSpinButton) {
+ m_outerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
+ m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
+ }
+ }
+}
+
void RenderTextControlSingleLine::updateFromElement()
{
createSubtreeIfNeeded();
// flag is false. It protects an unacceptable renderer value from
// being overwritten with the DOM value.
if (!static_cast<HTMLInputElement*>(node())->formControlValueMatchesRenderer())
- setInnerTextValue(inputElement()->value());
+ setInnerTextValue(inputElement()->visibleValue());
}
}
textBlockStyle->setOverflowY(OHIDDEN);
// Do not allow line-height to be smaller than our default.
- if (textBlockStyle->font().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
+ if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
textBlockStyle->setLineHeight(Length(-100.0f, Percent));
WebCore::EDisplay display = (m_innerBlock || inputElement()->hasSpinButton() ? INLINE_BLOCK : BLOCK);
RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
innerBlockStyle->inheritFrom(startStyle);
- innerBlockStyle->setDisplay(inputElement()->hasSpinButton() ? INLINE_BLOCK : BLOCK);
+ innerBlockStyle->setDisplay(BLOCK);
innerBlockStyle->setDirection(LTR);
// 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.
PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
{
- return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction());
+ return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction(), style()->unicodeBidi() == Override);
}
int RenderTextControlSingleLine::clientInsetLeft() const
int padding = paddingLeft();
if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
- padding += resultsRenderer->width();
+ padding += resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->paddingLeft() + resultsRenderer->marginRight() + resultsRenderer->paddingRight();
return padding;
}
int padding = paddingRight();
if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
- padding += cancelRenderer->width();
+ padding += cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->paddingLeft() + cancelRenderer->marginRight() + cancelRenderer->paddingRight();
return padding;
}
return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode);
}
-PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
{
RefPtr<Scrollbar> widget;
bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle)
- widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
+ widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this);
else
- widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize);
+ widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
return widget.release();
}
InputElement* RenderTextControlSingleLine::inputElement() const
{
- return toInputElement(static_cast<Element*>(node()));
+ return node()->toInputElement();
}
int RenderTextControlSingleLine::textBlockInsetLeft() const