2010-06-24 Satish Sampath <satish@chromium.org>
authorjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Jun 2010 10:40:28 +0000 (10:40 +0000)
committerjorlow@chromium.org <jorlow@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Jun 2010 10:40:28 +0000 (10:40 +0000)
        Reviewed by Kent Tamura.

        Add a speech button to input elements, no rendering or actions yet.

        Speech Input: Add a speech button to text input element (no rendering or actions yet)
        https://bugs.webkit.org/show_bug.cgi?id=40925

        No new tests. Will create a layout test in a subsequent patch.

        * css/CSSPrimitiveValueMappings.h:
        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
        * css/CSSSelector.cpp:
        (WebCore::CSSSelector::pseudoId):
        (WebCore::nameToPseudoTypeMap):
        (WebCore::CSSSelector::extractPseudoType):
        * css/CSSSelector.h:
        (WebCore::CSSSelector::):
        * css/CSSValueKeywords.in:
        * css/html.css:
        (input::-webkit-input-speech-button):
        * dom/InputElement.h:
        * html/HTMLAttributeNames.in:
        * html/HTMLInputElement.cpp:
        (WebCore::HTMLInputElement::isSpeechEnabled):
        * html/HTMLInputElement.h:
        * platform/ThemeTypes.h:
        (WebCore::):
        * rendering/RenderTextControlSingleLine.cpp:
        (WebCore::RenderTextControlSingleLine::nodeAtPoint):
        (WebCore::RenderTextControlSingleLine::forwardEvent):
        (WebCore::RenderTextControlSingleLine::styleDidChange):
        (WebCore::RenderTextControlSingleLine::hasControlClip):
        (WebCore::RenderTextControlSingleLine::controlClipRect):
        (WebCore::RenderTextControlSingleLine::textBlockWidth):
        (WebCore::RenderTextControlSingleLine::preferredContentWidth):
        (WebCore::RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight):
        (WebCore::RenderTextControlSingleLine::createSubtreeIfNeeded):
        (WebCore::RenderTextControlSingleLine::createSpeechButtonStyle):
        (WebCore::RenderTextControlSingleLine::clientPaddingRight):
        * rendering/RenderTextControlSingleLine.h:
        * rendering/RenderTheme.cpp:
        (WebCore::RenderTheme::adjustStyle):
        (WebCore::RenderTheme::paint):
        (WebCore::RenderTheme::paintBorderOnly):
        (WebCore::RenderTheme::paintDecorations):
        * rendering/TextControlInnerElements.cpp:
        (WebCore::InputFieldSpeechButtonElement::InputFieldSpeechButtonElement):
        (WebCore::InputFieldSpeechButtonElement::create):
        (WebCore::InputFieldSpeechButtonElement::defaultEventHandler):
        * rendering/TextControlInnerElements.h:
        * rendering/style/RenderStyleConstants.h:
        (WebCore::):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@61752 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
WebCore/ChangeLog
WebCore/css/CSSPrimitiveValueMappings.h
WebCore/css/CSSSelector.cpp
WebCore/css/CSSSelector.h
WebCore/css/CSSValueKeywords.in
WebCore/css/html.css
WebCore/dom/InputElement.h
WebCore/html/HTMLAttributeNames.in
WebCore/html/HTMLInputElement.cpp
WebCore/html/HTMLInputElement.h
WebCore/platform/ThemeTypes.h
WebCore/rendering/RenderTextControlSingleLine.cpp
WebCore/rendering/RenderTextControlSingleLine.h
WebCore/rendering/RenderTheme.cpp
WebCore/rendering/TextControlInnerElements.cpp
WebCore/rendering/TextControlInnerElements.h
WebCore/rendering/style/RenderStyleConstants.h

index 5073f79..81d0f7f 100644 (file)
@@ -1,3 +1,58 @@
+2010-06-24  Satish Sampath  <satish@chromium.org>
+
+        Reviewed by Kent Tamura.
+
+        Add a speech button to input elements, no rendering or actions yet.
+
+        Speech Input: Add a speech button to text input element (no rendering or actions yet)
+        https://bugs.webkit.org/show_bug.cgi?id=40925
+
+        No new tests. Will create a layout test in a subsequent patch.
+
+        * css/CSSPrimitiveValueMappings.h:
+        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::pseudoId):
+        (WebCore::nameToPseudoTypeMap):
+        (WebCore::CSSSelector::extractPseudoType):
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::):
+        * css/CSSValueKeywords.in:
+        * css/html.css:
+        (input::-webkit-input-speech-button):
+        * dom/InputElement.h:
+        * html/HTMLAttributeNames.in:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::isSpeechEnabled):
+        * html/HTMLInputElement.h:
+        * platform/ThemeTypes.h:
+        (WebCore::):
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::nodeAtPoint):
+        (WebCore::RenderTextControlSingleLine::forwardEvent):
+        (WebCore::RenderTextControlSingleLine::styleDidChange):
+        (WebCore::RenderTextControlSingleLine::hasControlClip):
+        (WebCore::RenderTextControlSingleLine::controlClipRect):
+        (WebCore::RenderTextControlSingleLine::textBlockWidth):
+        (WebCore::RenderTextControlSingleLine::preferredContentWidth):
+        (WebCore::RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight):
+        (WebCore::RenderTextControlSingleLine::createSubtreeIfNeeded):
+        (WebCore::RenderTextControlSingleLine::createSpeechButtonStyle):
+        (WebCore::RenderTextControlSingleLine::clientPaddingRight):
+        * rendering/RenderTextControlSingleLine.h:
+        * rendering/RenderTheme.cpp:
+        (WebCore::RenderTheme::adjustStyle):
+        (WebCore::RenderTheme::paint):
+        (WebCore::RenderTheme::paintBorderOnly):
+        (WebCore::RenderTheme::paintDecorations):
+        * rendering/TextControlInnerElements.cpp:
+        (WebCore::InputFieldSpeechButtonElement::InputFieldSpeechButtonElement):
+        (WebCore::InputFieldSpeechButtonElement::create):
+        (WebCore::InputFieldSpeechButtonElement::defaultEventHandler):
+        * rendering/TextControlInnerElements.h:
+        * rendering/style/RenderStyleConstants.h:
+        (WebCore::):
+
 2010-06-24  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Adam Barth.
index dd7b732..baa1ab8 100644 (file)
@@ -344,6 +344,11 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e)
         case CapsLockIndicatorPart:
             m_value.ident = CSSValueCapsLockIndicator;
             break;
+        case InputSpeechButtonPart:
+#if ENABLE(INPUT_SPEECH)
+            m_value.ident = CSSValueInputSpeechButton;
+#endif
+            break;
     }
 }
 
index 3ff9373..ddf1737 100644 (file)
@@ -5,6 +5,7 @@
  *               2001-2003 Dirk Mueller (mueller@kde.org)
  * Copyright (C) 2002, 2006, 2007, 2008 Apple Inc. All rights reserved.
  * Copyright (C) 2008 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -107,6 +108,10 @@ PseudoId CSSSelector::pseudoId(PseudoType type)
         return FILE_UPLOAD_BUTTON;
     case PseudoInputPlaceholder:
         return INPUT_PLACEHOLDER;
+#if ENABLE(INPUT_SPEECH)
+    case PseudoInputSpeechButton:
+        return INPUT_SPEECH_BUTTON;
+#endif
     case PseudoSliderThumb:
         return SLIDER_THUMB;
     case PseudoSearchCancelButton:
@@ -280,6 +285,9 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
     DEFINE_STATIC_LOCAL(AtomicString, before, ("before"));
     DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked"));
     DEFINE_STATIC_LOCAL(AtomicString, fileUploadButton, ("-webkit-file-upload-button"));
+#if ENABLE(INPUT_SPEECH)
+    DEFINE_STATIC_LOCAL(AtomicString, inputSpeechButton, ("-webkit-input-speech-button"));
+#endif
     DEFINE_STATIC_LOCAL(AtomicString, defaultString, ("default"));
     DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled"));
     DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only"));
@@ -390,6 +398,9 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
         nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore);
         nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked);
         nameToPseudoType->set(fileUploadButton.impl(), CSSSelector::PseudoFileUploadButton);
+#if ENABLE(INPUT_SPEECH)
+        nameToPseudoType->set(inputSpeechButton.impl(), CSSSelector::PseudoInputSpeechButton);
+#endif
         nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault);
         nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled);
         nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly);
@@ -519,6 +530,9 @@ void CSSSelector::extractPseudoType() const
     case PseudoFileUploadButton:
     case PseudoInputListButton:
     case PseudoInputPlaceholder:
+#if ENABLE(INPUT_SPEECH)
+    case PseudoInputSpeechButton:
+#endif
     case PseudoInnerSpinButton:
     case PseudoMediaControlsPanel:
     case PseudoMediaControlsMuteButton:
index f5b56ef..d55fafc 100644 (file)
@@ -196,6 +196,9 @@ namespace WebCore {
             PseudoMeterVerticalSuboptimal,
             PseudoMeterVerticalEvenLessGood,
             PseudoInputListButton,
+#if ENABLE(INPUT_SPEECH)
+            PseudoInputSpeechButton,
+#endif
             PseudoInnerSpinButton,
             PseudoOuterSpinButton,
             PseudoProgressBarValue,
index 13dd034..3439878 100644 (file)
@@ -566,6 +566,7 @@ button
 button-bevel
 default-button
 inner-spin-button
+input-speech-button
 list-button
 listbox
 listitem
index 1051659..dc27ff8 100644 (file)
@@ -372,6 +372,11 @@ input::-webkit-outer-spin-button {
     -webkit-user-select: none;
 }
 
+input::-webkit-input-speech-button {
+    -webkit-appearance: input-speech-button;
+    display: inline-block;
+}
+
 textarea {
     -webkit-appearance: textarea;
     background-color: white;
index d477046..1d6c356 100644 (file)
@@ -44,6 +44,9 @@ public:
     virtual bool isSearchField() const = 0;
     virtual bool isTextField() const = 0;
     virtual bool hasSpinButton() const { return false; }
+#if ENABLE(INPUT_SPEECH)
+    virtual bool isSpeechEnabled() const = 0;
+#endif    
 
     virtual bool searchEventsShouldBeDispatched() const = 0;
 
index 60d5d73..b45ba9e 100644 (file)
@@ -255,6 +255,7 @@ size
 sortable
 sortdirection
 span
+speech
 spellcheck
 src
 standby
index 55944bc..aef6db2 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
+ * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -2816,6 +2817,20 @@ void HTMLInputElement::setWapInputFormat(String& mask)
 }
 #endif
 
-
+#if ENABLE(INPUT_SPEECH)
+bool HTMLInputElement::isSpeechEnabled() const
+{
+    switch (inputType()) {
+    // FIXME: Add support for RANGE, EMAIL, URL, COLOR and DATE/TIME input types.
+    case TEXT:
+    case PASSWORD:
+    case SEARCH:
+    case NUMBER:
+    case TELEPHONE:
+        return hasAttribute(speechAttr);
+    }
+    return false;
+}
+#endif
 
 } // namespace
index fdf06db..5bcf01f 100644 (file)
@@ -105,6 +105,9 @@ public:
     bool isNumberField() const { return m_type == NUMBER; }
     bool isEmailField() const { return m_type == EMAIL; }
     bool isUrlField() const { return m_type == URL; }
+#if ENABLE(INPUT_SPEECH)
+    virtual bool isSpeechEnabled() const;
+#endif    
 
     bool checked() const { return m_checked; }
     void setChecked(bool, bool sendChangeEvent = false);
index 7314fba..271bd83 100644 (file)
@@ -47,7 +47,7 @@ typedef unsigned ControlStates;
 // Must follow CSSValueKeywords.in order
 enum ControlPart {
     NoControlPart, CheckboxPart, RadioPart, PushButtonPart, SquareButtonPart, ButtonPart,
-    ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, ListButtonPart, ListboxPart, ListItemPart,
+    ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, InputSpeechButtonPart, ListButtonPart, ListboxPart, ListItemPart,
     MediaFullscreenButtonPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart, 
     MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart,
     MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart,
index 2dbfb9f..da3283c 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
  *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -288,9 +289,13 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
     // If we found a spin button, we're done.
     if (m_outerSpinButton && result.innerNode() == m_outerSpinButton)
         return true;
-    // If we're not a search field, or we already found the results or cancel buttons, we're done.
+    // If we're not a search field, or we already found the speech, results or cancel buttons, we're done.
     if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton)
         return true;
+#if ENABLE(INPUT_SPEECH)
+    if (m_innerBlock && m_speechButton && result.innerNode() == m_speechButton)
+        return true;
+#endif
 
     Node* innerNode = 0;
     RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
@@ -303,6 +308,19 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
     if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)
         innerNode = m_resultsButton.get();
 
+#if ENABLE(INPUT_SPEECH)
+    if (!innerNode && m_speechButton && m_speechButton->renderer()) {
+        int buttonLeft = textLeft + innerTextRenderer->width();
+        if (m_cancelButton) {
+            RenderBox* cancelRenderer = m_cancelButton->renderBox();
+            cancelRenderer->calcWidth();
+            buttonLeft += cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
+        }
+        if (xPos > buttonLeft)
+            innerNode = m_speechButton.get();
+    }
+#endif
+
     if (!innerNode) {
         int textRight = textLeft + innerTextRenderer->width();
         if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)
@@ -339,8 +357,20 @@ void RenderTextControlSingleLine::forwardEvent(Event* event)
 
     FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
     int textRight = innerTextRenderer->borderBoxRect().right();
+#if ENABLE(INPUT_SPEECH)
+    int cancelRight = textRight;
+    if (m_cancelButton && m_cancelButton->renderBox()) {
+        RenderBox* cancelRenderer = m_cancelButton->renderBox();
+        cancelRight += cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
+    }
+#endif
+
     if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())
         m_resultsButton->defaultEventHandler(event);
+#if ENABLE(INPUT_SPEECH)
+    else if (m_speechButton && localPoint.x() > cancelRight)
+        m_speechButton->defaultEventHandler(event);
+#endif
     else if (m_cancelButton && localPoint.x() > textRight)
         m_cancelButton->defaultEventHandler(event);
     else if (m_outerSpinButton && localPoint.x() > textRight)
@@ -370,6 +400,11 @@ void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const Ren
     if (RenderObject* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderer() : 0)
         spinRenderer->setStyle(createOuterSpinButtonStyle());
 
+#if ENABLE(INPUT_SPEECH)
+    if (RenderObject* speechRenderer = m_speechButton ? m_speechButton->renderer() : 0)
+        speechRenderer->setStyle(createSpeechButtonStyle(style()));
+#endif
+
     setHasOverflowClip(false);
 }
 
@@ -397,9 +432,19 @@ void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
     }
 }
 
+bool RenderTextControlSingleLine::hasControlClip() const
+{
+    bool clip = m_cancelButton;
+#if ENABLE(INPUT_SPEECH)
+    if (m_speechButton)
+        clip = true;
+#endif
+    return clip;
+}
+
 IntRect RenderTextControlSingleLine::controlClipRect(int tx, int ty) const
 {
-    // This should only get called for search inputs.
+    // This should only get called for search & speech inputs.
     ASSERT(hasControlClip());
 
     IntRect clipRect = IntRect(m_innerBlock->renderBox()->frameRect());
@@ -421,6 +466,13 @@ int RenderTextControlSingleLine::textBlockWidth() const
         width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
     }
 
+#if ENABLE(INPUT_SPEECH)
+    if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
+        speechRenderer->calcWidth();
+        width -= speechRenderer->width() + speechRenderer->marginLeft() + speechRenderer->marginRight();
+    }
+#endif
+
     return width - decorationWidthRight();
 }
 
@@ -479,6 +531,12 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
         result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
                   cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
 
+#if ENABLE(INPUT_SPEECH)
+    if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
+        result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
+                  speechRenderer->paddingLeft() + speechRenderer->paddingRight();
+    }
+#endif
     return result;
 }
 
@@ -514,12 +572,28 @@ void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineH
         lineHeight = max(lineHeight, cancelRenderer->height());
     }
 
+#if ENABLE(INPUT_SPEECH)
+    if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
+        toRenderBlock(speechRenderer)->calcHeight();
+        setHeight(max(height(),
+                  speechRenderer->borderTop() + speechRenderer->borderBottom() +
+                  speechRenderer->paddingTop() + speechRenderer->paddingBottom() +
+                  speechRenderer->marginTop() + speechRenderer->marginBottom()));
+        lineHeight = max(lineHeight, speechRenderer->height());
+    }
+#endif
+
     setHeight(height() + lineHeight);
 }
 
 void RenderTextControlSingleLine::createSubtreeIfNeeded()
 {
-    if (!inputElement()->isSearchField()) {
+    bool createSubtree = inputElement()->isSearchField();
+#if ENABLE(INPUT_SPEECH)
+    if (inputElement()->isSpeechEnabled())
+        createSubtree = true;
+#endif
+    if (!createSubtree) {
         RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
         if (inputElement()->hasSpinButton() && !m_outerSpinButton) {
             m_outerSpinButton = SpinButtonElement::create(node());
@@ -534,20 +608,31 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded()
         m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
     }
 
-    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());
+    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 cancel button
+    // Create innerText element before adding the other buttons.
     RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
 
-    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());
+    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());
+        }
     }
+#if ENABLE(INPUT_SPEECH)
+    if (inputElement()->isSpeechEnabled() && !m_speechButton) {
+        // Create the speech button element.
+        m_speechButton = InputFieldSpeechButtonElement::create(document());
+        m_speechButton->attachInnerElement(m_innerBlock.get(), createSpeechButtonStyle(m_innerBlock->renderer()->style()), renderArena());
+    }
+#endif
 }
 
 void RenderTextControlSingleLine::updateFromElement()
@@ -685,6 +770,19 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createOuterSpinButtonStyle(
     return buttonStyle.release();
 }
 
+#if ENABLE(INPUT_SPEECH)
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createSpeechButtonStyle(const RenderStyle* startStyle) const
+{
+    ASSERT(node()->isHTMLElement());
+    RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INPUT_SPEECH_BUTTON);
+    if (!buttonStyle)
+        buttonStyle = RenderStyle::create();
+    if (startStyle)
+        buttonStyle->inheritFrom(startStyle);
+    return buttonStyle.release();
+}
+#endif
+
 void RenderTextControlSingleLine::updateCancelButtonVisibility() const
 {
     if (!m_cancelButton->renderer())
@@ -823,6 +921,10 @@ int RenderTextControlSingleLine::clientPaddingRight() const
 
     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
         padding += cancelRenderer->width();
+#if ENABLE(INPUT_SPEECH)
+    if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0)
+        padding += speechRenderer->width();
+#endif
 
     return padding;
 }
index dff9e5f..ab9f711 100644 (file)
@@ -29,6 +29,7 @@
 namespace WebCore {
 
 class InputElement;
+class InputFieldSpeechButtonElement;
 class SearchFieldCancelButtonElement;
 class SearchFieldResultsButtonElement;
 class SearchPopupMenu;
@@ -59,7 +60,7 @@ public:
 
 private:
     int preferredDecorationWidthRight() const;
-    virtual bool hasControlClip() const { return m_cancelButton; }
+    virtual bool hasControlClip() const;
     virtual IntRect controlClipRect(int tx, int ty) const;
     virtual bool isTextField() const { return true; }
 
@@ -98,6 +99,9 @@ private:
     PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle) const;
     PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle) const;
     PassRefPtr<RenderStyle> createOuterSpinButtonStyle() const;
+#if ENABLE(INPUT_SPEECH)
+    PassRefPtr<RenderStyle> createSpeechButtonStyle(const RenderStyle* startStyle) const;
+#endif
 
     void updateCancelButtonVisibility() const;
     EVisibility visibilityForCancelButton() const;
@@ -142,6 +146,9 @@ private:
     RefPtr<SearchFieldResultsButtonElement> m_resultsButton;
     RefPtr<SearchFieldCancelButtonElement> m_cancelButton;
     RefPtr<TextControlInnerElement> m_outerSpinButton;
+#if ENABLE(INPUT_SPEECH)
+    RefPtr<InputFieldSpeechButtonElement> m_speechButton;
+#endif
 
     Timer<RenderTextControlSingleLine> m_searchEventTimer;
     RefPtr<SearchPopupMenu> m_searchPopup;
index 4f3289d..fbea519 100644 (file)
@@ -228,6 +228,10 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
         case RatingLevelIndicatorPart:
             return adjustMeterStyle(selector, style, e);
 #endif
+#if ENABLE(INPUT_SPEECH)
+        case InputSpeechButtonPart:
+            // FIXME: Adjust the speech button's style and sizes.
+#endif
         default:
             break;
     }
@@ -358,6 +362,10 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf
             return paintSearchFieldResultsDecoration(o, paintInfo, r);
         case SearchFieldResultsButtonPart:
             return paintSearchFieldResultsButton(o, paintInfo, r);
+#if ENABLE(INPUT_SPEECH)
+        case InputSpeechButtonPart:
+            // FIXME: Add painting code to draw the speech button.
+#endif
         default:
             break;
     }
@@ -406,6 +414,9 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo
         case SearchFieldDecorationPart:
         case SearchFieldResultsDecorationPart:
         case SearchFieldResultsButtonPart:
+#if ENABLE(INPUT_SPEECH)
+        case InputSpeechButtonPart:
+#endif
         default:
             break;
     }
@@ -452,6 +463,9 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf
         case SearchFieldDecorationPart:
         case SearchFieldResultsDecorationPart:
         case SearchFieldResultsButtonPart:
+#if ENABLE(INPUT_SPEECH)
+        case InputSpeechButtonPart:
+#endif
         default:
             break;
     }
index 06efb81..61c85e7 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -314,4 +315,26 @@ void SpinButtonElement::defaultEventHandler(Event* event)
         HTMLDivElement::defaultEventHandler(event);
 }
 
+// ----------------------------
+
+#if ENABLE(INPUT_SPEECH)
+
+inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Document* document)
+    : TextControlInnerElement(document)
+{
+}
+
+PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(Document* document)
+{
+    return adoptRef(new InputFieldSpeechButtonElement(document));
+}
+
+void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
+{
+    // FIXME: Start speech recognition here.
+    HTMLDivElement::defaultEventHandler(event);
+}
+
+#endif // ENABLE(INPUT_SPEECH)
+
 }
index ed1887e..1884a34 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -104,6 +105,20 @@ private:
     bool m_onUpButton;
 };
 
+#if ENABLE(INPUT_SPEECH)
+
+class InputFieldSpeechButtonElement : public TextControlInnerElement {
+public:
+    static PassRefPtr<InputFieldSpeechButtonElement> create(Document*);
+
+    virtual void defaultEventHandler(Event*);
+
+private:
+    InputFieldSpeechButtonElement(Document*);
+};
+
+#endif // ENABLE(INPUT_SPEECH)
+
 } // namespace
 
 #endif
index ebd6f3a..dd82433 100644 (file)
@@ -74,7 +74,7 @@ enum PseudoId {
     MEDIA_CONTROLS_SEEK_BACK_BUTTON, MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON, 
     MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON,
     MEDIA_CONTROLS_STATUS_DISPLAY, SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
-    INPUT_LIST_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK, PROGRESS_BAR_VALUE,
+    INPUT_LIST_BUTTON, INPUT_SPEECH_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK, PROGRESS_BAR_VALUE,
     METER_HORIZONTAL_BAR, METER_HORIZONTAL_OPTIMUM, METER_HORIZONTAL_SUBOPTIMAL, METER_HORIZONTAL_EVEN_LESS_GOOD,
     METER_VERTICAL_BAR, METER_VERTICAL_OPTIMUM, METER_VERTICAL_SUBOPTIMAL, METER_VERTICAL_EVEN_LESS_GOOD, 
     AFTER_LAST_INTERNAL_PSEUDOID,