OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / rendering / RenderTextControlSingleLine.cpp
index 29538ce..c5a47fb 100644 (file)
@@ -51,6 +51,23 @@ namespace WebCore {
 
 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)
@@ -164,9 +181,13 @@ void RenderTextControlSingleLine::hidePopup()
 
 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
@@ -174,7 +195,7 @@ void RenderTextControlSingleLine::subtreeHasChanged()
     // 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();
@@ -397,16 +418,12 @@ void RenderTextControlSingleLine::forwardEvent(Event* event)
 #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);
 }
@@ -432,6 +449,9 @@ void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const Ren
     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());
@@ -564,9 +584,6 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
         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() +
@@ -612,80 +629,59 @@ void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineH
 
 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();
@@ -702,7 +698,7 @@ void RenderTextControlSingleLine::updateFromElement()
             // 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());
         }
     }
 
@@ -727,7 +723,7 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const
     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);
@@ -751,7 +747,7 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const
     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.
@@ -946,7 +942,7 @@ PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
 
 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
@@ -969,7 +965,7 @@ int RenderTextControlSingleLine::clientPaddingLeft() 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;
 }
@@ -979,7 +975,7 @@ int RenderTextControlSingleLine::clientPaddingRight() const
     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;
 }
@@ -1098,20 +1094,20 @@ bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction
     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