diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-16 00:05:15 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-16 00:05:15 +0000 |
commit | 01899c12fdad06f0e12667871be5ac99624256d8 (patch) | |
tree | c98b6c59915dcb1cdc9ead4fafb828df08f4a12e | |
parent | c1bcb90272edd39e67f85877b58da4f28fef055e (diff) | |
download | chromium_src-01899c12fdad06f0e12667871be5ac99624256d8.zip chromium_src-01899c12fdad06f0e12667871be5ac99624256d8.tar.gz chromium_src-01899c12fdad06f0e12667871be5ac99624256d8.tar.bz2 |
Changes to the autofill popup:
- we now reuse the existing popup if there is one (instead of creating a new on with each key stoke), this prevents the flickering we used to see.
- we don't hide the popup on every key stroke, instead we rely on the client editor telling us the field is not being edited anymore.
TEST=Enter some text in a form's text field several times, the autofill should show and not flicker.
BUG=5258
Review URL: http://codereview.chromium.org/14100
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7017 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/render_widget_host.cc | 4 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.cc | 5 | ||||
-rw-r--r-- | webkit/glue/editor_client_impl.cc | 7 | ||||
-rw-r--r-- | webkit/glue/webview_impl.cc | 55 | ||||
-rw-r--r-- | webkit/port/platform/chromium/PopupMenuChromium.cpp | 5 | ||||
-rw-r--r-- | webkit/port/platform/chromium/PopupMenuChromium.h | 3 |
6 files changed, 59 insertions, 20 deletions
diff --git a/chrome/browser/render_widget_host.cc b/chrome/browser/render_widget_host.cc index 41fd233..90aac3c 100644 --- a/chrome/browser/render_widget_host.cc +++ b/chrome/browser/render_widget_host.cc @@ -340,8 +340,8 @@ void RenderWidgetHost::OnMsgClose() { } void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { - // Don't allow renderer widgets to move themselves by default. Maybe this - // policy will change if we add more types of widgets. + // Note that we ignore the position. + view_->SetSize(pos.size()); } void RenderWidgetHost::OnMsgPaintRect( diff --git a/chrome/browser/render_widget_host_view_win.cc b/chrome/browser/render_widget_host_view_win.cc index d530e5d..d927868 100644 --- a/chrome/browser/render_widget_host_view_win.cc +++ b/chrome/browser/render_widget_host_view_win.cc @@ -131,9 +131,10 @@ void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) { if (is_hidden_) return; + // No SWP_NOREDRAW as autofill popups can resize and the underneath window + // should redraw in that case. UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS | - SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE | - SWP_DEFERERASE; + SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE; SetWindowPos(NULL, 0, 0, size.width(), size.height(), swp_flags); render_widget_host_->WasResized(); EnsureTooltip(); diff --git a/webkit/glue/editor_client_impl.cc b/webkit/glue/editor_client_impl.cc index e1b3e1e..4daa74d 100644 --- a/webkit/glue/editor_client_impl.cc +++ b/webkit/glue/editor_client_impl.cc @@ -644,6 +644,9 @@ void EditorClientImpl::textFieldDidEndEditing(WebCore::Element*) { // Cancel any pending DoAutofill calls. autofill_factory_.RevokeAll(); + + // Hide any showing popup. + web_view_->HideAutoCompletePopup(); } void EditorClientImpl::textDidChangeInTextField(WebCore::Element* element) { @@ -687,8 +690,10 @@ void EditorClientImpl::DoAutofill(WebCore::HTMLInputElement* input_element, bool caret_at_end = input_element->selectionStart() == input_element->selectionEnd() && input_element->selectionEnd() == static_cast<int>(value.length()); - if (value.empty() || !caret_at_end) + if (value.empty() || !caret_at_end) { + web_view_->HideAutoCompletePopup(); return; + } // First let's see if there is a password listener for that element. WebFrameImpl* webframe = diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index c04b649..540b654 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -132,10 +132,7 @@ class AutocompletePopupMenuClient : 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)); - } + SetSuggestions(suggestions); } virtual ~AutocompletePopupMenuClient() { } @@ -233,6 +230,21 @@ class AutocompletePopupMenuClient return widget.release(); } + void SetSuggestions(const std::vector<std::wstring>& suggestions) { + suggestions_.clear(); + for (std::vector<std::wstring>::const_iterator iter = suggestions.begin(); + iter != suggestions.end(); ++iter) { + suggestions_.push_back(webkit_glue::StdWStringToString(*iter)); + } + // Try to preserve selection if possible. + if (selected_index_ >= static_cast<int>(suggestions.size())) + selected_index_ = -1; + } + + WebCore::HTMLInputElement* text_field() const { + return text_field_.get(); + } + private: RefPtr<WebCore::HTMLInputElement> text_field_; std::vector<WebCore::String> suggestions_; @@ -431,10 +443,6 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { } } - // A new key being pressed should hide the popup. - if (event.type == WebInputEvent::KEY_DOWN) - HideAutoCompletePopup(); - Frame* frame = GetFocusedWebCoreFrame(); if (!frame) return false; @@ -1449,15 +1457,19 @@ void WebViewImpl::AutofillSuggestionsForNode( int64 node_id, const std::vector<std::wstring>& suggestions, int default_suggestion_index) { - if (!page_.get() || suggestions.empty()) + if (!page_.get() || suggestions.empty()) { + HideAutoCompletePopup(); return; + } DCHECK(default_suggestion_index < static_cast<int>(suggestions.size())); if (RefPtr<Frame> focused = page_->focusController()->focusedFrame()) { RefPtr<Document> document = focused->document(); - if (!document.get()) + if (!document.get()) { + HideAutoCompletePopup(); return; + } RefPtr<Node> focused_node = document->focusedNode(); // If the node for which we queried the autofill suggestions is not the @@ -1465,8 +1477,10 @@ void WebViewImpl::AutofillSuggestionsForNode( // 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) + reinterpret_cast<int64>(focused_node.get()) != node_id) { + HideAutoCompletePopup(); return; + } if (!focused_node->hasTagName(WebCore::HTMLNames::inputTag)) { NOTREACHED(); @@ -1475,10 +1489,8 @@ void WebViewImpl::AutofillSuggestionsForNode( WebCore::HTMLInputElement* input_elem = static_cast<WebCore::HTMLInputElement*>(focused_node.get()); - // Hide any current autocomplete popup. - HideAutoCompletePopup(); - - if (suggestions.size() > 0) { + if (!autocomplete_popup_client_.get() || + autocomplete_popup_client_->text_field() != input_elem) { autocomplete_popup_client_ = adoptRef(new AutocompletePopupMenuClient(this, input_elem, suggestions, @@ -1492,6 +1504,19 @@ void WebViewImpl::AutofillSuggestionsForNode( autocomplete_popup_->setAcceptOnAbandon(false); autocomplete_popup_->show(focused_node->getRect(), page_->mainFrame()->view(), 0); + } else { + // There is already a popup, reuse it. + autocomplete_popup_client_->SetSuggestions(suggestions); + IntRect old_bounds = autocomplete_popup_->boundsRect(); + autocomplete_popup_->refresh(); + IntRect new_bounds = autocomplete_popup_->boundsRect(); + // Let's resize the backing window if necessary. + if (old_bounds != new_bounds) { + WebWidgetImpl* web_widget = + static_cast<WebWidgetImpl*>(autocomplete_popup_->client()); + web_widget->delegate()->SetWindowRect( + web_widget, webkit_glue::FromIntRect(new_bounds)); + } } } } diff --git a/webkit/port/platform/chromium/PopupMenuChromium.cpp b/webkit/port/platform/chromium/PopupMenuChromium.cpp index c85b1e2..82696cf 100644 --- a/webkit/port/platform/chromium/PopupMenuChromium.cpp +++ b/webkit/port/platform/chromium/PopupMenuChromium.cpp @@ -494,6 +494,11 @@ void PopupContainer::setAcceptOnAbandon(bool value) { listBox()->setAcceptOnAbandon(value); } +void PopupContainer::refresh() { + listBox()->updateFromElement(); + layout(); +} + /////////////////////////////////////////////////////////////////////////////// // PopupListBox implementation diff --git a/webkit/port/platform/chromium/PopupMenuChromium.h b/webkit/port/platform/chromium/PopupMenuChromium.h index 49b2a75..c8c7098 100644 --- a/webkit/port/platform/chromium/PopupMenuChromium.h +++ b/webkit/port/platform/chromium/PopupMenuChromium.h @@ -79,6 +79,9 @@ public: PopupListBox* listBox() const { return m_listBox.get(); } + // Refresh the popup values from the PopupMenuClient. + void refresh(); + private: friend class WTF::RefCounted<PopupContainer>; |