From db8635032b1f83436a072be14e425076a7bd8164 Mon Sep 17 00:00:00 2001 From: "jcampan@chromium.org" Date: Thu, 18 Dec 2008 23:24:14 +0000 Subject: We now show the form autofill when the user does any of these on a focused empty text-field: - presses the up/down arrow key - left-clicks it The other browsers have that feature. BUG=5130 TEST=See bug. Review URL: http://codereview.chromium.org/14852 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7269 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/editor_client_impl.cc | 30 ++++++++++++++++++++++++++---- webkit/glue/editor_client_impl.h | 19 ++++++++++++++++++- webkit/glue/webview_impl.cc | 26 ++++++++++++++++++++++++++ webkit/glue/webview_impl.h | 3 +++ 4 files changed, 73 insertions(+), 5 deletions(-) (limited to 'webkit/glue') diff --git a/webkit/glue/editor_client_impl.cc b/webkit/glue/editor_client_impl.cc index 4daa74d..3d4e96f 100644 --- a/webkit/glue/editor_client_impl.cc +++ b/webkit/glue/editor_client_impl.cc @@ -575,7 +575,7 @@ const char* EditorClientImpl::interpretKeyEvent( } bool EditorClientImpl::handleEditingKeyboardEvent( - WebCore::KeyboardEvent* evt) { + WebCore::KeyboardEvent* evt) { const WebCore::PlatformKeyboardEvent* keyEvent = evt->keyEvent(); // do not treat this as text input if it's a system key event if (!keyEvent || keyEvent->isSystemKey()) @@ -627,6 +627,12 @@ bool EditorClientImpl::handleEditingKeyboardEvent( // void EditorClientImpl::handleKeyboardEvent(WebCore::KeyboardEvent* evt) { + if (evt->keyCode() == WebCore::VKEY_DOWN || + evt->keyCode() == WebCore::VKEY_UP) { + DCHECK(evt->target()->toNode()); + ShowAutofillForNode(evt->target()->toNode()); + } + if (handleEditingKeyboardEvent(evt)) evt->setDefaultHandled(); } @@ -651,13 +657,27 @@ void EditorClientImpl::textFieldDidEndEditing(WebCore::Element*) { void EditorClientImpl::textDidChangeInTextField(WebCore::Element* element) { DCHECK(element->hasLocalName(WebCore::HTMLNames::inputTag)); + Autofill(static_cast(element), false); +} + +void EditorClientImpl::ShowAutofillForNode(WebCore::Node* node) { + if (node->nodeType() == WebCore::Node::ELEMENT_NODE) { + WebCore::Element* element = static_cast(node); + if (element->hasLocalName(WebCore::HTMLNames::inputTag)) { + WebCore::HTMLInputElement* input_element = + static_cast(element); + if (input_element->value().isEmpty()) + Autofill(input_element, true); + } + } +} +void EditorClientImpl::Autofill(WebCore::HTMLInputElement* input_element, + bool autofill_on_empty_value) { // Cancel any pending DoAutofill calls. autofill_factory_.RevokeAll(); // Let's try to trigger autofill for that field, if applicable. - WebCore::HTMLInputElement* input_element = - static_cast(element); if (!input_element->isEnabled() || !input_element->isTextField() || input_element->isPasswordField() || !input_element->autoComplete()) { return; @@ -679,10 +699,12 @@ void EditorClientImpl::textDidChangeInTextField(WebCore::Element* element) { FROM_HERE, autofill_factory_.NewRunnableMethod(&EditorClientImpl::DoAutofill, input_element, + autofill_on_empty_value, backspace_pressed_)); } void EditorClientImpl::DoAutofill(WebCore::HTMLInputElement* input_element, + bool autofill_on_empty_value, bool backspace) { std::wstring value = webkit_glue::StringToStdWString(input_element->value()); @@ -690,7 +712,7 @@ void EditorClientImpl::DoAutofill(WebCore::HTMLInputElement* input_element, bool caret_at_end = input_element->selectionStart() == input_element->selectionEnd() && input_element->selectionEnd() == static_cast(value.length()); - if (value.empty() || !caret_at_end) { + if ((!autofill_on_empty_value && value.empty()) || !caret_at_end) { web_view_->HideAutoCompletePopup(); return; } diff --git a/webkit/glue/editor_client_impl.h b/webkit/glue/editor_client_impl.h index 3870923..daef0fb 100644 --- a/webkit/glue/editor_client_impl.h +++ b/webkit/glue/editor_client_impl.h @@ -119,11 +119,28 @@ class EditorClientImpl : public WebCore::EditorClient { virtual std::wstring Describe(WebCore::EAffinity affinity); virtual std::wstring Describe(WebCore::CSSStyleDeclaration* style); + // Shows the autofill popup for |node| if it is an HTMLInputElement and it is + // empty. This is called when you press the up or down arrow in a text field + // or when clicking an already focused text-field. + virtual void ShowAutofillForNode(WebCore::Node* node); + private: void ModifySelection(WebCore::Frame* frame, WebCore::KeyboardEvent* event); - void DoAutofill(WebCore::HTMLInputElement* input_element, bool backspace); + // Popups an autofill menu for |input_element| is applicable. + // |autofill_on_empty_value| indicates whether the autofill should be shown + // when the text-field is empty. + void Autofill(WebCore::HTMLInputElement* input_element, + bool autofill_on_empty_value); + + // This method is invoked later by Autofill() as when Autofill() is invoked + // (from one of the EditorClient callback) the carret position is not + // reflecting the last text change yet and we need it to decide whether or not + // to show the autofill popup. + void DoAutofill(WebCore::HTMLInputElement* input_element, + bool autofill_on_empty_value, + bool backspace); protected: WebViewImpl* web_view_; diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index d4d19fb..8a1aee6 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -364,8 +364,22 @@ void WebViewImpl::MouseDown(const WebMouseEvent& event) { return; last_mouse_down_point_ = gfx::Point(event.x, event.y); + // We need to remember who has focus, as if the user left-clicks an already + // focused text-field, we may want to show the auto-fill popup. + RefPtr focused_node; + if (event.button == WebMouseEvent::BUTTON_LEFT) + focused_node = GetFocusedNode(); + main_frame()->frame()->eventHandler()->handleMousePressEvent( MakePlatformMouseEvent(main_frame()->frameview(), event)); + + if (focused_node.get() && focused_node == GetFocusedNode()) { + // Already focused node was clicked, ShowAutofillForNode will determine + // whether to show the autofill (typically, if the node is a text-field and + // is empty). + static_cast(page_->editorClient())-> + ShowAutofillForNode(focused_node.get()); + } } void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) { @@ -1617,3 +1631,15 @@ void WebViewImpl::HideAutoCompletePopup() { autocomplete_popup_client_.clear(); } } + +Node* WebViewImpl::GetFocusedNode() { + Frame* frame = page_->focusController()->focusedFrame(); + if (!frame) + return NULL; + + Document* document = frame->document(); + if (!document) + return NULL; + + return document->focusedNode(); +} diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 5c0a554..1f03477 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -255,6 +255,9 @@ class WebViewImpl : public WebView { // This is invoked after the download is completed (or fails). void DeleteImageResourceFetcher(ImageResourceFetcher* fetcher); + // Returns the currently focused Node or NULL if no node has focus. + WebCore::Node* GetFocusedNode(); + // ImageResourceFetchers schedule via DownloadImage. std::set image_fetchers_; -- cgit v1.1