[BlackBerry] Upstream the datalist support UI
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Feb 2013 16:28:24 +0000 (16:28 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Feb 2013 16:28:24 +0000 (16:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=110736

Patch by Alberto Garcia <agarcia@igalia.com> on 2013-02-26
Reviewed by Rob Buis.

Original code by Otto Derek Cheung <otcheung@rim.com>

Source/WebCore:

* css/themeBlackBerry.css:
(input::-webkit-suggestion-dropdown-box):
(input::-webkit-suggestion-dropdown-box-item):
(input::-webkit-suggestion-prefix-text):
(input::-webkit-suggestion-dropdown-box-item-last):
* platform/blackberry/RenderThemeBlackBerry.cpp:
(WebCore::RenderThemeBlackBerry::supportsDataListUI):
(WebCore):
* platform/blackberry/RenderThemeBlackBerry.h:
(RenderThemeBlackBerry):

Source/WebKit:

* PlatformBlackBerry.cmake:

Source/WebKit/blackberry:

* WebCoreSupport/SuggestionBoxElement.cpp: Added.
(WebCore):
(WebCore::SuggestionBoxElement::SuggestionBoxElement):
(WebCore::SuggestionBoxElement::~SuggestionBoxElement):
(WebCore::SuggestionBoxElement::create):
(WebCore::SuggestionBoxElement::defaultEventHandler):
* WebCoreSupport/SuggestionBoxElement.h: Added.
(WebCore):
(SuggestionBoxElement):
* WebCoreSupport/SuggestionBoxHandler.cpp: Added.
(WebCore):
(WebCore::SuggestionBoxHandler::SuggestionBoxHandler):
(WebCore::SuggestionBoxHandler::~SuggestionBoxHandler):
(WebCore::SuggestionBoxHandler::create):
(WebCore::SuggestionBoxHandler::setInputElementAndUpdateDisplay):
(WebCore::SuggestionBoxHandler::showDropdownBox):
(WebCore::SuggestionBoxHandler::hideDropdownBox):
(WebCore::SuggestionBoxHandler::changeInputElementInnerTextValue):
(WebCore::SuggestionBoxHandler::parseSuggestions):
(WebCore::SuggestionBoxHandler::insertSuggestionsToDropdownBox):
(WebCore::adjustDropdownBoxPosition):
(WebCore::SuggestionBoxHandler::buildDropdownBoxTree):
* WebCoreSupport/SuggestionBoxHandler.h: Added.
(WebCore):
(SuggestionBoxHandler):
(WebCore::SuggestionBoxHandler::focusedElement):
* WebKitSupport/InputHandler.cpp:
(BlackBerry::WebKit::InputHandler::setElementUnfocused):
(BlackBerry::WebKit::InputHandler::updateFormState):
* WebKitSupport/InputHandler.h:
(WebCore):
(InputHandler):
* WebKitSupport/TouchEventHandler.cpp:
(BlackBerry::WebKit::TouchEventHandler::handleTouchPoint):

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

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/css/themeBlackBerry.css
Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp
Source/WebCore/platform/blackberry/RenderThemeBlackBerry.h
Source/WebKit/ChangeLog
Source/WebKit/PlatformBlackBerry.cmake
Source/WebKit/blackberry/ChangeLog
Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.cpp [new file with mode: 0644]
Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.h [new file with mode: 0644]
Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.cpp [new file with mode: 0644]
Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.h [new file with mode: 0644]
Source/WebKit/blackberry/WebKitSupport/InputHandler.cpp
Source/WebKit/blackberry/WebKitSupport/InputHandler.h
Source/WebKit/blackberry/WebKitSupport/TouchEventHandler.cpp

index dd46f1d..a72c279 100644 (file)
@@ -1,3 +1,23 @@
+2013-02-26  Alberto Garcia  <agarcia@igalia.com>
+
+        [BlackBerry] Upstream the datalist support UI
+        https://bugs.webkit.org/show_bug.cgi?id=110736
+
+        Reviewed by Rob Buis.
+
+        Original code by Otto Derek Cheung <otcheung@rim.com>
+
+        * css/themeBlackBerry.css:
+        (input::-webkit-suggestion-dropdown-box):
+        (input::-webkit-suggestion-dropdown-box-item):
+        (input::-webkit-suggestion-prefix-text):
+        (input::-webkit-suggestion-dropdown-box-item-last):
+        * platform/blackberry/RenderThemeBlackBerry.cpp:
+        (WebCore::RenderThemeBlackBerry::supportsDataListUI):
+        (WebCore):
+        * platform/blackberry/RenderThemeBlackBerry.h:
+        (RenderThemeBlackBerry):
+
 2013-02-26  Andrey Kosyakov  <caseq@chromium.org>
 
         Web Inspector: plumb trace events to Timeline agent
index 2fcadc0..8ce6643 100644 (file)
@@ -62,6 +62,49 @@ select[size="1"] {
     font-weight: normal;
 }
 
+
+/* Suggestion Box */
+
+input::-webkit-suggestion-dropdown-box {
+    position: absolute;
+    z-index: 2147483647;
+    opacity: 0.98;
+    max-height: 200px;
+    overflow-y: scroll;
+    overflow-x: hidden;
+    border: 1px solid #e0e0e0;
+    border-top: none;
+    background-color: #fcfcfc;
+    -webkit-box-shadow: 0px 5px 5px -2px #606060 inset;
+    -webkit-box-shadow: 2px 0px 8px -5px #AEAEAE;
+}
+
+input::-webkit-suggestion-dropdown-box-item {
+    display: block;
+    width: 100%;
+    padding: 10px 5px;
+    color: #363636;
+    text-decoration: none;
+    border-bottom: 1px solid #e8e8e8;
+    text-overflow: -blackberry-fade;
+    overflow: hidden;
+}
+
+input::-webkit-suggestion-prefix-text {
+    font-weight: bold;
+}
+
+input::-webkit-suggestion-dropdown-box-item-last {
+    display: block;
+    width: 100%;
+    padding: 10px 5px;
+    color: #363636;
+    text-decoration: none;
+    text-overflow: -blackberry-fade;
+    overflow: hidden;
+    border-bottom: none;
+}
+
 input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="time"], input[type="month"] {
     font-family: "Slate Pro";
     -webkit-appearance: button;
index c7525db..239d6af 100644 (file)
@@ -1267,4 +1267,10 @@ Color RenderThemeBlackBerry::platformInactiveTextSearchHighlightColor() const
     return Color(255, 255, 0); // Yellow.
 }
 
+bool RenderThemeBlackBerry::supportsDataListUI(const AtomicString& type) const
+{
+    // TODO: support other input types in the future.
+    return type == InputTypeNames::text();
+}
+
 } // namespace WebCore
index 1eeb55b..bda6208 100644 (file)
@@ -96,6 +96,8 @@ public:
     virtual Color platformActiveTextSearchHighlightColor() const;
     virtual Color platformInactiveTextSearchHighlightColor() const;
 
+    virtual bool supportsDataListUI(const AtomicString&) const;
+
 private:
     static const String& defaultGUIFont();
 
index 8633e04..a0f3fa8 100644 (file)
@@ -1,3 +1,14 @@
+2013-02-26  Alberto Garcia  <agarcia@igalia.com>
+
+        [BlackBerry] Upstream the datalist support UI
+        https://bugs.webkit.org/show_bug.cgi?id=110736
+
+        Reviewed by Rob Buis.
+
+        Original code by Otto Derek Cheung <otcheung@rim.com>
+
+        * PlatformBlackBerry.cmake:
+
 2013-02-25  Roger Fong  <roger_fong@apple.com>
 
         Unreviewed. VS2010 solution build fix.
index af8d141..11f9d8f 100644 (file)
@@ -118,6 +118,8 @@ list(APPEND WebKit_SOURCES
     blackberry/WebCoreSupport/PagePopupBlackBerry.cpp
     blackberry/WebCoreSupport/NavigatorContentUtilsClientBlackBerry.cpp
     blackberry/WebCoreSupport/SelectPopupClient.cpp
+    blackberry/WebCoreSupport/SuggestionBoxHandler.cpp
+    blackberry/WebCoreSupport/SuggestionBoxElement.cpp
     blackberry/WebCoreSupport/VibrationClientBlackBerry.cpp
     blackberry/WebCoreSupport/DatePickerClient.cpp
     blackberry/WebCoreSupport/ColorPickerClient.cpp
index 9f38274..cbae054 100644 (file)
@@ -1,3 +1,47 @@
+2013-02-26  Alberto Garcia  <agarcia@igalia.com>
+
+        [BlackBerry] Upstream the datalist support UI
+        https://bugs.webkit.org/show_bug.cgi?id=110736
+
+        Reviewed by Rob Buis.
+
+        Original code by Otto Derek Cheung <otcheung@rim.com>
+
+        * WebCoreSupport/SuggestionBoxElement.cpp: Added.
+        (WebCore):
+        (WebCore::SuggestionBoxElement::SuggestionBoxElement):
+        (WebCore::SuggestionBoxElement::~SuggestionBoxElement):
+        (WebCore::SuggestionBoxElement::create):
+        (WebCore::SuggestionBoxElement::defaultEventHandler):
+        * WebCoreSupport/SuggestionBoxElement.h: Added.
+        (WebCore):
+        (SuggestionBoxElement):
+        * WebCoreSupport/SuggestionBoxHandler.cpp: Added.
+        (WebCore):
+        (WebCore::SuggestionBoxHandler::SuggestionBoxHandler):
+        (WebCore::SuggestionBoxHandler::~SuggestionBoxHandler):
+        (WebCore::SuggestionBoxHandler::create):
+        (WebCore::SuggestionBoxHandler::setInputElementAndUpdateDisplay):
+        (WebCore::SuggestionBoxHandler::showDropdownBox):
+        (WebCore::SuggestionBoxHandler::hideDropdownBox):
+        (WebCore::SuggestionBoxHandler::changeInputElementInnerTextValue):
+        (WebCore::SuggestionBoxHandler::parseSuggestions):
+        (WebCore::SuggestionBoxHandler::insertSuggestionsToDropdownBox):
+        (WebCore::adjustDropdownBoxPosition):
+        (WebCore::SuggestionBoxHandler::buildDropdownBoxTree):
+        * WebCoreSupport/SuggestionBoxHandler.h: Added.
+        (WebCore):
+        (SuggestionBoxHandler):
+        (WebCore::SuggestionBoxHandler::focusedElement):
+        * WebKitSupport/InputHandler.cpp:
+        (BlackBerry::WebKit::InputHandler::setElementUnfocused):
+        (BlackBerry::WebKit::InputHandler::updateFormState):
+        * WebKitSupport/InputHandler.h:
+        (WebCore):
+        (InputHandler):
+        * WebKitSupport/TouchEventHandler.cpp:
+        (BlackBerry::WebKit::TouchEventHandler::handleTouchPoint):
+
 2013-02-25  Yongxin Dai  <yodai@rim.com>
 
         [BlackBerry] Add isInputMode() method to WebPage class.
diff --git a/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.cpp b/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.cpp
new file mode 100644 (file)
index 0000000..453f211
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "config.h"
+#include "SuggestionBoxElement.h"
+
+#include "Frame.h"
+#include "HTMLNames.h"
+#include "MouseEvent.h"
+#include "SuggestionBoxHandler.h"
+#include "TouchEvent.h"
+
+namespace WebCore {
+
+SuggestionBoxElement::SuggestionBoxElement(SuggestionBoxHandler* element, String& value, const QualifiedName& name, Document* document)
+    : HTMLDivElement(name, document)
+    , m_suggestionBox(element)
+    , m_value(value)
+{
+}
+
+SuggestionBoxElement::~SuggestionBoxElement()
+{
+}
+
+PassRefPtr<SuggestionBoxElement> SuggestionBoxElement::create(SuggestionBoxHandler* element, String& value, Document* document)
+{
+    return adoptRef(new SuggestionBoxElement(element, value, HTMLNames::divTag, document));
+}
+
+void SuggestionBoxElement::defaultEventHandler(Event* event)
+{
+    if (event->isMouseEvent()) {
+        // Capture a mouse down event with left click and set the parent input element to the node's text
+        if (event->type() == eventNames().mousedownEvent && static_cast<MouseEvent*>(event)->button() != RightButton && document()->frame()) {
+            m_suggestionBox->changeInputElementInnerTextValue(m_value);
+            m_suggestionBox->hideDropdownBox();
+        }
+    }
+}
+
+} /* namespace WebCore */
diff --git a/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.h b/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxElement.h
new file mode 100644 (file)
index 0000000..25edf1a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef SuggestionBoxElement_h
+#define SuggestionBoxElement_h
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class SuggestionBoxHandler;
+class Event;
+
+class SuggestionBoxElement : public HTMLDivElement {
+public:
+    static PassRefPtr<SuggestionBoxElement> create(SuggestionBoxHandler*, String&, Document*);
+    virtual ~SuggestionBoxElement();
+
+private:
+    SuggestionBoxElement(SuggestionBoxHandler*, String&, const QualifiedName&, Document*);
+
+    virtual void defaultEventHandler(Event*);
+
+    SuggestionBoxHandler* m_suggestionBox;
+    String m_value;
+};
+
+} /* namespace WebCore */
+#endif /* SuggestionBoxElement_h */
diff --git a/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.cpp b/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.cpp
new file mode 100644 (file)
index 0000000..a88f300
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SuggestionBoxHandler.h"
+
+#include "CSSPropertyNames.h"
+#include "CSSValueKeywords.h"
+#include "DOMTokenList.h"
+#include "ElementShadow.h"
+#include "ExceptionCodePlaceholder.h"
+#include "HTMLCollection.h"
+#include "HTMLDataListElement.h"
+#include "HTMLDivElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLSpanElement.h"
+#include "RenderBlock.h"
+#include "RenderObject.h"
+#include "ShadowRoot.h"
+#include "StyleResolver.h"
+#include "SuggestionBoxElement.h"
+#include "Text.h"
+
+#include <BlackBerryPlatformLog.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+SuggestionBoxHandler::SuggestionBoxHandler(HTMLInputElement* element)
+    : m_inputElement(element)
+{
+}
+
+SuggestionBoxHandler::~SuggestionBoxHandler()
+{
+    hideDropdownBox();
+}
+
+PassOwnPtr<SuggestionBoxHandler> SuggestionBoxHandler::create(HTMLInputElement* element)
+{
+    return adoptPtr(new SuggestionBoxHandler(element));
+}
+
+void SuggestionBoxHandler::setInputElementAndUpdateDisplay(HTMLInputElement* element, bool allowEmptyPrefix)
+{
+    hideDropdownBox();
+    m_inputElement = element;
+    showDropdownBox(allowEmptyPrefix);
+}
+
+void SuggestionBoxHandler::showDropdownBox(bool allowEmptyPrefix)
+{
+    // Clearing suggestions and parse again
+    m_suggestions.clear();
+    parseSuggestions(allowEmptyPrefix);
+
+    // Don't bother building the tree if suggestion size is 0.
+    // We need to call insertSuggestions to clear previous suggestions
+    // in the DOM if suggestion size is 0.
+    if (!m_dropdownBox) {
+        if (!m_suggestions.size())
+            return;
+        buildDropdownBoxTree();
+    }
+
+    insertSuggestionsToDropdownBox();
+}
+
+void SuggestionBoxHandler::hideDropdownBox()
+{
+    if (m_dropdownBox) {
+        if (ShadowRoot* shadowRoot = m_inputElement->userAgentShadowRoot()) {
+            ExceptionCode ec;
+            shadowRoot->removeChild(m_dropdownBox.get(), ec);
+        }
+        m_dropdownBox = 0;
+    }
+    m_suggestions.clear();
+}
+
+void SuggestionBoxHandler::changeInputElementInnerTextValue(String& text)
+{
+    m_inputElement->setInnerTextValue(text);
+}
+
+void SuggestionBoxHandler::parseSuggestions(bool allowEmptyPrefix)
+{
+    // Return if this handler doesn't have an input element to attach to
+    if (!m_inputElement)
+        return;
+
+    // List attribute exists, check if datalist exists.
+    HTMLDataListElement* dList = m_inputElement->dataList();
+    if (!dList)
+        return;
+
+    RefPtr<HTMLCollection> optionsList = dList->options();
+    String prefix = m_inputElement->innerTextValue();
+
+    // Exit if:
+    // 1) If length of nodes in datalist is empty, return.
+    // 2) If we do not allow empty prefixes and prefix is null
+    if (!optionsList->length() || (!allowEmptyPrefix && prefix.isEmpty())) {
+        hideDropdownBox();
+        return;
+    }
+
+    // Prefix match the inner text value of the input against the candidate suggestions.
+    // Make sure the length of the suggestion is smaller than max length
+    for (unsigned i = 0; i < optionsList->length(); i++) {
+        HTMLOptionElement* target = toHTMLOptionElement((optionsList->item(i)));
+        if (!m_inputElement->isValidValue(target->value()))
+            continue;
+        String candidateString = m_inputElement->sanitizeValue(target->value());
+        if (!candidateString.findIgnoringCase(prefix) && candidateString.length() <= (unsigned) m_inputElement->maxLength())
+            m_suggestions.append(candidateString);
+    }
+}
+
+void SuggestionBoxHandler::insertSuggestionsToDropdownBox()
+{
+    // In case someone is calling this function without successfully building the dropdownBox tree
+    ASSERT(m_dropdownBox);
+
+    Document* document = m_dropdownBox->document();
+
+    // Clear the dropdown box's previous values
+    m_dropdownBox->removeChildren();
+
+    int prefixIndex = m_inputElement->innerTextValue().length();
+
+    unsigned total = m_suggestions.size();
+    for (unsigned i = 0; i < total; ++i) {
+        RefPtr<HTMLElement> suggestionItem = SuggestionBoxElement::create(this, m_suggestions[i], document);
+        if (i < total - 1)
+            suggestionItem->setPseudo("-webkit-suggestion-dropdown-box-item");
+        else
+            suggestionItem->setPseudo("-webkit-suggestion-dropdown-box-item-last");
+
+        // Append the part where it prefix matched
+        RefPtr<HTMLSpanElement> prefixElement = HTMLSpanElement::create(HTMLNames::spanTag, document);
+        prefixElement->appendChild(Text::create(document, m_suggestions[i].substring(0, prefixIndex)));
+        prefixElement->setPseudo("-webkit-suggestion-prefix-text");
+        suggestionItem->appendChild(prefixElement.release(), ASSERT_NO_EXCEPTION);
+
+        // Append the rest of the text in the suggestion item
+        suggestionItem->appendChild(Text::create(document, m_suggestions[i].substring(prefixIndex)), ASSERT_NO_EXCEPTION);
+        m_dropdownBox->appendChild(suggestionItem.release(), ASSERT_NO_EXCEPTION);
+    }
+}
+
+static void adjustDropdownBoxPosition(const LayoutRect& hostRect, HTMLElement* dropdownBox)
+{
+    // FIXME: reverse positioning and scroll
+    ASSERT(dropdownBox);
+    if (hostRect.isEmpty())
+        return;
+    double hostX = hostRect.x();
+    double hostY = hostRect.y();
+    if (RenderObject* renderer = dropdownBox->renderer()) {
+        if (RenderBox* container = renderer->containingBlock()) {
+            FloatPoint containerLocation = container->localToAbsolute();
+            hostX -= containerLocation.x() + container->borderLeft();
+            hostY -= containerLocation.y() + container->borderTop();
+        }
+    }
+
+    dropdownBox->setInlineStyleProperty(CSSPropertyTop, hostY + hostRect.height(), CSSPrimitiveValue::CSS_PX);
+    // The 'left' value of ::-webkit-validation-bubble-arrow.
+    const int bubbleArrowTopOffset = 32;
+    double bubbleX = hostX;
+    if (hostRect.width() / 2 < bubbleArrowTopOffset)
+        bubbleX = max(hostX + hostRect.width() / 2 - bubbleArrowTopOffset, 0.0);
+    dropdownBox->setInlineStyleProperty(CSSPropertyLeft, bubbleX, CSSPrimitiveValue::CSS_PX);
+}
+
+void SuggestionBoxHandler::buildDropdownBoxTree()
+{
+    ShadowRoot* shadowRoot = m_inputElement->ensureUserAgentShadowRoot();
+
+    // Return if shadowRoot is null
+    if (!shadowRoot)
+        return;
+
+    Document* document = m_inputElement->document();
+    m_dropdownBox = HTMLDivElement::create(document);
+    m_dropdownBox->setPseudo("-webkit-suggestion-dropdown-box");
+    // Need to force position:absolute because RenderMenuList doesn't assume it
+    // contains non-absolute or non-fixed renderers as children.
+    m_dropdownBox->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
+
+    // Minus 2 pixels because of the 1px borders on the suggestion box.
+    m_dropdownBox->setInlineStyleProperty(CSSPropertyWidth, String::number(m_inputElement->boundingBox().width().rawValue() - 2) + "px", false);
+    ExceptionCode ec = 0;
+    shadowRoot->appendChild(m_dropdownBox.get(), ec);
+    ASSERT(!ec);
+    document->updateLayout();
+    adjustDropdownBoxPosition(m_inputElement->boundingBox(), m_dropdownBox.get());
+}
+
+} // namespace WebCore
diff --git a/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.h b/Source/WebKit/blackberry/WebCoreSupport/SuggestionBoxHandler.h
new file mode 100644 (file)
index 0000000..429b468
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SuggestionBoxHandler_h
+#define SuggestionBoxHandler_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class HTMLInputElement;
+class HTMLElement;
+
+class SuggestionBoxHandler {
+    WTF_MAKE_NONCOPYABLE(SuggestionBoxHandler);
+public:
+    static PassOwnPtr<SuggestionBoxHandler> create(HTMLInputElement*);
+    ~SuggestionBoxHandler();
+    void setInputElementAndUpdateDisplay(HTMLInputElement*, bool allowEmptyPrefix = false);
+    void changeInputElementInnerTextValue(String& text);
+    void showDropdownBox(bool);
+    void hideDropdownBox();
+    HTMLInputElement* focusedElement() const { return m_inputElement.get(); }
+
+private:
+    SuggestionBoxHandler(HTMLInputElement*);
+    void insertSuggestionsToDropdownBox();
+    void buildDropdownBoxTree();
+    void parseSuggestions(bool);
+
+    RefPtr<HTMLInputElement> m_inputElement;
+    RefPtr<HTMLElement> m_dropdownBox;
+    Vector<String> m_suggestions;
+};
+
+} // namespace WebCore
+
+#endif // SuggestionBoxHandler_h
index 199ff1d..7076325 100644 (file)
@@ -57,6 +57,7 @@
 #include "SelectionHandler.h"
 #include "SpellChecker.h"
 #include "SpellingHandler.h"
+#include "SuggestionBoxHandler.h"
 #include "TextCheckerClient.h"
 #include "TextIterator.h"
 #include "VisiblePosition.h"
@@ -871,6 +872,9 @@ void InputHandler::setElementUnfocused(bool refocusOccuring)
 
         m_webPage->m_client->inputFocusLost();
 
+        // Hide the suggestion box if it is visible.
+        hideTextInputTypeSuggestionBox();
+
         // Repaint the element absent of the caret.
         if (m_currentFocusElement->renderer())
             m_currentFocusElement->renderer()->repaint();
@@ -1088,6 +1092,9 @@ void InputHandler::setElementFocused(Element* element)
 
     handleInputLocaleChanged(m_webPage->m_webSettings->isWritingDirectionRTL());
 
+    // update the suggestion box
+    showTextInputTypeSuggestionBox();
+
     if (!m_delayKeyboardVisibilityChange)
         notifyClientOfKeyboardVisibilityChange(true, true /* triggeredByFocusChange */);
 
@@ -1733,6 +1740,10 @@ bool InputHandler::handleKeyboardInput(const Platform::KeyboardEvent& keyboardEv
         if (!changeIsPartOfComposition && type == Platform::KeyboardEvent::KeyUp)
             ensureFocusTextElementVisible(EdgeIfNeeded);
     }
+
+    if (m_currentFocusElement && keyboardEventHandled)
+        showTextInputTypeSuggestionBox();
+
     return keyboardEventHandled;
 }
 
@@ -2547,5 +2558,38 @@ void InputHandler::restoreViewState()
     focusedNodeChanged();
 }
 
+void InputHandler::showTextInputTypeSuggestionBox(bool allowEmptyPrefix)
+{
+    HTMLInputElement* focusedInputElement = static_cast<HTMLInputElement*>(m_currentFocusElement->toInputElement());
+    if (!focusedInputElement || !focusedInputElement->isTextField())
+        return;
+
+    if (!focusedInputElement)
+        return;
+
+    if (!m_suggestionDropdownBoxHandler)
+        m_suggestionDropdownBoxHandler = SuggestionBoxHandler::create(focusedInputElement);
+
+    // If the focused input element isn't the same as the one inside the handler, reset and display.
+    // If the focused element is the same, display the suggestions.
+    if ((m_suggestionDropdownBoxHandler->focusedElement()) && m_suggestionDropdownBoxHandler->focusedElement() != focusedInputElement)
+        m_suggestionDropdownBoxHandler->setInputElementAndUpdateDisplay(focusedInputElement);
+    else
+        m_suggestionDropdownBoxHandler->showDropdownBox(allowEmptyPrefix);
+}
+
+void InputHandler::hideTextInputTypeSuggestionBox()
+{
+    if (m_suggestionDropdownBoxHandler)
+        m_suggestionDropdownBoxHandler->hideDropdownBox();
+}
+
+void InputHandler::elementTouched(WebCore::Element* nonShadowElementUnderFatFinger)
+{
+    // Attempt to show all suggestions when the input field is empty and a tap is registered when the element is focused.
+    if (isActiveTextEdit() && nonShadowElementUnderFatFinger == m_currentFocusElement)
+        showTextInputTypeSuggestionBox(true /* allowEmptyPrefix */);
+}
+
 }
 }
index 461d488..45bd50b 100644 (file)
@@ -50,6 +50,7 @@ class SpellCheckRequest;
 class TextCheckingRequest;
 class VisiblePosition;
 class VisibleSelection;
+class SuggestionBoxHandler;
 }
 
 namespace BlackBerry {
@@ -158,6 +159,7 @@ public:
     void callRequestCheckingFor(PassRefPtr<WebCore::SpellCheckRequest>);
     void setSystemSpellCheckStatus(bool enabled) { m_spellCheckStatusConfirmed = true; m_globalSpellCheckStatus = enabled; }
 
+    void elementTouched(WebCore::Element*);
     void restoreViewState();
 
 private:
@@ -223,6 +225,9 @@ private:
 
     bool shouldNotifyWebView(const Platform::KeyboardEvent&);
 
+    void showTextInputTypeSuggestionBox(bool allowEmptyPrefix = false);
+    void hideTextInputTypeSuggestionBox();
+
     WebPagePrivate* m_webPage;
 
     RefPtr<WebCore::Element> m_currentFocusElement;
@@ -257,6 +262,8 @@ private:
     bool m_spellCheckStatusConfirmed;
     bool m_globalSpellCheckStatus;
 
+    OwnPtr<WebCore::SuggestionBoxHandler> m_suggestionDropdownBoxHandler;
+
     DISABLE_COPY(InputHandler);
 };
 
index 3522829..492aa89 100644 (file)
@@ -117,6 +117,8 @@ void TouchEventHandler::handleTouchPoint(const Platform::TouchPoint& point, unsi
                 m_shouldRequestSpellCheckOptions = m_webPage->m_inputHandler->shouldRequestSpellCheckingOptionsForPoint(m_lastFatFingersResult.adjustedPosition(), elementUnderFatFinger, m_spellCheckOptionRequest);
             }
 
+            m_webPage->m_inputHandler->elementTouched(lastFatFingersResult().nodeAsElementIfApplicable(FatFingersResult::ShadowContentNotAllowed));
+
             handleFatFingerPressed(shiftActive, altActive, ctrlActive);
             break;
         }