| Index: webkit/glue/webview_impl.cc
|
| ===================================================================
|
| --- webkit/glue/webview_impl.cc (revision 4621)
|
| +++ webkit/glue/webview_impl.cc (working copy)
|
| @@ -35,6 +35,7 @@
|
|
|
| #include "base/compiler_specific.h"
|
| MSVC_PUSH_WARNING_LEVEL(0);
|
| +#include "CSSStyleSelector.h"
|
| #if defined(OS_WIN)
|
| #include "Cursor.h"
|
| #endif
|
| @@ -50,6 +51,8 @@
|
| #include "FrameTree.h"
|
| #include "FrameView.h"
|
| #include "GraphicsContext.h"
|
| +#include "HTMLNames.h"
|
| +#include "HTMLInputElement.h"
|
| #include "HitTestResult.h"
|
| #include "Image.h"
|
| #include "InspectorController.h"
|
| @@ -61,9 +64,11 @@
|
| #include "PlatformMouseEvent.h"
|
| #include "PlatformWheelEvent.h"
|
| #include "PluginInfoStore.h"
|
| +#include "PopupMenuClient.h"
|
| #if defined(OS_WIN)
|
| #include "RenderThemeWin.h"
|
| #endif
|
| +#include "RenderView.h"
|
| #include "ResourceHandle.h"
|
| #include "SelectionController.h"
|
| #include "Settings.h"
|
| @@ -94,6 +99,7 @@
|
| #include "webkit/glue/webview_delegate.h"
|
| #include "webkit/glue/webview_impl.h"
|
| #include "webkit/glue/webwidget_impl.h"
|
| +#include "webkit/port/platform/chromium/PopupMenuChromium.h"
|
| #include "webkit/port/platform/graphics/PlatformContextSkia.h"
|
|
|
| // Get rid of WTF's pow define so we can use std::pow.
|
| @@ -115,6 +121,126 @@
|
| static const WebCore::DragOperation kDropTargetOperation =
|
| static_cast<WebCore::DragOperation>(DragOperationCopy | DragOperationLink);
|
|
|
| +// AutocompletePopupMenuClient
|
| +class AutocompletePopupMenuClient
|
| + : public RefCounted<AutocompletePopupMenuClient>,
|
| + public WebCore::PopupMenuClient {
|
| + public:
|
| + AutocompletePopupMenuClient(WebViewImpl* webview,
|
| + WebCore::HTMLInputElement* text_field,
|
| + const std::vector<std::wstring>& suggestions,
|
| + int default_suggestion_index)
|
| + : text_field_(text_field),
|
| + selected_index_(default_suggestion_index),
|
| + webview_(webview) {
|
| + for (std::vector<std::wstring>::const_iterator iter = suggestions.begin();
|
| + iter != suggestions.end(); ++iter) {
|
| + suggestions_.push_back(webkit_glue::StdWStringToString(*iter));
|
| + }
|
| + }
|
| + virtual ~AutocompletePopupMenuClient() {
|
| + }
|
| +
|
| + virtual void valueChanged(unsigned listIndex, bool fireEvents = true) {
|
| + text_field_->setValue(suggestions_[listIndex]);
|
| + }
|
| +
|
| + virtual WebCore::String itemText(unsigned list_index) const {
|
| + return suggestions_[list_index];
|
| + }
|
| +
|
| + virtual bool itemIsEnabled(unsigned listIndex) const {
|
| + return true;
|
| + }
|
| +
|
| + virtual PopupMenuStyle itemStyle(unsigned listIndex) const {
|
| + return menuStyle();
|
| + }
|
| +
|
| + virtual PopupMenuStyle menuStyle() const {
|
| + RenderStyle* style = text_field_->renderStyle() ?
|
| + text_field_->renderStyle() :
|
| + text_field_->computedStyle();
|
| + return PopupMenuStyle(style->color(), Color::white, style->font(),
|
| + style->visibility() == VISIBLE);
|
| + }
|
| +
|
| + virtual int clientInsetLeft() const {
|
| + return 0;
|
| + }
|
| + virtual int clientInsetRight() const {
|
| + return 0;
|
| + }
|
| + virtual int clientPaddingLeft() const {
|
| +#if defined(OS_WIN)
|
| + return theme()->popupInternalPaddingLeft(text_field_->computedStyle());
|
| +#else
|
| + NOTIMPLEMENTED();
|
| + return 0;
|
| +#endif
|
| + }
|
| + virtual int clientPaddingRight() const {
|
| +#if defined(OS_WIN)
|
| + return theme()->popupInternalPaddingRight(text_field_->computedStyle());
|
| +#else
|
| + NOTIMPLEMENTED();
|
| + return 0;
|
| +#endif
|
| + }
|
| + virtual int listSize() const {
|
| + return suggestions_.size();
|
| + }
|
| + virtual int selectedIndex() const {
|
| + return selected_index_;
|
| + }
|
| + virtual void hidePopup() {
|
| + webview_->HideAutoCompletePopup();
|
| + }
|
| + virtual bool itemIsSeparator(unsigned listIndex) const {
|
| + return false;
|
| + }
|
| + virtual bool itemIsLabel(unsigned listIndex) const {
|
| + return false;
|
| + }
|
| + virtual bool itemIsSelected(unsigned listIndex) const {
|
| + return false;
|
| + }
|
| + virtual bool shouldPopOver() const {
|
| + return false;
|
| + }
|
| + virtual bool valueShouldChangeOnHotTrack() const {
|
| + return false;
|
| + }
|
| +
|
| + virtual FontSelector* fontSelector() const {
|
| + return text_field_->document()->styleSelector()->fontSelector();
|
| + }
|
| +
|
| + virtual void setTextFromItem(unsigned listIndex) {
|
| + text_field_->setValue(suggestions_[listIndex]);
|
| + }
|
| +
|
| + virtual HostWindow* hostWindow() const {
|
| + return text_field_->document()->view()->hostWindow();
|
| + }
|
| +
|
| + virtual PassRefPtr<Scrollbar> createScrollbar(
|
| + ScrollbarClient* client,
|
| + ScrollbarOrientation orientation,
|
| + ScrollbarControlSize size) {
|
| + RefPtr<Scrollbar> widget = Scrollbar::createNativeScrollbar(client,
|
| + orientation,
|
| + size);
|
| + return widget.release();
|
| + }
|
| +
|
| + private:
|
| + RefPtr<WebCore::HTMLInputElement> text_field_;
|
| + std::vector<WebCore::String> suggestions_;
|
| + int selected_index_;
|
| + WebViewImpl* webview_;
|
| +};
|
| +
|
| // WebView ----------------------------------------------------------------
|
|
|
| /*static*/
|
| @@ -292,6 +418,18 @@
|
| // event.
|
| suppress_next_keypress_event_ = false;
|
|
|
| + // Give autocomplete a chance to consume the key events it is interested in.
|
| + if (autocomplete_popup_ &&
|
| + autocomplete_popup_->isInterestedInEventForKey(event.key_code)) {
|
| + if (autocomplete_popup_->handleKeyEvent(MakePlatformKeyboardEvent(event)))
|
| + return true;
|
| + return false;
|
| + }
|
| +
|
| + // A new key being pressed should hide the popup.
|
| + if (event.type == WebInputEvent::KEY_DOWN)
|
| + HideAutoCompletePopup();
|
| +
|
| Frame* frame = GetFocusedWebCoreFrame();
|
| if (!frame)
|
| return false;
|
| @@ -714,7 +852,6 @@
|
| // we're done.
|
| if (doing_drag_and_drop_)
|
| return true;
|
| -
|
| // TODO(eseidel): Remove g_current_input_event.
|
| // This only exists to allow ChromeClient::show() to know which mouse button
|
| // triggered a window.open event.
|
| @@ -782,6 +919,14 @@
|
|
|
| void WebViewImpl::SetFocus(bool enable) {
|
| if (enable) {
|
| + // Hide the popup menu if any.
|
| + // TODO(jcampan): bug #3844: we should do that when we lose focus. The
|
| + // reason we are not doing it is because when clicking on the autofill
|
| + // popup, the page first loses focus before the mouse click is sent to the
|
| + // popup. So if we close when the focus is lost, the mouse click does not
|
| + // do anything.
|
| + HideAutoCompletePopup();
|
| +
|
| // Getting the focused frame will have the side-effect of setting the main
|
| // frame as the focused frame if it is not already focused. Otherwise, if
|
| // there is already a focused frame, then this does nothing.
|
| @@ -803,8 +948,6 @@
|
| // updated below.
|
| ReleaseFocusReferences();
|
|
|
| - // Clear focus on the currently focused frame if any.
|
| -
|
| if (!main_frame_)
|
| return;
|
|
|
| @@ -1020,7 +1163,8 @@
|
| // We have to set the key type explicitly to avoid an assert in the
|
| // KeyboardEvent constructor.
|
| platform_event.SetKeyType(PlatformKeyboardEvent::RawKeyDown);
|
| - RefPtr<KeyboardEvent> webkit_event = KeyboardEvent::create(platform_event, NULL);
|
| + RefPtr<KeyboardEvent> webkit_event = KeyboardEvent::create(platform_event,
|
| + NULL);
|
| page()->focusController()->setInitialFocus(
|
| reverse ? WebCore::FocusDirectionBackward :
|
| WebCore::FocusDirectionForward,
|
| @@ -1333,6 +1477,59 @@
|
| return NULL;
|
| }
|
|
|
| +void WebViewImpl::AutofillSuggestionsForNode(
|
| + int64 node_id,
|
| + const std::vector<std::wstring>& suggestions,
|
| + int default_suggestion_index) {
|
| + if (!main_frame_ || suggestions.empty())
|
| + return;
|
| +
|
| + DCHECK(default_suggestion_index < static_cast<int>(suggestions.size()));
|
| +
|
| + Frame* frame = main_frame_->frame();
|
| + if (!frame)
|
| + return;
|
| +
|
| + if (RefPtr<Frame> focused =
|
| + frame->page()->focusController()->focusedFrame()) {
|
| + RefPtr<Document> document = focused->document();
|
| + if (!document.get())
|
| + return;
|
| +
|
| + RefPtr<Node> focused_node = document->focusedNode();
|
| + // If the node for which we queried the autofill suggestions is not the
|
| + // focused node, then we have nothing to do.
|
| + // TODO(jcampan): also check the carret is at the end and that the text has
|
| + // not changed.
|
| + if (!focused_node.get() ||
|
| + reinterpret_cast<int64>(focused_node.get()) != node_id)
|
| + return;
|
| +
|
| + if (!focused_node->hasTagName(WebCore::HTMLNames::inputTag)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| +
|
| + WebCore::HTMLInputElement* input_elem =
|
| + static_cast<WebCore::HTMLInputElement*>(focused_node.get());
|
| + // Hide any current autocomplete popup.
|
| + HideAutoCompletePopup();
|
| +
|
| + if (suggestions.size() > 0) {
|
| + autocomplete_popup_client_ =
|
| + adoptRef(new AutocompletePopupMenuClient(this, input_elem,
|
| + suggestions,
|
| + default_suggestion_index));
|
| + // Autocomplete popup does not get focused. We need the page to still
|
| + // have focus so the user can keep typing when the popup is showing.
|
| + autocomplete_popup_ =
|
| + WebCore::PopupContainer::create(autocomplete_popup_client_.get(),
|
| + false);
|
| + autocomplete_popup_->show(focused_node->getRect(), frame->view(), 0);
|
| + }
|
| + }
|
| +}
|
| +
|
| void WebViewImpl::DidCommitLoad(bool* is_new_navigation) {
|
| if (is_new_navigation)
|
| *is_new_navigation = observed_new_navigation_;
|
| @@ -1481,3 +1678,11 @@
|
| // deletion.
|
| MessageLoop::current()->DeleteSoon(FROM_HERE, fetcher);
|
| }
|
| +
|
| +void WebViewImpl::HideAutoCompletePopup() {
|
| + if (autocomplete_popup_) {
|
| + autocomplete_popup_->hidePopup();
|
| + autocomplete_popup_.clear();
|
| + autocomplete_popup_client_.clear();
|
| + }
|
| +}
|
|
|