diff options
Diffstat (limited to 'chrome/browser/autocomplete')
23 files changed, 551 insertions, 862 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.cc b/chrome/browser/autocomplete/autocomplete.cc index ba37681..9c7e942 100644 --- a/chrome/browser/autocomplete/autocomplete.cc +++ b/chrome/browser/autocomplete/autocomplete.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -27,7 +27,6 @@ #include "googleurl/src/url_canon_ip.h" #include "googleurl/src/url_util.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" #include "net/base/net_util.h" #include "net/base/registry_controlled_domain.h" #include "net/url_request/url_request.h" @@ -368,18 +367,6 @@ void AutocompleteInput::Clear() { // AutocompleteMatch ---------------------------------------------------------- -AutocompleteMatch::AutocompleteMatch() - : provider(NULL), - relevance(0), - deletable(false), - inline_autocomplete_offset(std::wstring::npos), - transition(PageTransition::GENERATED), - is_history_what_you_typed_match(false), - type(SEARCH_WHAT_YOU_TYPED), - template_url(NULL), - starred(false) { -} - AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider, int relevance, bool deletable, @@ -397,40 +384,23 @@ AutocompleteMatch::AutocompleteMatch(AutocompleteProvider* provider, // static std::string AutocompleteMatch::TypeToString(Type type) { - const char* strings[NUM_TYPES] = { - "url-what-you-typed", - "history-url", - "history-title", - "history-body", - "history-keyword", - "navsuggest", - "search-what-you-typed", - "search-history", - "search-suggest", - "search-other-engine", - "open-history-page", - }; - DCHECK(arraysize(strings) == NUM_TYPES); - return strings[type]; -} + switch (type) { + case URL_WHAT_YOU_TYPED: return "url-what-you-typed"; + case HISTORY_URL: return "history-url"; + case HISTORY_TITLE: return "history-title"; + case HISTORY_BODY: return "history-body"; + case HISTORY_KEYWORD: return "history-keyword"; + case NAVSUGGEST: return "navsuggest"; + case SEARCH_WHAT_YOU_TYPED: return "search-what-you-typed"; + case SEARCH_HISTORY: return "search-history"; + case SEARCH_SUGGEST: return "search-suggest"; + case SEARCH_OTHER_ENGINE: return "search-other-engine"; + case OPEN_HISTORY_PAGE: return "open-history-page"; -// static -int AutocompleteMatch::TypeToIcon(Type type) { - int icons[NUM_TYPES] = { - IDR_OMNIBOX_HTTP, - IDR_OMNIBOX_HTTP, - IDR_OMNIBOX_HISTORY, - IDR_OMNIBOX_HISTORY, - IDR_OMNIBOX_HISTORY, - IDR_OMNIBOX_HTTP, - IDR_OMNIBOX_SEARCH, - IDR_OMNIBOX_SEARCH, - IDR_OMNIBOX_SEARCH, - IDR_OMNIBOX_SEARCH, - IDR_OMNIBOX_MORE, - }; - DCHECK(arraysize(icons) == NUM_TYPES); - return icons[type]; + default: + NOTREACHED(); + return std::string(); + } } // static @@ -595,14 +565,10 @@ void AutocompleteProvider::UpdateStarredStateOfMatches() { std::wstring AutocompleteProvider::StringForURLDisplay( const GURL& url, - bool check_accept_lang, - bool trim_http) const { + bool check_accept_lang) const { std::wstring languages = (check_accept_lang && profile_) ? profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::wstring(); - const net::FormatUrlTypes format_types = trim_http ? - net::kFormatUrlOmitAll : net::kFormatUrlOmitUsernamePassword; - return net::FormatUrl(url, languages, format_types, UnescapeRule::SPACES, - NULL, NULL, NULL); + return net::FormatUrl(url, languages); } // AutocompleteResult --------------------------------------------------------- diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h index 54bd9ff..d64fd6c 100644 --- a/chrome/browser/autocomplete/autocomplete.h +++ b/chrome/browser/autocomplete/autocomplete.h @@ -314,24 +314,22 @@ struct AutocompleteMatch { // The type of this match. enum Type { - URL_WHAT_YOU_TYPED = 0, // The input as a URL. - HISTORY_URL, // A past page whose URL contains the input. - HISTORY_TITLE, // A past page whose title contains the input. - HISTORY_BODY, // A past page whose body contains the input. - HISTORY_KEYWORD, // A past page whose keyword contains the input. - NAVSUGGEST, // A suggested URL. - SEARCH_WHAT_YOU_TYPED, // The input as a search query (with the default - // engine). - SEARCH_HISTORY, // A past search (with the default engine) - // containing the input. - SEARCH_SUGGEST, // A suggested search (with the default engine). - SEARCH_OTHER_ENGINE, // A search with a non-default engine. - OPEN_HISTORY_PAGE, // A synthetic result that opens the history page - // to search for the input. - NUM_TYPES, + URL_WHAT_YOU_TYPED, // The input as a URL. + HISTORY_URL, // A past page whose URL contains the input. + HISTORY_TITLE, // A past page whose title contains the input. + HISTORY_BODY, // A past page whose body contains the input. + HISTORY_KEYWORD, // A past page whose keyword contains the input. + NAVSUGGEST, // A suggested URL. + SEARCH_WHAT_YOU_TYPED, // The input as a search query (with the default + // engine). + SEARCH_HISTORY, // A past search (with the default engine) + // containing the input. + SEARCH_SUGGEST, // A suggested search (with the default engine). + SEARCH_OTHER_ENGINE, // A search with a non-default engine. + OPEN_HISTORY_PAGE, // A synthetic result that opens the history page to + // search for the input. }; - AutocompleteMatch(); AutocompleteMatch(AutocompleteProvider* provider, int relevance, bool deletable, @@ -340,10 +338,6 @@ struct AutocompleteMatch { // Converts |type| to a string representation. Used in logging. static std::string TypeToString(Type type); - // Converts |type| to a resource identifier for the appropriate icon for this - // type. - static int TypeToIcon(Type type); - // Comparison function for determining when one match is better than another. static bool MoreRelevant(const AutocompleteMatch& elem1, const AutocompleteMatch& elem2); @@ -561,8 +555,7 @@ class AutocompleteProvider // "Accept Languages" when check_accept_lang is true. Otherwise, it's called // with an empty list. std::wstring StringForURLDisplay(const GURL& url, - bool check_accept_lang, - bool trim_http) const; + bool check_accept_lang) const; // The profile associated with the AutocompleteProvider. Reference is not // owned by us. @@ -783,7 +776,7 @@ class AutocompleteController : public ACProviderListener { const AutocompleteInput& input() const { return input_; } const AutocompleteResult& result() const { return result_; } // This next is temporary and should go away when - // AutocompletePopup::InfoForCurrentSelection() moves to the controller. + // AutocompletePopup::URLsForCurrentSelection() moves to the controller. const AutocompleteResult& latest_result() const { return latest_result_; } bool done() const { return done_ && !update_delay_timer_.IsRunning(); } diff --git a/chrome/browser/autocomplete/autocomplete_classifier.cc b/chrome/browser/autocomplete/autocomplete_classifier.cc deleted file mode 100644 index 3e96ff5..0000000 --- a/chrome/browser/autocomplete/autocomplete_classifier.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/autocomplete/autocomplete_classifier.h" - -#include "chrome/browser/autocomplete/autocomplete.h" -#include "googleurl/src/gurl.h" - -AutocompleteClassifier::AutocompleteClassifier(Profile* profile) - : controller_(new AutocompleteController(profile)) { -} - -AutocompleteClassifier::~AutocompleteClassifier() { -} - -void AutocompleteClassifier::Classify(const std::wstring& text, - const std::wstring& desired_tld, - AutocompleteMatch* match, - GURL* alternate_nav_url) { - controller_->Start(text, desired_tld, true, false, true); - DCHECK(controller_->done()); - const AutocompleteResult& result = controller_->result(); - if (result.empty()) { - if (alternate_nav_url) - *alternate_nav_url = GURL(); - return; - } - - DCHECK(result.default_match() != result.end()); - *match = *result.default_match(); - if (alternate_nav_url) - *alternate_nav_url = result.alternate_nav_url(); -} diff --git a/chrome/browser/autocomplete/autocomplete_classifier.h b/chrome/browser/autocomplete/autocomplete_classifier.h deleted file mode 100644 index 3588c27..0000000 --- a/chrome/browser/autocomplete/autocomplete_classifier.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_ -#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" - -class AutocompleteController; -struct AutocompleteMatch; -class GURL; -class Profile; - -class AutocompleteClassifier { - public: - explicit AutocompleteClassifier(Profile* profile); - virtual ~AutocompleteClassifier(); - - // Given some string |text| that the user wants to use for navigation, - // determines how it should be interpreted. |desired_tld| is the user's - // desired TLD, if any; see AutocompleteInput::desired_tld(). |match| should - // be a non-NULL outparam that will be set to the default match for this - // input, if any (for invalid input, there will be no default match, and - // |match| will be left unchanged). |alternate_nav_url| is a possibly-NULL - // outparam that, if non-NULL, will be set to the navigational URL (if any) in - // case of an accidental search; see comments on - // AutocompleteResult::alternate_nav_url_ in autocomplete.h. - void Classify(const std::wstring& text, - const std::wstring& desired_tld, - AutocompleteMatch* match, - GURL* alternate_nav_url); - - private: - scoped_ptr<AutocompleteController> controller_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(AutocompleteClassifier); -}; - -#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CLASSIFIER_H_ diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index 9b0aefb..f4c2583 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,6 @@ #include "base/basictypes.h" #include "base/utf_string_conversions.h" #include "chrome/app/chrome_dll_resource.h" -#include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/autocomplete/autocomplete_edit_view.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" #include "chrome/browser/autocomplete/keyword_provider.h" @@ -20,6 +19,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/browser/search_versus_navigate_classifier.h" #include "chrome/common/notification_service.h" #include "googleurl/src/gurl.h" #include "googleurl/src/url_util.h" @@ -44,6 +44,7 @@ AutocompleteEditModel::AutocompleteEditModel( control_key_state_(UP), is_keyword_hint_(false), keyword_ui_state_(NORMAL), + show_search_hint_(true), paste_and_go_transition_(PageTransition::TYPED), profile_(profile) { } @@ -80,7 +81,7 @@ const AutocompleteEditModel::State } return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_, - keyword_ui_state_); + keyword_ui_state_, show_search_hint_); } void AutocompleteEditModel::RestoreState(const State& state) { @@ -91,6 +92,7 @@ void AutocompleteEditModel::RestoreState(const State& state) { keyword_ = state.keyword; is_keyword_hint_ = state.is_keyword_hint; keyword_ui_state_ = state.keyword_ui_state; + show_search_hint_ = state.show_search_hint; view_->SetUserText(state.user_text, DisplayTextFromUserText(state.user_text), false); } @@ -120,9 +122,7 @@ void AutocompleteEditModel::SetUserText(const std::wstring& text) { void AutocompleteEditModel::GetDataForURLExport(GURL* url, std::wstring* title, SkBitmap* favicon) { - AutocompleteMatch match; - GetInfoForCurrentText(&match, NULL); - *url = match.destination_url; + *url = GetURLForCurrentText(NULL, NULL, NULL); if (UTF8ToWide(url->possibly_invalid_spec()) == permanent_text_) { *title = controller_->GetTitle(); *favicon = controller_->GetFavIcon(); @@ -134,7 +134,7 @@ std::wstring AutocompleteEditModel::GetDesiredTLD() const { std::wstring(L"com") : std::wstring(); } -bool AutocompleteEditModel::CurrentTextIsURL() const { +bool AutocompleteEditModel::CurrentTextIsURL() { // If !user_input_in_progress_, the permanent text is showing, which should // always be a URL, so no further checking is needed. By avoiding checking in // this case, we avoid calling into the autocomplete providers, and thus @@ -142,15 +142,9 @@ bool AutocompleteEditModel::CurrentTextIsURL() const { if (!user_input_in_progress_) return true; - AutocompleteMatch match; - GetInfoForCurrentText(&match, NULL); - return match.transition == PageTransition::TYPED; -} - -AutocompleteMatch::Type AutocompleteEditModel::CurrentTextType() const { - AutocompleteMatch match; - GetInfoForCurrentText(&match, NULL); - return match.type; + PageTransition::Type transition = PageTransition::LINK; + GetURLForCurrentText(&transition, NULL, NULL); + return transition == PageTransition::TYPED; } bool AutocompleteEditModel::GetURLForText(const std::wstring& text, @@ -180,6 +174,7 @@ void AutocompleteEditModel::Revert() { keyword_.clear(); is_keyword_hint_ = false; keyword_ui_state_ = NORMAL; + show_search_hint_ = permanent_text_.empty(); has_temporary_text_ = false; view_->SetWindowTextAndCaretPos(permanent_text_, has_focus_ ? permanent_text_.length() : 0); @@ -196,11 +191,14 @@ bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) return false; - AutocompleteMatch match; - profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), - &match, &paste_and_go_alternate_nav_url_); - paste_and_go_url_ = match.destination_url; - paste_and_go_transition_ = match.transition; + paste_and_go_url_ = GURL(); + paste_and_go_transition_ = PageTransition::TYPED; + paste_and_go_alternate_nav_url_ = GURL(); + + profile_->GetSearchVersusNavigateClassifier()->Classify(text, std::wstring(), + NULL, &paste_and_go_url_, &paste_and_go_transition_, NULL, + &paste_and_go_alternate_nav_url_); + return paste_and_go_url_.is_valid(); } @@ -217,30 +215,33 @@ void AutocompleteEditModel::PasteAndGo() { void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition, bool for_drop) { // Get the URL and transition type for the selected entry. - AutocompleteMatch match; + PageTransition::Type transition; + bool is_history_what_you_typed_match; GURL alternate_nav_url; - GetInfoForCurrentText(&match, &alternate_nav_url); - if (!match.destination_url.is_valid()) + const GURL url(GetURLForCurrentText(&transition, + &is_history_what_you_typed_match, + &alternate_nav_url)); + if (!url.is_valid()) return; - if (UTF8ToWide(match.destination_url.spec()) == permanent_text_) { + if (UTF8ToWide(url.spec()) == permanent_text_) { // When the user hit enter on the existing permanent URL, treat it like a // reload for scoring purposes. We could detect this by just checking // user_input_in_progress_, but it seems better to treat "edits" that end // up leaving the URL unchanged (e.g. deleting the last character and then // retyping it) as reloads too. - match.transition = PageTransition::RELOAD; + transition = PageTransition::RELOAD; } else if (for_drop || ((paste_state_ != NONE) && - match.is_history_what_you_typed_match)) { + is_history_what_you_typed_match)) { // When the user pasted in a URL and hit enter, score it like a link click // rather than a normal typed URL, so it doesn't get inline autocompleted // as aggressively later. - match.transition = PageTransition::LINK; + transition = PageTransition::LINK; } - view_->OpenURL(match.destination_url, disposition, match.transition, - alternate_nav_url, AutocompletePopupModel::kNoMatch, - is_keyword_hint_ ? std::wstring() : keyword_); + view_->OpenURL(url, disposition, transition, alternate_nav_url, + AutocompletePopupModel::kNoMatch, + is_keyword_hint_ ? std::wstring() : keyword_); } void AutocompleteEditModel::SendOpenNotification(size_t selected_line, @@ -324,20 +325,17 @@ void AutocompleteEditModel::OnKillFocus() { } bool AutocompleteEditModel::OnEscapeKeyPressed() { - if (has_temporary_text_) { - AutocompleteMatch match; - popup_->InfoForCurrentSelection(&match, NULL); - if (match.destination_url != original_url_) { - // The user typed something, then selected a different item. Restore the - // text they typed and change back to the default item. - // NOTE: This purposefully does not reset paste_state_. - just_deleted_text_ = false; - has_temporary_text_ = false; - keyword_ui_state_ = original_keyword_ui_state_; - popup_->ResetToDefaultMatch(); - view_->OnRevertTemporaryText(); - return true; - } + if (has_temporary_text_ && + (popup_->URLsForCurrentSelection(NULL, NULL, NULL) != original_url_)) { + // The user typed something, then selected a different item. Restore the + // text they typed and change back to the default item. + // NOTE: This purposefully does not reset paste_state_. + just_deleted_text_ = false; + has_temporary_text_ = false; + keyword_ui_state_ = original_keyword_ui_state_; + popup_->ResetToDefaultMatch(); + view_->OnRevertTemporaryText(); + return true; } // If the user wasn't editing, but merely had focus in the edit, allow <esc> @@ -407,24 +405,35 @@ void AutocompleteEditModel::OnUpOrDownKeyPressed(int count) { void AutocompleteEditModel::OnPopupDataChanged( const std::wstring& text, - GURL* destination_for_temporary_text_change, + bool is_temporary_text, const std::wstring& keyword, - bool is_keyword_hint) { + bool is_keyword_hint, + AutocompleteMatch::Type type) { + // We don't want to show the search hint if we're showing a keyword hint or + // selected keyword, or (subtle!) if we would be showing a selected keyword + // but for keyword_ui_state_ == NO_KEYWORD. + const bool show_search_hint = keyword.empty() && + ((type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED) || + (type == AutocompleteMatch::SEARCH_HISTORY) || + (type == AutocompleteMatch::SEARCH_SUGGEST)); + // Update keyword/hint-related local state. bool keyword_state_changed = (keyword_ != keyword) || - ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); + ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()) || + (show_search_hint_ != show_search_hint); if (keyword_state_changed) { keyword_ = keyword; is_keyword_hint_ = is_keyword_hint; + show_search_hint_ = show_search_hint; } // Handle changes to temporary text. - if (destination_for_temporary_text_change != NULL) { + if (is_temporary_text) { const bool save_original_selection = !has_temporary_text_; if (save_original_selection) { // Save the original selection and URL so it can be reverted later. has_temporary_text_ = true; - original_url_ = *destination_for_temporary_text_change; + original_url_ = popup_->URLsForCurrentSelection(NULL, NULL, NULL); original_keyword_ui_state_ = keyword_ui_state_; } if (control_key_state_ == DOWN_WITHOUT_CHANGE) { @@ -533,6 +542,7 @@ void AutocompleteEditModel::Observe(NotificationType type, std::wstring inline_autocomplete_text; std::wstring keyword; bool is_keyword_hint = false; + AutocompleteMatch::Type match_type = AutocompleteMatch::SEARCH_WHAT_YOU_TYPED; const AutocompleteResult* result = Details<const AutocompleteResult>(details).ptr(); const AutocompleteResult::const_iterator match(result->default_match()); @@ -549,9 +559,11 @@ void AutocompleteEditModel::Observe(NotificationType type, // the OS DNS cache could suffer eviction problems for minimal gain. is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); + match_type = match->type; } - OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint); + OnPopupDataChanged(inline_autocomplete_text, false, keyword, is_keyword_hint, + match_type); } void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { @@ -574,14 +586,20 @@ std::wstring AutocompleteEditModel::UserTextFromDisplayText( text : (keyword_ + L" " + text); } -void AutocompleteEditModel::GetInfoForCurrentText( - AutocompleteMatch* match, +GURL AutocompleteEditModel::GetURLForCurrentText( + PageTransition::Type* transition, + bool* is_history_what_you_typed_match, GURL* alternate_nav_url) const { if (popup_->IsOpen() || query_in_progress()) { - popup_->InfoForCurrentSelection(match, alternate_nav_url); - } else { - profile_->GetAutocompleteClassifier()->Classify( - UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), match, - alternate_nav_url); + return popup_->URLsForCurrentSelection(transition, + is_history_what_you_typed_match, + alternate_nav_url); } + + GURL destination_url; + profile_->GetSearchVersusNavigateClassifier()->Classify( + UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), NULL, + &destination_url, transition, is_history_what_you_typed_match, + alternate_nav_url); + return destination_url; } diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h index 9f4e973..1a0386c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.h +++ b/chrome/browser/autocomplete/autocomplete_edit.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -83,12 +83,14 @@ class AutocompleteEditModel : public NotificationObserver { const std::wstring& user_text, const std::wstring& keyword, bool is_keyword_hint, - KeywordUIState keyword_ui_state) + KeywordUIState keyword_ui_state, + bool show_search_hint) : user_input_in_progress(user_input_in_progress), user_text(user_text), keyword(keyword), is_keyword_hint(is_keyword_hint), - keyword_ui_state(keyword_ui_state) { + keyword_ui_state(keyword_ui_state), + show_search_hint(show_search_hint) { } bool user_input_in_progress; @@ -96,6 +98,7 @@ class AutocompleteEditModel : public NotificationObserver { const std::wstring keyword; const bool is_keyword_hint; const KeywordUIState keyword_ui_state; + const bool show_search_hint; }; AutocompleteEditModel(AutocompleteEditView* view, @@ -134,10 +137,7 @@ class AutocompleteEditModel : public NotificationObserver { // Returns true if the current edit contents will be treated as a // URL/navigation, as opposed to a search. - bool CurrentTextIsURL() const; - - // Returns the match type for the current edit contents. - AutocompleteMatch::Type CurrentTextType() const; + bool CurrentTextIsURL(); // Returns true if |text| (which is display text in the current context) // parses as a URL, and in that case sets |url| to the calculated URL. @@ -208,7 +208,7 @@ class AutocompleteEditModel : public NotificationObserver { // Accessors for keyword-related state (see comments on keyword_ and // is_keyword_hint_). std::wstring keyword() const { - return (is_keyword_hint_ || (keyword_ui_state_ != NO_KEYWORD)) ? + return (is_keyword_hint_ ? has_focus_ : (keyword_ui_state_ != NO_KEYWORD)) ? keyword_ : std::wstring(); } bool is_keyword_hint() const { return is_keyword_hint_; } @@ -220,6 +220,10 @@ class AutocompleteEditModel : public NotificationObserver { // currently visible in the edit. void ClearKeyword(const std::wstring& visible_text); + // True if we should show the "Type to search" hint (see comments on + // show_search_hint_). + bool show_search_hint() const { return has_focus_ && show_search_hint_; } + // Returns true if a query to an autocomplete provider is currently // in progress. This logic should in the future live in // AutocompleteController but resides here for now. This method is used by @@ -256,20 +260,21 @@ class AutocompleteEditModel : public NotificationObserver { // Called when any relevant data changes. This rolls together several // separate pieces of data into one call so we can update all the UI // efficiently: - // |text| is either the new temporary text from the user manually selecting - // a different match, or the inline autocomplete text. We distinguish by - // checking if |destination_for_temporary_text_change| is NULL. - // |destination_for_temporary_text_change| is NULL (if temporary text should - // not change) or the pre-change desitnation URL (if temporary text should - // change) so we can save it off to restore later. + // |text| is either the new temporary text (if |is_temporary_text| is true) + // from the user manually selecting a different match, or the inline + // autocomplete text (if |is_temporary_text| is false). // |keyword| is the keyword to show a hint for if |is_keyword_hint| is true, // or the currently selected keyword if |is_keyword_hint| is false (see // comments on keyword_ and is_keyword_hint_). + // |type| is the type of match selected; this is used to determine whether + // we can show the "Type to search" hint (see comments on + // show_search_hint_). void OnPopupDataChanged( const std::wstring& text, - GURL* destination_for_temporary_text_change, + bool is_temporary_text, const std::wstring& keyword, - bool is_keyword_hint); + bool is_keyword_hint, + AutocompleteMatch::Type type); // Called by the AutocompleteEditView after something changes, with details // about what state changes occured. Updates internal state, updates the @@ -321,10 +326,16 @@ class AutocompleteEditModel : public NotificationObserver { std::wstring DisplayTextFromUserText(const std::wstring& text) const; std::wstring UserTextFromDisplayText(const std::wstring& text) const; - // Returns the default match for the current text, as well as the alternate - // nav URL, if |alternate_nav_url| is non-NULL and there is such a URL. - void GetInfoForCurrentText(AutocompleteMatch* match, - GURL* alternate_nav_url) const; + // Returns the URL. If the user has not edited the text, this returns the + // permanent text. If the user has edited the text, this returns the default + // match based on the current text, which may be a search URL, or keyword + // generated URL. + // + // See AutocompleteEdit for a description of the args (they may be null if + // not needed). + GURL GetURLForCurrentText(PageTransition::Type* transition, + bool* is_history_what_you_typed_match, + GURL* alternate_nav_url) const; AutocompleteEditView* view_; @@ -421,6 +432,10 @@ class AutocompleteEditModel : public NotificationObserver { // See KeywordUIState enum. KeywordUIState keyword_ui_state_; + // True when it's safe to show a "Type to search" hint to the user (when the + // edit is empty, or the user is in the process of searching). + bool show_search_hint_; + // Paste And Go-related state. See CanPasteAndGo(). mutable GURL paste_and_go_url_; mutable PageTransition::Type paste_and_go_transition_; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h index 0d4c230..63c2524 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view.h @@ -59,13 +59,6 @@ class AutocompleteEditView { // browser, or just whatever the user has currently typed. virtual std::wstring GetText() const = 0; - // |true| if the user is in the process of editing the field, or if - // the field is empty. - virtual bool IsEditingOrEmpty() const = 0; - - // Returns the resource ID of the icon to show for the current text. - virtual int GetIcon() const = 0; - // The user text is the text the user has manually keyed in. When present, // this is shown in preference to the permanent text; hitting escape will // revert to the permanent text. diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc index 006395f..86d886d 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -17,6 +17,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/defaults.h" @@ -33,11 +34,9 @@ #include "net/base/escape.h" #if defined(TOOLKIT_VIEWS) -#include "chrome/browser/views/autocomplete/autocomplete_popup_contents_view.h" #include "chrome/browser/views/location_bar_view.h" #include "gfx/skia_utils_gtk.h" #else -#include "chrome/browser/autocomplete/autocomplete_popup_view_gtk.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/location_bar_view_gtk.h" #endif @@ -46,13 +45,11 @@ using gfx::SkColorToGdkColor; namespace { -const gchar* kAutocompleteEditViewGtkKey = "__ACE_VIEW_GTK__"; - const char kTextBaseColor[] = "#808080"; -const char kSecureSchemeColor[] = "#079500"; -const char kSecurityErrorSchemeColor[] = "#a20000"; +const char kSecureSchemeColor[] = "#009614"; +const char kInsecureSchemeColor[] = "#c80000"; -const double kStrikethroughStrokeRed = 162.0 / 256.0; +const double kStrikethroughStrokeRed = 210.0 / 256.0; const double kStrikethroughStrokeWidth = 2.0; size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) { @@ -111,26 +108,6 @@ void SetEntryStyle() { "style \"chrome-location-bar-entry\""); } -// Copied from GTK+. Called when we lose the primary selection. This will clear -// the selection in the text buffer. -void ClipboardSelectionCleared(GtkClipboard* clipboard, - gpointer data) { - GtkTextIter insert; - GtkTextIter selection_bound; - GtkTextBuffer* buffer = GTK_TEXT_BUFFER(data); - - gtk_text_buffer_get_iter_at_mark(buffer, &insert, - gtk_text_buffer_get_insert(buffer)); - gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound, - gtk_text_buffer_get_selection_bound(buffer)); - - if (!gtk_text_iter_equal(&insert, &selection_bound)) { - gtk_text_buffer_move_mark(buffer, - gtk_text_buffer_get_selection_bound(buffer), - &insert); - } -} - } // namespace AutocompleteEditViewGtk::AutocompleteEditViewGtk( @@ -139,30 +116,23 @@ AutocompleteEditViewGtk::AutocompleteEditViewGtk( Profile* profile, CommandUpdater* command_updater, bool popup_window_mode, -#if defined(TOOLKIT_VIEWS) - const views::View* location_bar) -#else - GtkWidget* location_bar) -#endif + const BubblePositioner* bubble_positioner) : text_view_(NULL), tag_table_(NULL), text_buffer_(NULL), faded_text_tag_(NULL), secure_scheme_tag_(NULL), - security_error_scheme_tag_(NULL), + insecure_scheme_tag_(NULL), model_(new AutocompleteEditModel(this, controller, profile)), -#if defined(TOOLKIT_VIEWS) - popup_view_(new AutocompletePopupContentsView( - gfx::Font(), this, model_.get(), profile, location_bar)), -#else - popup_view_(new AutocompletePopupViewGtk(this, model_.get(), profile, - location_bar)), -#endif + popup_view_(AutocompletePopupView::CreatePopupView(gfx::Font(), this, + model_.get(), + profile, + bubble_positioner)), controller_(controller), toolbar_model_(toolbar_model), command_updater_(command_updater), popup_window_mode_(popup_window_mode), - security_level_(ToolbarModel::NONE), + scheme_security_level_(ToolbarModel::NORMAL), mark_set_handler_id_(0), #if defined(OS_CHROMEOS) button_1_pressed_(false), @@ -215,7 +185,6 @@ void AutocompleteEditViewGtk::Init() { // the other objects adds a reference; it doesn't adopt them. tag_table_ = gtk_text_tag_table_new(); text_buffer_ = gtk_text_buffer_new(tag_table_); - g_object_set_data(G_OBJECT(text_buffer_), kAutocompleteEditViewGtkKey, this); text_view_ = gtk_text_view_new_with_buffer(text_buffer_); if (popup_window_mode_) gtk_text_view_set_editable(GTK_TEXT_VIEW(text_view_), false); @@ -246,8 +215,8 @@ void AutocompleteEditViewGtk::Init() { NULL, "foreground", kTextBaseColor, NULL); secure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, NULL, "foreground", kSecureSchemeColor, NULL); - security_error_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, - NULL, "foreground", kSecurityErrorSchemeColor, NULL); + insecure_scheme_tag_ = gtk_text_buffer_create_tag(text_buffer_, + NULL, "foreground", kInsecureSchemeColor, NULL); normal_text_tag_ = gtk_text_buffer_create_tag(text_buffer_, NULL, "foreground", "#000000", NULL); @@ -289,8 +258,6 @@ void AutocompleteEditViewGtk::Init() { G_CALLBACK(&HandlePopulatePopupThunk), this); mark_set_handler_id_ = g_signal_connect( text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this); - mark_set_handler_id2_ = g_signal_connect_after( - text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetAfterThunk), this); g_signal_connect(text_view_, "drag-data-received", G_CALLBACK(&HandleDragDataReceivedThunk), this); g_signal_connect(text_view_, "backspace", @@ -317,7 +284,7 @@ void AutocompleteEditViewGtk::Init() { SetBaseColor(); #endif - ViewIDUtil::SetID(GetNativeView(), VIEW_ID_AUTOCOMPLETE); + ViewIDUtil::SetID(widget(), VIEW_ID_AUTOCOMPLETE); } void AutocompleteEditViewGtk::SetFocus() { @@ -351,8 +318,9 @@ void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) { DCHECK(tab); // If any text has been selected, register it as the PRIMARY selection so it // can still be pasted via middle-click after the text view is cleared. - if (!selected_text_.empty()) + if (!selected_text_.empty()) { SavePrimarySelection(selected_text_); + } // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important. AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch(); GetStateAccessor()->SetProperty( @@ -366,9 +334,15 @@ void AutocompleteEditViewGtk::Update(const TabContents* contents) { model_->UpdatePermanentText(toolbar_model_->GetText()); ToolbarModel::SecurityLevel security_level = - toolbar_model_->GetSecurityLevel(); - bool changed_security_level = (security_level != security_level_); - security_level_ = security_level; + toolbar_model_->GetSchemeSecurityLevel(); + bool changed_security_level = (security_level != scheme_security_level_); + scheme_security_level_ = security_level; + + // TODO(deanm): This doesn't exactly match Windows. There there is a member + // background_color_. I think we can get away with just the level though. + if (changed_security_level) { + SetBaseColor(); + } if (contents) { selected_text_.clear(); @@ -418,17 +392,6 @@ std::wstring AutocompleteEditViewGtk::GetText() const { return out; } -bool AutocompleteEditViewGtk::IsEditingOrEmpty() const { - return model_->user_input_in_progress() || - (gtk_text_buffer_get_char_count(text_buffer_) == 0); -} - -int AutocompleteEditViewGtk::GetIcon() const { - return IsEditingOrEmpty() ? - AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : - toolbar_model_->GetIcon(); -} - void AutocompleteEditViewGtk::SetUserText(const std::wstring& text, const std::wstring& display_text, bool update_popup) { @@ -619,8 +582,10 @@ void AutocompleteEditViewGtk::SetBaseColor() { bool use_gtk = theme_provider_->UseGtkTheme(); #endif - if (use_gtk) { - gtk_widget_modify_cursor(text_view_, NULL, NULL); + // If we're on a secure connection, ignore what the theme wants us to do + // and use a yellow background. + bool is_secure = (scheme_security_level_ == ToolbarModel::SECURE); + if (use_gtk && !is_secure) { gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL); gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, NULL); gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, NULL); @@ -635,21 +600,20 @@ void AutocompleteEditViewGtk::SetBaseColor() { GdkColor average_color = gtk_util::AverageColors( style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]); - g_object_set(faded_text_tag_, "foreground-gdk", &average_color, NULL); + g_object_set(faded_text_tag_, "foreground-gdk", + &average_color, NULL); g_object_set(normal_text_tag_, "foreground-gdk", &style->text[GTK_STATE_NORMAL], NULL); } else { - const GdkColor* background_color_ptr; #if defined(TOOLKIT_VIEWS) const GdkColor background_color = gfx::SkColorToGdkColor( - LocationBarView::GetColor(ToolbarModel::NONE, - LocationBarView::BACKGROUND)); - background_color_ptr = &background_color; + LocationBarView::GetColor(is_secure, LocationBarView::BACKGROUND)); + gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, + &background_color); #else - background_color_ptr = &LocationBarViewGtk::kBackgroundColor; + gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, + &LocationBarViewGtk::kBackgroundColorByLevel[scheme_security_level_]); #endif - gtk_widget_modify_cursor(text_view_, &gfx::kGdkBlack, &gfx::kGdkGray); - gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, background_color_ptr); #if !defined(TOOLKIT_VIEWS) // Override the selected colors so we don't leak colors from the current @@ -1073,32 +1037,11 @@ void AutocompleteEditViewGtk::HandleMarkSet(GtkTextBuffer* buffer, GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_)) SavePrimarySelection(selected_text_); - } else if (IsSelectAll() && !model_->user_input_in_progress()) { - // Copy the whole URL to the clipboard (including the scheme, which is - // hidden in the case of http://). - GURL url; - if (model_->GetURLForText(GetText(), &url)) - OwnPrimarySelection(url.spec()); } selected_text_ = new_selected_text; } -// Override the primary selection the text buffer has set. This has to happen -// after the default handler for the "mark-set" signal. -void AutocompleteEditViewGtk::HandleMarkSetAfter(GtkTextBuffer* buffer, - GtkTextIter* location, - GtkTextMark* mark) { - std::wstring text = GetText(); - if (IsSelectAll() && !model_->user_input_in_progress() && !text.empty()) { - // Copy the whole URL to the clipboard (including the scheme, which is - // hidden in the case of http://). - GURL url; - if (model_->GetURLForText(GetText(), &url)) - OwnPrimarySelection(url.spec()); - } -} - // Just use the default behavior for DnD, except if the drop can be a PasteAndGo // then override. void AutocompleteEditViewGtk::HandleDragDataReceived( @@ -1235,14 +1178,18 @@ void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(GtkWidget* sender) { // string to avoid encoding and escaping issues when pasting this text // elsewhere. scw.WriteText(url_spec16); - OwnPrimarySelection(url.spec()); } else { scw.WriteText(text16); - OwnPrimarySelection(UTF16ToUTF8(text16)); } scw.WriteHyperlink(UTF16ToUTF8(EscapeForHTML(text16)), url.spec()); + // Update PRIMARY selection if it is not owned by the text_buffer. + if (gtk_clipboard_get_owner(clipboard) != G_OBJECT(text_buffer_)) { + std::string utf8_text(UTF16ToUTF8(text16)); + gtk_clipboard_set_text(clipboard, utf8_text.c_str(), utf8_text.length()); + } + // Stop propagating the signal. static guint signal_id = g_signal_lookup("copy-clipboard", GTK_TYPE_TEXT_VIEW); @@ -1250,27 +1197,16 @@ void AutocompleteEditViewGtk::HandleCopyOrCutClipboard(GtkWidget* sender) { return; } - OwnPrimarySelection(selected_text_); -} - -void AutocompleteEditViewGtk::OwnPrimarySelection(const std::string& text) { - primary_selection_text_ = text; - - GtkTargetList* list = gtk_target_list_new(NULL, 0); - gtk_target_list_add_text_targets(list, 0); - gint len; - GtkTargetEntry* entries = gtk_target_table_new_from_list(list, &len); - - // When |text_buffer_| is destroyed, it will clear the clipboard, hence - // we needn't worry about calling gtk_clipboard_clear(). - gtk_clipboard_set_with_owner(gtk_clipboard_get(GDK_SELECTION_PRIMARY), - entries, len, - ClipboardGetSelectionThunk, - ClipboardSelectionCleared, - G_OBJECT(text_buffer_)); + // Passing gtk_text_buffer_copy_clipboard() a text buffer that already owns + // the clipboard that's being updated clears the highlighted text, which we + // don't want to do (and it also appears to at least sometimes trigger a + // failed G_IS_OBJECT() assertion). + if (gtk_clipboard_get_owner(clipboard) == G_OBJECT(text_buffer_)) + return; - gtk_target_list_unref(list); - gtk_target_table_free(entries, len); + // We can't just call SavePrimarySelection(); that makes the text view lose + // the selection and unhighlight its text. + gtk_text_buffer_copy_clipboard(text_buffer_, clipboard); } void AutocompleteEditViewGtk::HandlePasteClipboard(GtkWidget* sender) { @@ -1358,7 +1294,6 @@ void AutocompleteEditViewGtk::StartUpdatingHighlightedText() { gtk_text_buffer_remove_selection_clipboard(text_buffer_, clipboard); } g_signal_handler_block(text_buffer_, mark_set_handler_id_); - g_signal_handler_block(text_buffer_, mark_set_handler_id2_); } void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() { @@ -1370,7 +1305,6 @@ void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() { gtk_text_buffer_add_selection_clipboard(text_buffer_, clipboard); } g_signal_handler_unblock(text_buffer_, mark_set_handler_id_); - g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_); } AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() { @@ -1440,21 +1374,22 @@ void AutocompleteEditViewGtk::EmphasizeURLComponents() { strikethrough_ = CharRange(); // Emphasize the scheme for security UI display purposes (if necessary). if (!model_->user_input_in_progress() && scheme.is_nonempty() && - (security_level_ != ToolbarModel::NONE)) { + (scheme_security_level_ != ToolbarModel::NORMAL)) { CharRange scheme_range = CharRange(GetUTF8Offset(text, scheme.begin), GetUTF8Offset(text, scheme.end())); ItersFromCharRange(scheme_range, &start, &end); - if (security_level_ == ToolbarModel::SECURITY_ERROR) { + if (scheme_security_level_ == ToolbarModel::SECURE) { + gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, + &start, &end); + } else { strikethrough_ = scheme_range; // When we draw the strikethrough, we don't want to include the ':' at the // end of the scheme. strikethrough_.cp_max--; - gtk_text_buffer_apply_tag(text_buffer_, security_error_scheme_tag_, + gtk_text_buffer_apply_tag(text_buffer_, insecure_scheme_tag_, &start, &end); - } else { - gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, &start, &end); } } } @@ -1534,23 +1469,3 @@ void AutocompleteEditViewGtk::HandleWidgetDirectionChanged( void AutocompleteEditViewGtk::HandleKeymapDirectionChanged(GdkKeymap* sender) { AdjustTextJustification(); } - -// static -void AutocompleteEditViewGtk::ClipboardGetSelectionThunk( - GtkClipboard* clipboard, - GtkSelectionData* selection_data, - guint info, - gpointer object) { - AutocompleteEditViewGtk* edit_view = - reinterpret_cast<AutocompleteEditViewGtk*>( - g_object_get_data(G_OBJECT(object), kAutocompleteEditViewGtkKey)); - edit_view->ClipboardGetSelection(clipboard, selection_data, info); -} - -void AutocompleteEditViewGtk::ClipboardGetSelection( - GtkClipboard* clipboard, - GtkSelectionData* selection_data, - guint info) { - gtk_selection_data_set_text(selection_data, primary_selection_text_.c_str(), - primary_selection_text_.size()); -} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h index 66b837b..1eb1736 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -25,11 +25,9 @@ class AutocompleteEditController; class AutocompleteEditModel; class AutocompletePopupView; +class BubblePositioner; class Profile; class TabContents; -namespace views { -class View; -} #if !defined(TOOLKIT_VIEWS) class GtkThemeProvider; @@ -55,16 +53,14 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, Profile* profile, CommandUpdater* command_updater, bool popup_window_mode, -#if defined(TOOLKIT_VIEWS) - const views::View* location_bar); -#else - GtkWidget* location_bar); -#endif + const BubblePositioner* bubble_positioner); ~AutocompleteEditViewGtk(); // Initialize, create the underlying widgets, etc. void Init(); + GtkWidget* widget() { return alignment_.get(); } + // Returns the width, in pixels, needed to display the current text. The // returned value includes margins and borders. int TextWidth(); @@ -86,9 +82,6 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, virtual std::wstring GetText() const; - virtual bool IsEditingOrEmpty() const; - virtual int GetIcon() const; - virtual void SetUserText(const std::wstring& text) { SetUserText(text, text, true); } @@ -141,9 +134,6 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, GtkTextBuffer*); CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSet, GtkTextBuffer*, GtkTextIter*, GtkTextMark*); - // As above, but called after the default handler. - CHROMEG_CALLBACK_2(AutocompleteEditViewGtk, void, HandleMarkSetAfter, - GtkTextBuffer*, GtkTextIter*, GtkTextMark*); CHROMEG_CALLBACK_3(AutocompleteEditViewGtk, void, HandleInsertText, GtkTextBuffer*, GtkTextIter*, const gchar*, gint); CHROMEG_CALLBACK_0(AutocompleteEditViewGtk, void, @@ -182,20 +172,6 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, CHROMEGTK_CALLBACK_1(AutocompleteEditViewGtk, void, HandleWidgetDirectionChanged, GtkTextDirection); - // Callback for the PRIMARY selection clipboard. - static void ClipboardGetSelectionThunk(GtkClipboard* clipboard, - GtkSelectionData* selection_data, - guint info, - gpointer object); - void ClipboardGetSelection(GtkClipboard* clipboard, - GtkSelectionData* selection_data, - guint info); - - // Take control of the PRIMARY selection clipboard with |text|. Use - // |text_buffer_| as the owner, so that this doesn't remove the selection on - // it. This makes use of the above callbacks. - void OwnPrimarySelection(const std::string& text); - // Gets the GTK_TEXT_WINDOW_WIDGET coordinates for |text_view_| that bound the // given iters. gfx::Rect WindowBoundsFromIters(GtkTextIter* iter1, GtkTextIter* iter2); @@ -233,8 +209,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // Internally invoked whenever the text changes in some way. void TextChanged(); - // Save |selected_text| as the PRIMARY X selection. Unlike - // OwnPrimarySelection(), this won't set an owner or use callbacks. + // Save |selected_text| as the PRIMARY X selection. void SavePrimarySelection(const std::string& selected_text); // Update the field with |text| and set the selection. @@ -264,7 +239,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, GtkTextBuffer* text_buffer_; GtkTextTag* faded_text_tag_; GtkTextTag* secure_scheme_tag_; - GtkTextTag* security_error_scheme_tag_; + GtkTextTag* insecure_scheme_tag_; GtkTextTag* normal_text_tag_; scoped_ptr<AutocompleteEditModel> model_; @@ -280,7 +255,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // different presentation (smaller font size). This is used for popups. bool popup_window_mode_; - ToolbarModel::SecurityLevel security_level_; + ToolbarModel::SecurityLevel scheme_security_level_; // Selection at the point where the user started using the // arrows to move around in the popup. @@ -297,12 +272,8 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // it, we pass this string to SavePrimarySelection()). std::string selected_text_; - // When we own the X clipboard, this is the text for it. - std::string primary_selection_text_; - - // IDs of the signal handlers for "mark-set" on |text_buffer_|. + // ID of the signal handler for "mark-set" on |text_buffer_|. gulong mark_set_handler_id_; - gulong mark_set_handler_id2_; #if defined(OS_CHROMEOS) // The following variables are used to implement select-all-on-mouse-up, which diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h index 80f18e8..11bb62f 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,6 +13,7 @@ class AutocompleteEditController; class AutocompletePopupViewMac; +class BubblePositioner; class Clipboard; class Profile; class ToolbarModel; @@ -23,6 +24,7 @@ class AutocompleteEditViewMac : public AutocompleteEditView, public AutocompleteTextFieldObserver { public: AutocompleteEditViewMac(AutocompleteEditController* controller, + const BubblePositioner* bubble_positioner, ToolbarModel* toolbar_model, Profile* profile, CommandUpdater* command_updater, @@ -46,10 +48,6 @@ class AutocompleteEditViewMac : public AutocompleteEditView, const std::wstring& keyword); virtual std::wstring GetText() const; - - virtual bool IsEditingOrEmpty() const; - virtual int GetIcon() const; - virtual void SetUserText(const std::wstring& text) { SetUserText(text, text, true); } @@ -100,10 +98,6 @@ class AutocompleteEditViewMac : public AutocompleteEditView, // empty string if no appropriate data is found on |clipboard|. static std::wstring GetClipboardText(Clipboard* clipboard); - // If |resource_id| has a PDF image which can be used, return it. - // Otherwise return the PNG image from the resource bundle. - static NSImage* ImageForResource(int resource_id); - private: // Called when the user hits backspace in |field_|. Checks whether // keyword search is being terminated. Returns true if the diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm index 61ff69dd..81a3daf 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm @@ -9,7 +9,6 @@ #include "app/clipboard/clipboard.h" #include "app/clipboard/scoped_clipboard_writer.h" #include "app/resource_bundle.h" -#include "base/nsimage_cache_mac.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" @@ -21,7 +20,6 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/toolbar_model.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" #include "net/base/escape.h" // Focus-handling between |field_| and |model_| is a bit subtle. @@ -63,6 +61,15 @@ const NSColor* ColorWithRGBBytes(int rr, int gg, int bb) { blue:static_cast<float>(bb)/255.0 alpha:1.0]; } +const NSColor* SecureBackgroundColor() { + return ColorWithRGBBytes(255, 245, 195); // Yellow +} +const NSColor* NormalBackgroundColor() { + return [NSColor controlBackgroundColor]; +} +const NSColor* InsecureBackgroundColor() { + return [NSColor controlBackgroundColor]; +} const NSColor* HostTextColor() { return [NSColor blackColor]; @@ -70,14 +77,11 @@ const NSColor* HostTextColor() { const NSColor* BaseTextColor() { return [NSColor darkGrayColor]; } -const NSColor* EVSecureSchemeColor() { - return ColorWithRGBBytes(0x07, 0x95, 0x00); -} const NSColor* SecureSchemeColor() { - return ColorWithRGBBytes(0x00, 0x0e, 0x95); + return ColorWithRGBBytes(0x00, 0x96, 0x14); } -const NSColor* SecurityErrorSchemeColor() { - return ColorWithRGBBytes(0xa2, 0x00, 0x00); +const NSColor* InsecureSchemeColor() { + return ColorWithRGBBytes(0xc8, 0x00, 0x00); } // Store's the model and view state across tab switches. @@ -121,57 +125,20 @@ NSRange ComponentToNSRange(const url_parse::Component& component) { } // namespace -// static -NSImage* AutocompleteEditViewMac::ImageForResource(int resource_id) { - NSString* image_name = nil; - - switch(resource_id) { - // From the autocomplete popup, or the star icon at the RHS of the - // text field. - case IDR_OMNIBOX_STAR: image_name = @"omnibox_star.pdf"; break; - case IDR_OMNIBOX_STAR_LIT: image_name = @"omnibox_star_lit.pdf"; break; - - // Values from |AutocompleteMatch::TypeToIcon()|. - case IDR_OMNIBOX_SEARCH: image_name = @"omnibox_search.pdf"; break; - case IDR_OMNIBOX_HTTP: image_name = @"omnibox_http.pdf"; break; - case IDR_OMNIBOX_HISTORY: image_name = @"omnibox_history.pdf"; break; - case IDR_OMNIBOX_MORE: image_name = @"omnibox_more.pdf"; break; - - // Values from |ToolbarModel::GetIcon()|. - case IDR_OMNIBOX_HTTPS_VALID: - image_name = @"omnibox_https_valid.pdf"; break; - case IDR_OMNIBOX_HTTPS_WARNING: - image_name = @"omnibox_https_warning.pdf"; break; - case IDR_OMNIBOX_HTTPS_INVALID: - image_name = @"omnibox_https_invalid.pdf"; break; - } - - if (image_name) { - if (NSImage* image = nsimage_cache::ImageNamed(image_name)) { - return image; - } else { - NOTREACHED() - << "Missing image for " << base::SysNSStringToUTF8(image_name); - } - } - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - return rb.GetNSImageNamed(resource_id); -} - // TODO(shess): AutocompletePopupViewMac doesn't really need an // NSTextField. It wants to know where the position the popup, what // font to use, and it also needs to be able to attach the popup to // the window |field_| is in. AutocompleteEditViewMac::AutocompleteEditViewMac( AutocompleteEditController* controller, + const BubblePositioner* bubble_positioner, ToolbarModel* toolbar_model, Profile* profile, CommandUpdater* command_updater, AutocompleteTextField* field) : model_(new AutocompleteEditModel(this, controller, profile)), - popup_view_(new AutocompletePopupViewMac(this, model_.get(), profile, - field)), + popup_view_(new AutocompletePopupViewMac( + this, model_.get(), bubble_positioner, profile, field)), controller_(controller), toolbar_model_(toolbar_model), command_updater_(command_updater), @@ -305,17 +272,6 @@ std::wstring AutocompleteEditViewMac::GetText() const { return base::SysNSStringToWide([field_ stringValue]); } -bool AutocompleteEditViewMac::IsEditingOrEmpty() const { - return model_->user_input_in_progress() || - ([[field_ stringValue] length] == 0); -} - -int AutocompleteEditViewMac::GetIcon() const { - return IsEditingOrEmpty() ? - AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : - toolbar_model_->GetIcon(); -} - void AutocompleteEditViewMac::SetUserText(const std::wstring& text, const std::wstring& display_text, bool update_popup) { @@ -454,23 +410,32 @@ void AutocompleteEditViewMac::SetText(const std::wstring& display_text) { // TODO(shess): GTK has this as a member var, figure out why. // [Could it be to not change if no change? If so, I'm guessing // AppKit may already handle that.] - const ToolbarModel::SecurityLevel security_level = - toolbar_model_->GetSecurityLevel(); + const ToolbarModel::SecurityLevel scheme_security_level = + toolbar_model_->GetSchemeSecurityLevel(); + + if (scheme_security_level == ToolbarModel::SECURE) { + [field_ setBackgroundColor:SecureBackgroundColor()]; + } else if (scheme_security_level == ToolbarModel::NORMAL) { + [field_ setBackgroundColor:NormalBackgroundColor()]; + } else if (scheme_security_level == ToolbarModel::INSECURE) { + [field_ setBackgroundColor:InsecureBackgroundColor()]; + } else { + NOTREACHED() << "Unexpected scheme_security_level: " + << scheme_security_level; + } // Emphasize the scheme for security UI display purposes (if necessary). if (!model_->user_input_in_progress() && scheme.is_nonempty() && - (security_level != ToolbarModel::NONE)) { + (scheme_security_level != ToolbarModel::NORMAL)) { NSColor* color; - if (security_level == ToolbarModel::EV_SECURE) { - color = EVSecureSchemeColor(); - } else if (security_level == ToolbarModel::SECURITY_ERROR) { - color = SecurityErrorSchemeColor(); + if (scheme_security_level == ToolbarModel::SECURE) { + color = SecureSchemeColor(); + } else { + color = InsecureSchemeColor(); // Add a strikethrough through the scheme. [as addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:ComponentToNSRange(scheme)]; - } else { - color = SecureSchemeColor(); } [as addAttribute:NSForegroundColorAttributeName value:color range:ComponentToNSRange(scheme)]; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 5a0632f..6ead1fe 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -28,6 +28,7 @@ #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/autocomplete/autocomplete_accessibility.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/autocomplete/autocomplete_popup_view.h" #include "chrome/browser/autocomplete/keyword_provider.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/command_updater.h" @@ -386,10 +387,10 @@ AutocompleteEditViewWin::AutocompleteEditViewWin( Profile* profile, CommandUpdater* command_updater, bool popup_window_mode, - const views::View* location_bar) + const BubblePositioner* bubble_positioner) : model_(new AutocompleteEditModel(this, controller, profile)), - popup_view_(new AutocompletePopupContentsView(font, this, model_.get(), - profile, location_bar)), + popup_view_(AutocompletePopupView::CreatePopupView( + font, this, model_.get(), profile, bubble_positioner)), controller_(controller), parent_view_(parent_view), toolbar_model_(toolbar_model), @@ -406,9 +407,8 @@ AutocompleteEditViewWin::AutocompleteEditViewWin( in_drag_(false), initiated_drag_(false), drop_highlight_position_(-1), - background_color_(skia::SkColorToCOLORREF(LocationBarView::GetColor( - ToolbarModel::NONE, LocationBarView::BACKGROUND))), - security_level_(ToolbarModel::NONE), + background_color_(0), + scheme_security_level_(ToolbarModel::NORMAL), text_object_model_(NULL) { // Dummy call to a function exported by riched20.dll to ensure it sets up an // import dependency on the dll. @@ -459,8 +459,6 @@ AutocompleteEditViewWin::AutocompleteEditViewWin( cf.yOffset = -font_y_adjustment_ * kTwipsPerPixel; SetDefaultCharFormat(cf); - SetBackgroundColor(background_color_); - // By default RichEdit has a drop target. Revoke it so that we can install our // own. Revoke takes care of deleting the existing one. RevokeDragDrop(m_hWnd); @@ -510,21 +508,30 @@ void AutocompleteEditViewWin::Update( model_->UpdatePermanentText(toolbar_model_->GetText()); const ToolbarModel::SecurityLevel security_level = - toolbar_model_->GetSecurityLevel(); - const bool changed_security_level = (security_level != security_level_); + toolbar_model_->GetSchemeSecurityLevel(); + const COLORREF background_color = + skia::SkColorToCOLORREF(LocationBarView::GetColor( + security_level == ToolbarModel::SECURE, LocationBarView::BACKGROUND)); + const bool changed_security_level = + (security_level != scheme_security_level_); // Bail early when no visible state will actually change (prevents an // unnecessary ScopedFreeze, and thus UpdateWindow()). - if (!changed_security_level && !visibly_changed_permanent_text && - !tab_for_state_restoring) + if ((background_color == background_color_) && !changed_security_level && + !visibly_changed_permanent_text && !tab_for_state_restoring) return; - // Update our local state as desired. We set security_level_ here so it will - // already be correct before we get to any RevertAll()s below and use it. - security_level_ = security_level; + // Update our local state as desired. We set scheme_security_level_ here so + // it will already be correct before we get to any RevertAll()s below and use + // it. + ScopedFreeze freeze(this, GetTextObjectModel()); + if (background_color_ != background_color) { + background_color_ = background_color; + SetBackgroundColor(background_color_); + } + scheme_security_level_ = security_level; // When we're switching to a new tab, restore its state, if any. - ScopedFreeze freeze(this, GetTextObjectModel()); if (tab_for_state_restoring) { // Make sure we reset our own state first. The new tab may not have any // saved state, or it may not have had input in progress, in which case we @@ -598,16 +605,6 @@ std::wstring AutocompleteEditViewWin::GetText() const { return str; } -bool AutocompleteEditViewWin::IsEditingOrEmpty() const { - return model_->user_input_in_progress() || (GetTextLength() == 0); -} - -int AutocompleteEditViewWin::GetIcon() const { - return IsEditingOrEmpty() ? - AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : - toolbar_model_->GetIcon(); -} - void AutocompleteEditViewWin::SetUserText(const std::wstring& text, const std::wstring& display_text, bool update_popup) { @@ -1372,6 +1369,15 @@ void AutocompleteEditViewWin::OnKillFocus(HWND focus_wnd) { ScopedFreeze freeze(this, GetTextObjectModel()); DefWindowProc(WM_KILLFOCUS, reinterpret_cast<WPARAM>(focus_wnd), 0); + // Hide the "Type to search" hint if necessary. We do this after calling + // DefWindowProc() because processing the resulting IME messages may notify + // the controller that input is in progress, which could cause the visible + // hints to change. (I don't know if there's a real scenario where they + // actually do change, but this is safest.) + if (model_->show_search_hint() || + (model_->is_keyword_hint() && !model_->keyword().empty())) + controller_->OnChanged(); + // Cancel any user selection and scroll the text back to the beginning of the // URL. We have to do this after calling DefWindowProc() because otherwise // an in-progress IME composition will be completed at the new caret position, @@ -1681,6 +1687,12 @@ void AutocompleteEditViewWin::OnSetFocus(HWND focus_wnd) { model_->OnSetFocus(GetKeyState(VK_CONTROL) < 0); + // Notify controller if it needs to show hint UI of some kind. + ScopedFreeze freeze(this, GetTextObjectModel()); + if (model_->show_search_hint() || + (model_->is_keyword_hint() && !model_->keyword().empty())) + controller_->OnChanged(); + // Restore saved selection if available. if (saved_selection_for_focus_change_.cpMin != -1) { SetSelectionRange(saved_selection_for_focus_change_); @@ -2048,11 +2060,11 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() { // Set the baseline emphasis. CHARFORMAT cf = {0}; cf.dwMask = CFM_COLOR; + const bool is_secure = (scheme_security_level_ == ToolbarModel::SECURE); // If we're going to emphasize parts of the text, then the baseline state // should be "de-emphasized". If not, then everything should be rendered in // the standard text color. - cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( - security_level_, + cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor(is_secure, emphasize ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT)); // NOTE: Don't use SetDefaultCharFormat() instead of the below; that sets the // format that will get applied to text added in the future, not to text @@ -2063,7 +2075,7 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() { if (emphasize) { // We've found a host name, give it more emphasis. cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( - security_level_, LocationBarView::TEXT)); + is_secure, LocationBarView::TEXT)); SetSelection(host.begin, host.end()); SetSelectionCharFormat(cf); } @@ -2071,13 +2083,13 @@ void AutocompleteEditViewWin::EmphasizeURLComponents() { // Emphasize the scheme for security UI display purposes (if necessary). insecure_scheme_component_.reset(); if (!model_->user_input_in_progress() && scheme.is_nonempty() && - (security_level_ != ToolbarModel::NONE)) { - if (security_level_ == ToolbarModel::SECURITY_ERROR) { + (scheme_security_level_ != ToolbarModel::NORMAL)) { + if (!is_secure) { insecure_scheme_component_.begin = scheme.begin; insecure_scheme_component_.len = scheme.len; } cf.crTextColor = skia::SkColorToCOLORREF(LocationBarView::GetColor( - security_level_, LocationBarView::SECURITY_TEXT)); + is_secure, LocationBarView::SECURITY_TEXT)); SetSelection(scheme.begin, scheme.end()); SetSelectionCharFormat(cf); } @@ -2171,8 +2183,8 @@ void AutocompleteEditViewWin::DrawSlashForInsecureScheme( canvas.save(); if (selection_rect.isEmpty() || canvas.clipRect(selection_rect, SkRegion::kDifference_Op)) { - paint.setColor(LocationBarView::GetColor(security_level_, - LocationBarView::SECURITY_TEXT)); + paint.setColor(LocationBarView::GetColor(false, + LocationBarView::SCHEME_STRIKEOUT)); canvas.drawLine(start_point.fX, start_point.fY, end_point.fX, end_point.fY, paint); } @@ -2180,7 +2192,7 @@ void AutocompleteEditViewWin::DrawSlashForInsecureScheme( // Draw the selected portion of the stroke. if (!selection_rect.isEmpty() && canvas.clipRect(selection_rect)) { - paint.setColor(LocationBarView::GetColor(security_level_, + paint.setColor(LocationBarView::GetColor(false, LocationBarView::SELECTED_TEXT)); canvas.drawLine(start_point.fX, start_point.fY, end_point.fX, end_point.fY, paint); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h index 33af6a7..9de2d34 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h @@ -69,7 +69,7 @@ class AutocompleteEditViewWin Profile* profile, CommandUpdater* command_updater, bool popup_window_mode, - const views::View* location_bar); + const BubblePositioner* bubble_positioner); ~AutocompleteEditViewWin(); views::View* parent_view() const { return parent_view_; } @@ -91,9 +91,6 @@ class AutocompleteEditViewWin virtual std::wstring GetText() const; - virtual bool IsEditingOrEmpty() const; - virtual int GetIcon() const; - virtual void SetUserText(const std::wstring& text) { SetUserText(text, text, true); } @@ -479,7 +476,7 @@ class AutocompleteEditViewWin // Security UI-related data. COLORREF background_color_; - ToolbarModel::SecurityLevel security_level_; + ToolbarModel::SecurityLevel scheme_security_level_; // This interface is useful for accessing the CRichEditCtrl at a low level. mutable ITextDocument* text_object_model_; diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.cc b/chrome/browser/autocomplete/autocomplete_popup_model.cc index 009cc0b..41e0255 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_model.cc +++ b/chrome/browser/autocomplete/autocomplete_popup_model.cc @@ -103,24 +103,12 @@ void AutocompletePopupModel::SetSelectedLine(size_t line, if (line == selected_line_) return; // Nothing else to do. - // We need to update |selected_line_| before calling OnPopupDataChanged(), so - // that when the edit notifies its controller that something has changed, the - // controller can get the correct updated data. - // - // NOTE: We should never reach here with no selected line; the same code that - // opened the popup and made it possible to get here should have also set a - // selected line. - CHECK(selected_line_ != kNoMatch); - GURL current_destination(result.match_at(selected_line_).destination_url); - view_->InvalidateLine(selected_line_); - selected_line_ = line; - view_->InvalidateLine(selected_line_); - // Update the edit with the new data for this match. // TODO(pkasting): If |selected_line_| moves to the controller, this can be // eliminated and just become a call to the observer on the edit. std::wstring keyword; const bool is_keyword_hint = GetKeywordForMatch(match, &keyword); + if (reset_to_default) { std::wstring inline_autocomplete_text; if ((match.inline_autocomplete_offset != std::wstring::npos) && @@ -128,15 +116,27 @@ void AutocompletePopupModel::SetSelectedLine(size_t line, inline_autocomplete_text = match.fill_into_edit.substr(match.inline_autocomplete_offset); } - edit_model_->OnPopupDataChanged(inline_autocomplete_text, NULL, - keyword, is_keyword_hint); + edit_model_->OnPopupDataChanged(inline_autocomplete_text, false, + keyword, is_keyword_hint, match.type); } else { - edit_model_->OnPopupDataChanged(match.fill_into_edit, ¤t_destination, - keyword, is_keyword_hint); + edit_model_->OnPopupDataChanged(match.fill_into_edit, true, + keyword, is_keyword_hint, match.type); } // Repaint old and new selected lines immediately, so that the edit doesn't - // appear to update [much] faster than the popup. + // appear to update [much] faster than the popup. We must not update + // |selected_line_| before calling OnPopupDataChanged() (since the edit may + // call us back to get data about the old selection), and we must not call + // UpdateWindow() before updating |selected_line_| (since the paint routine + // relies on knowing the correct selected line). + // + // NOTE: We should never reach here with no selected line; the same code that + // opened the popup and made it possible to get here should have also set a + // selected line. + CHECK(selected_line_ != kNoMatch); + view_->InvalidateLine(selected_line_); + selected_line_ = line; + view_->InvalidateLine(selected_line_); view_->PaintUpdatesNow(); } @@ -147,21 +147,22 @@ void AutocompletePopupModel::ResetToDefaultMatch() { view_->OnDragCanceled(); } -void AutocompletePopupModel::InfoForCurrentSelection( - AutocompleteMatch* match, +GURL AutocompletePopupModel::URLsForCurrentSelection( + PageTransition::Type* transition, + bool* is_history_what_you_typed_match, GURL* alternate_nav_url) const { - DCHECK(match != NULL); const AutocompleteResult* result; + AutocompleteResult::const_iterator match; if (!controller_->done()) { result = &controller_->latest_result(); // It's technically possible for |result| to be empty if no provider returns // a synchronous result but the query has not completed synchronously; // pratically, however, that should never actually happen. if (result->empty()) - return; + return GURL(); // The user cannot have manually selected a match, or the query would have // stopped. So the default match must be the desired selection. - *match = *result->default_match(); + match = result->default_match(); } else { CHECK(IsOpen()); // The query isn't running, so the standard result set can't possibly be out @@ -176,10 +177,15 @@ void AutocompletePopupModel::InfoForCurrentSelection( // called instead. CHECK(!result->empty()); CHECK(selected_line_ < result->size()); - *match = result->match_at(selected_line_); + match = result->begin() + selected_line_; } + if (transition) + *transition = match->transition; + if (is_history_what_you_typed_match) + *is_history_what_you_typed_match = match->is_history_what_you_typed_match; if (alternate_nav_url && manually_selected_match_.empty()) *alternate_nav_url = result->alternate_nav_url(); + return match->destination_url; } bool AutocompletePopupModel::GetKeywordForMatch(const AutocompleteMatch& match, @@ -233,7 +239,7 @@ void AutocompletePopupModel::Move(int count) { } void AutocompletePopupModel::TryDeletingCurrentItem() { - // We could use InfoForCurrentSelection() here, but it seems better to try + // We could use URLsForCurrentSelection() here, but it seems better to try // and shift-delete the actual selection, rather than any "in progress, not // yet visible" one. if (selected_line_ == kNoMatch) diff --git a/chrome/browser/autocomplete/autocomplete_popup_model.h b/chrome/browser/autocomplete/autocomplete_popup_model.h index a986419..166a238 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_model.h +++ b/chrome/browser/autocomplete/autocomplete_popup_model.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -73,9 +73,15 @@ class AutocompletePopupModel : public NotificationObserver { // will change the selected line back to the default match and redraw. void ResetToDefaultMatch(); - // Copies the selected match into |match|. If an update is in progress, - // "selected" means "default in the latest matches". If there are no matches, - // does not update |match|. + // Returns the URL for the selected match. If an update is in progress, + // "selected" means "default in the latest matches". If there are no + // matches, returns the empty string. + // + // If |transition_type| is non-NULL, it will be set to the appropriate + // transition type for the selected entry (TYPED or GENERATED). + // + // If |is_history_what_you_typed_match| is non-NULL, it will be set based on + // the selected entry's is_history_what_you_typed value. // // If |alternate_nav_url| is non-NULL, it will be set to the alternate // navigation URL for |url| if one exists, or left unchanged otherwise. See @@ -83,8 +89,10 @@ class AutocompletePopupModel : public NotificationObserver { // // TODO(pkasting): When manually_selected_match_ moves to the controller, this // can move too. - void InfoForCurrentSelection(AutocompleteMatch* match, - GURL* alternate_nav_url) const; + GURL URLsForCurrentSelection( + PageTransition::Type* transition, + bool* is_history_what_you_typed_match, + GURL* alternate_nav_url) const; // Gets the selected keyword or keyword hint for the given match. Returns // true if |keyword| represents a keyword hint, or false if |keyword| diff --git a/chrome/browser/autocomplete/autocomplete_popup_view.h b/chrome/browser/autocomplete/autocomplete_popup_view.h index 5674e4b..41b21a6 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view.h +++ b/chrome/browser/autocomplete/autocomplete_popup_view.h @@ -13,7 +13,15 @@ #include "build/build_config.h" +class AutocompleteEditView; class AutocompletePopupModel; +class BubblePositioner; +namespace gfx { +class Font; +} +class AutocompleteEditViewWin; +class AutocompleteEditModel; +class Profile; class AutocompletePopupView { public: @@ -40,6 +48,17 @@ class AutocompletePopupView { // Returns the popup's model. virtual AutocompletePopupModel* GetModel() = 0; + +#if !defined(OS_MACOSX) + // Create a popup view implementation. It may make sense for this to become + // platform independent eventually. + static AutocompletePopupView* CreatePopupView( + const gfx::Font& font, + AutocompleteEditView* edit_view, + AutocompleteEditModel* edit_model, + Profile* profile, + const BubblePositioner* bubble_positioner); +#endif }; #endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_POPUP_VIEW_H_ diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc index 46a2115..84538e0f 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -18,18 +18,16 @@ #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/defaults.h" -#include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/common/notification_service.h" -#include "gfx/color_utils.h" #include "gfx/font.h" #include "gfx/gtk_util.h" #include "gfx/rect.h" -#include "gfx/skia_utils_gtk.h" #include "grit/theme_resources.h" namespace { @@ -46,40 +44,27 @@ const GdkColor kDescriptionSelectedTextColor = GDK_COLOR_RGB(0x78, 0x82, 0xb1); // We have a 1 pixel border around the entire results popup. const int kBorderThickness = 1; - // The vertical height of each result. const int kHeightPerResult = 24; - // Width of the icons. -const int kIconWidth = 17; - +const int kIconWidth = 16; // We want to vertically center the image in the result space. -const int kIconTopPadding = 2; - +const int kIconTopPadding = 4; // Space between the left edge (including the border) and the text. -const int kIconLeftPadding = 5 + kBorderThickness; - -// Space between the image and the text. -const int kIconRightPadding = 7; - +const int kIconLeftPadding = 6 + kBorderThickness; +// Space between the image and the text. Would be 6 to line up with the +// entry, but nudge it a bit more to match with the text in the entry. +const int kIconRightPadding = 10; // Space between the left edge (including the border) and the text. const int kIconAreaWidth = kIconLeftPadding + kIconWidth + kIconRightPadding; - // Space between the right edge (including the border) and the text. const int kRightPadding = 3; - // When we have both a content and description string, we don't want the // content to push the description off. Limit the content to a percentage of // the total width. const float kContentWidthPercentage = 0.7; -// How much to offset the popup from the bottom of the location bar in gtk mode. -const int kGtkVerticalOffset = 3; - -// How much we shrink the popup on the left/right in gtk mode. -const int kGtkHorizontalOffset = 1; - // UTF-8 Left-to-right embedding. const char* kLRE = "\xe2\x80\xaa"; @@ -118,7 +103,6 @@ void SetupLayoutForMatch(PangoLayout* layout, const std::wstring& text, AutocompleteMatch::ACMatchClassifications classifications, const GdkColor* base_color, - const GdkColor* url_color, const std::string& prefix_text) { // We can have a prefix, or insert additional characters while processing the @@ -155,7 +139,7 @@ void SetupLayoutForMatch(PangoLayout* layout, // support it. const GdkColor* color = base_color; if (i->style & ACMatchClassification::URL) { - color = url_color; + color = &kURLTextColor; // Insert a left to right embedding to make sure that URLs are shown LTR. std::string lre(kLRE); text_utf8.insert(offset, lre); @@ -180,81 +164,48 @@ void SetupLayoutForMatch(PangoLayout* layout, pango_attr_list_unref(attrs); } -GdkPixbuf* IconForMatch(BrowserThemeProvider* theme, - const AutocompleteMatch& match, - bool selected) { - int icon = match.starred ? - IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); - if (selected) { - switch (icon) { - case IDR_OMNIBOX_HTTP: icon = IDR_OMNIBOX_HTTP_DARK; break; - case IDR_OMNIBOX_HISTORY: icon = IDR_OMNIBOX_HISTORY_DARK; break; - case IDR_OMNIBOX_SEARCH: icon = IDR_OMNIBOX_SEARCH_DARK; break; - case IDR_OMNIBOX_MORE: icon = IDR_OMNIBOX_MORE_DARK; break; - case IDR_OMNIBOX_STAR: icon = IDR_OMNIBOX_STAR_DARK; break; - default: NOTREACHED(); break; - } - } - +GdkPixbuf* IconForMatch(const AutocompleteMatch& match, bool selected) { + // TODO(deanm): These would be better as pixmaps someday. // TODO(estade): Do we want to flip these for RTL? (Windows doesn't). - return theme->GetPixbufNamed(icon); -} - -// Generates the normal URL color, a green color used in unhighlighted URL -// text. It is a mix of |kURLTextColor| and the current text color. Unlike the -// selected text color, It is more important to match the qualities of the -// foreground typeface color instead of taking the background into account. -GdkColor NormalURLColor(GdkColor foreground) { - color_utils::HSL fg_hsl; - color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl); - - color_utils::HSL hue_hsl; - color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl); - - // Only allow colors that have a fair amount of saturation in them (color vs - // white). This means that our output color will always be fairly green. - double s = std::max(0.5, fg_hsl.s); - - // Make sure the luminance is at least as bright as the |kURLTextColor| green - // would be if we were to use that. - double l; - if (fg_hsl.l < hue_hsl.l) - l = hue_hsl.l; - else - l = (fg_hsl.l + hue_hsl.l) / 2; - - color_utils::HSL output = { hue_hsl.h, s, l }; - return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255)); -} + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + static GdkPixbuf* o2_globe = rb.GetPixbufNamed(IDR_O2_GLOBE); + static GdkPixbuf* o2_globe_s = rb.GetPixbufNamed(IDR_O2_GLOBE_SELECTED_DARK); + static GdkPixbuf* o2_history = rb.GetPixbufNamed(IDR_O2_HISTORY); + static GdkPixbuf* o2_history_s = + rb.GetPixbufNamed(IDR_O2_HISTORY_SELECTED_DARK); + static GdkPixbuf* o2_more = rb.GetPixbufNamed(IDR_O2_MORE); + static GdkPixbuf* o2_more_s = rb.GetPixbufNamed(IDR_O2_MORE_SELECTED_DARK); + static GdkPixbuf* o2_search = rb.GetPixbufNamed(IDR_O2_SEARCH); + static GdkPixbuf* o2_search_s = + rb.GetPixbufNamed(IDR_O2_SEARCH_SELECTED_DARK); + static GdkPixbuf* o2_star = rb.GetPixbufNamed(IDR_O2_STAR); + static GdkPixbuf* o2_star_s = rb.GetPixbufNamed(IDR_O2_STAR_SELECTED_DARK); + + if (match.starred) + return selected ? o2_star_s : o2_star; + + switch (match.type) { + case AutocompleteMatch::URL_WHAT_YOU_TYPED: + case AutocompleteMatch::NAVSUGGEST: + return selected ? o2_globe_s : o2_globe; + case AutocompleteMatch::HISTORY_URL: + case AutocompleteMatch::HISTORY_TITLE: + case AutocompleteMatch::HISTORY_BODY: + case AutocompleteMatch::HISTORY_KEYWORD: + return selected ? o2_history_s : o2_history; + case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatch::SEARCH_HISTORY: + case AutocompleteMatch::SEARCH_SUGGEST: + case AutocompleteMatch::SEARCH_OTHER_ENGINE: + return selected ? o2_search_s : o2_search; + case AutocompleteMatch::OPEN_HISTORY_PAGE: + return selected ? o2_more_s : o2_more; + default: + NOTREACHED(); + break; + } -// Generates the selected URL color, a green color used on URL text in the -// currently highlighted entry in the autocomplete popup. It's a mix of -// |kURLTextColor|, the current text color, and the background color (the -// select highlight). It is more important to contrast with the background -// saturation than to look exactly like the foreground color. -GdkColor SelectedURLColor(GdkColor foreground, GdkColor background) { - color_utils::HSL fg_hsl; - color_utils::SkColorToHSL(gfx::GdkColorToSkColor(foreground), &fg_hsl); - - color_utils::HSL bg_hsl; - color_utils::SkColorToHSL(gfx::GdkColorToSkColor(background), &bg_hsl); - - color_utils::HSL hue_hsl; - color_utils::SkColorToHSL(gfx::GdkColorToSkColor(kURLTextColor), &hue_hsl); - - // The saturation of the text should be opposite of the background, clamped - // to 0.2-0.8. We make sure it's greater than 0.2 so there's some color, but - // less than 0.8 so it's not the oversaturated neon-color. - double opposite_s = 1 - bg_hsl.s; - double s = std::max(0.2, std::min(0.8, opposite_s)); - - // The luminance should match the luminance of the foreground text. Again, - // we clamp so as to have at some amount of color (green) in the text. - double opposite_l = fg_hsl.l; - double l = std::max(0.1, std::min(0.9, opposite_l)); - - color_utils::HSL output = { hue_hsl.h, s, l }; - return gfx::SkColorToGdkColor(color_utils::HSLToSkColor(output, 255)); + return NULL; } } // namespace @@ -263,13 +214,12 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk( AutocompleteEditView* edit_view, AutocompleteEditModel* edit_model, Profile* profile, - GtkWidget* location_bar) + const BubblePositioner* bubble_positioner) : model_(new AutocompletePopupModel(this, edit_model, profile)), edit_view_(edit_view), - location_bar_(location_bar), + bubble_positioner_(bubble_positioner), window_(gtk_window_new(GTK_WINDOW_POPUP)), layout_(NULL), - theme_provider_(GtkThemeProvider::GetFrom(profile)), opened_(false) { GTK_WIDGET_UNSET_FLAGS(window_, GTK_CAN_FOCUS); // Don't allow the window to be resized. This also forces the window to @@ -278,6 +228,8 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk( gtk_widget_set_app_paintable(window_, TRUE); // Have GTK double buffer around the expose signal. gtk_widget_set_double_buffered(window_, TRUE); + // Set the background color, so we don't need to paint it manually. + gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &kBackgroundColor); // Cache the layout so we don't have to create it for every expose. If we // were a real widget we should handle changing directions, but we're not @@ -310,11 +262,6 @@ AutocompletePopupViewGtk::AutocompletePopupViewGtk( g_signal_connect(window_, "expose-event", G_CALLBACK(&HandleExposeThunk), this); - registrar_.Add(this, - NotificationType::BROWSER_THEME_CHANGED, - NotificationService::AllSources()); - theme_provider_->InitThemesFor(this); - // TODO(erg): There appears to be a bug somewhere in something which shows // itself when we're in NX. Previously, we called // gtk_util::ActAsRoundedWindow() to make this popup have rounded @@ -365,85 +312,16 @@ AutocompletePopupModel* AutocompletePopupViewGtk::GetModel() { return model_.get(); } -void AutocompletePopupViewGtk::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::BROWSER_THEME_CHANGED); - - if (theme_provider_->UseGtkTheme()) { - border_color_ = theme_provider_->GetBorderColor(); - - // Create a fake gtk table - GtkWidget* fake_tree = gtk_entry_new(); - GtkStyle* style = gtk_rc_get_style(fake_tree); - - background_color_ = style->base[GTK_STATE_NORMAL]; - selected_background_color_ = style->base[GTK_STATE_SELECTED]; - hovered_background_color_ = gtk_util::AverageColors( - background_color_, selected_background_color_); - - content_text_color_ = style->text[GTK_STATE_NORMAL]; - selected_content_text_color_ = style->text[GTK_STATE_SELECTED]; - url_text_color_ = - NormalURLColor(style->text[GTK_STATE_NORMAL]); - url_selected_text_color_ = - SelectedURLColor(style->text[GTK_STATE_SELECTED], - style->base[GTK_STATE_SELECTED]); - - description_text_color_ = style->text[GTK_STATE_NORMAL]; - description_selected_text_color_ = style->text[GTK_STATE_SELECTED]; - - g_object_ref_sink(fake_tree); - g_object_unref(fake_tree); - } else { - border_color_ = kBorderColor; - background_color_ = kBackgroundColor; - selected_background_color_ = kSelectedBackgroundColor; - hovered_background_color_ = kHoveredBackgroundColor; - - content_text_color_ = kContentTextColor; - selected_content_text_color_ = kContentTextColor; - url_text_color_ = kURLTextColor; - url_selected_text_color_ = kURLTextColor; - description_text_color_ = kDescriptionTextColor; - description_selected_text_color_ = kDescriptionSelectedTextColor; - } - - // Set the background color, so we don't need to paint it manually. - gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &background_color_); -} - void AutocompletePopupViewGtk::Show(size_t num_results) { - gint origin_x, origin_y; - gdk_window_get_origin(location_bar_->window, &origin_x, &origin_y); - GtkAllocation allocation = location_bar_->allocation; - int vertical_offset = 0; - int horizontal_offset = 0; - if (theme_provider_->UseGtkTheme()) { - // Shrink the popup by 1 pixel on both sides in gtk mode. The darkest line - // is usually one pixel in, and is almost always +/-1 pixel from this, - // meaning the vertical offset will hide (hopefully) problems when this is - // wrong. - horizontal_offset = kGtkHorizontalOffset; - - // We offset the the popup from the bottom of the location bar in gtk - // mode. The background color between the bottom of the location bar and - // the popup helps hide the fact that we can't really reliably match what - // the user would otherwise preceive as the left/right edges of the - // location bar. - vertical_offset = kGtkVerticalOffset; - } - - gtk_window_move(GTK_WINDOW(window_), - origin_x + allocation.x - kBorderThickness + horizontal_offset, - origin_y + allocation.y + allocation.height - kBorderThickness - 1 + - vertical_offset); - gtk_widget_set_size_request(window_, - allocation.width + (kBorderThickness * 2) - (horizontal_offset * 2), - (num_results * kHeightPerResult) + (kBorderThickness * 2)); - gtk_widget_show(window_); - StackWindow(); - opened_ = true; + gfx::Rect rect = bubble_positioner_->GetLocationStackBounds(); + rect.set_y(rect.bottom()); + rect.set_height((num_results * kHeightPerResult) + (kBorderThickness * 2)); + + gtk_window_move(GTK_WINDOW(window_), rect.x(), rect.y()); + gtk_widget_set_size_request(window_, rect.width(), rect.height()); + gtk_widget_show(window_); + StackWindow(); + opened_ = true; } void AutocompletePopupViewGtk::Hide() { @@ -536,7 +414,7 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, GdkGC* gc = gdk_gc_new(drawable); // kBorderColor is unallocated, so use the GdkRGB routine. - gdk_gc_set_rgb_fg_color(gc, &border_color_); + gdk_gc_set_rgb_fg_color(gc, &kBorderColor); // This assert is kinda ugly, but it would be more currently unneeded work // to support painting a border that isn't 1 pixel thick. There is no point @@ -549,17 +427,8 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE); - // An offset to align text in gtk mode. The hard coded constants in this file - // are all created for the chrome-theme. In an effort to make this look good - // on the majority of gtk themes, we shrink the popup by one pixel on each - // side and push it downwards a bit so there's space between the drawn - // location bar and the popup so we don't touch it (contrast with - // chrome-theme where that's exactly what we want). Because of that, we need - // to shift the content inside the popup by one pixel. - int gtk_offset = 0; - if (theme_provider_->UseGtkTheme()) - gtk_offset = kGtkHorizontalOffset; - + // TODO(deanm): Intersect the line and damage rects, and only repaint and + // layout the lines that are actually damaged. For now paint everything. for (size_t i = 0; i < result.size(); ++i) { gfx::Rect line_rect = GetRectForLine(i, window_rect.width()); // Only repaint and layout damaged lines. @@ -570,19 +439,18 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, bool is_selected = (model_->selected_line() == i); bool is_hovered = (model_->hovered_line() == i); if (is_selected || is_hovered) { - gdk_gc_set_rgb_fg_color(gc, is_selected ? &selected_background_color_ : - &hovered_background_color_); + gdk_gc_set_rgb_fg_color(gc, is_selected ? &kSelectedBackgroundColor : + &kHoveredBackgroundColor); // This entry is selected or hovered, fill a rect with the color. gdk_draw_rectangle(drawable, gc, TRUE, line_rect.x(), line_rect.y(), line_rect.width(), line_rect.height()); } - int icon_start_x = ltr ? (kIconLeftPadding - gtk_offset) : - (line_rect.width() - kIconLeftPadding - kIconWidth + gtk_offset); + int icon_start_x = ltr ? kIconLeftPadding : + line_rect.width() - kIconLeftPadding - kIconWidth; // Draw the icon for this result. - DrawFullPixbuf(drawable, gc, - IconForMatch(theme_provider_, match, is_selected), + DrawFullPixbuf(drawable, gc, IconForMatch(match, is_selected), icon_start_x, line_rect.y() + kIconTopPadding); // Draw the results text vertically centered in the results space. @@ -596,11 +464,7 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, // Note: We force to URL to LTR for all text directions. SetupLayoutForMatch(layout_, match.contents, match.contents_class, - is_selected ? &selected_content_text_color_ : - &content_text_color_, - is_selected ? &url_selected_text_color_ : - &url_text_color_, - std::string()); + &kContentTextColor, std::string()); int actual_content_width, actual_content_height; pango_layout_get_size(layout_, @@ -614,25 +478,22 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, line_rect.y() + ((kHeightPerResult - actual_content_height) / 2)); gdk_draw_layout(drawable, gc, - ltr ? (kIconAreaWidth - gtk_offset) : - (text_width - actual_content_width + gtk_offset), + ltr ? kIconAreaWidth : text_width - actual_content_width, content_y, layout_); if (has_description) { pango_layout_set_width(layout_, (text_width - actual_content_width) * PANGO_SCALE); SetupLayoutForMatch(layout_, match.description, match.description_class, - is_selected ? &description_selected_text_color_ : - &description_text_color_, - is_selected ? &url_selected_text_color_ : - &url_text_color_, + is_selected ? &kDescriptionSelectedTextColor : + &kDescriptionTextColor, std::string(" - ")); gint actual_description_width; pango_layout_get_size(layout_, &actual_description_width, NULL); - gdk_draw_layout(drawable, gc, ltr ? - (kIconAreaWidth - gtk_offset + actual_content_width) : - (text_width - actual_content_width + gtk_offset - - (actual_description_width / PANGO_SCALE)), + gdk_draw_layout(drawable, gc, + ltr ? kIconAreaWidth + actual_content_width : + text_width - actual_content_width - + actual_description_width / PANGO_SCALE, content_y, layout_); } } @@ -641,3 +502,14 @@ gboolean AutocompletePopupViewGtk::HandleExpose(GtkWidget* widget, return TRUE; } + +// static +AutocompletePopupView* AutocompletePopupView::CreatePopupView( + const gfx::Font& font, + AutocompleteEditView* edit_view, + AutocompleteEditModel* edit_model, + Profile* profile, + const BubblePositioner* bubble_positioner) { + return new AutocompletePopupViewGtk(edit_view, edit_model, profile, + bubble_positioner); +} diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h index 90cd2c9..f46cfb2 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_popup_view_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,27 +10,23 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" #include "chrome/browser/autocomplete/autocomplete_popup_view.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" #include "webkit/glue/window_open_disposition.h" class AutocompleteEditModel; class AutocompleteEditView; class AutocompletePopupModel; -class GtkThemeProvider; class Profile; class SkBitmap; -class AutocompletePopupViewGtk : public AutocompletePopupView, - public NotificationObserver { +class AutocompletePopupViewGtk : public AutocompletePopupView { public: AutocompletePopupViewGtk(AutocompleteEditView* edit_view, AutocompleteEditModel* edit_model, Profile* profile, - GtkWidget* location_bar); + const BubblePositioner* bubble_positioner); ~AutocompletePopupViewGtk(); - // Overridden from AutocompletePopupView: + // Implement the AutocompletePopupView interface. virtual bool IsOpen() const { return opened_; } virtual void InvalidateLine(size_t line); virtual void UpdatePopupAppearance(); @@ -38,11 +34,6 @@ class AutocompletePopupViewGtk : public AutocompletePopupView, virtual void OnDragCanceled() {} virtual AutocompletePopupModel* GetModel(); - // Overridden from NotificationObserver: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - private: void Show(size_t num_results); void Hide(); @@ -88,7 +79,7 @@ class AutocompletePopupViewGtk : public AutocompletePopupView, scoped_ptr<AutocompletePopupModel> model_; AutocompleteEditView* edit_view_; - GtkWidget* location_bar_; + const BubblePositioner* bubble_positioner_; // Our popup window, which is the only widget used, and we paint it on our // own. This widget shouldn't be exposed outside of this class. @@ -96,22 +87,6 @@ class AutocompletePopupViewGtk : public AutocompletePopupView, // The pango layout object created from the window, cached across exposes. PangoLayout* layout_; - GtkThemeProvider* theme_provider_; - NotificationRegistrar registrar_; - - // A list of colors which we should use for drawing the popup. These change - // between gtk and normal mode. - GdkColor border_color_; - GdkColor background_color_; - GdkColor selected_background_color_; - GdkColor hovered_background_color_; - GdkColor content_text_color_; - GdkColor selected_content_text_color_; - GdkColor url_text_color_; - GdkColor url_selected_text_color_; - GdkColor description_text_color_; - GdkColor description_selected_text_color_; - // Whether our popup is currently open / shown, or closed / hidden. bool opened_; diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h index 56d20fd..a430f58 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -32,6 +32,7 @@ class AutocompletePopupViewMac : public AutocompletePopupView { public: AutocompletePopupViewMac(AutocompleteEditViewMac* edit_view, AutocompleteEditModel* edit_model, + const BubblePositioner* bubble_positioner, Profile* profile, NSTextField* field); virtual ~AutocompletePopupViewMac(); @@ -108,6 +109,7 @@ class AutocompletePopupViewMac : public AutocompletePopupView { scoped_ptr<AutocompletePopupModel> model_; AutocompleteEditViewMac* edit_view_; + const BubblePositioner* bubble_positioner_; // owned by toolbar controller NSTextField* field_; // owned by tab controller // Child window containing a matrix which implements the popup. diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm index 29ea9ab..644c065 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,11 +10,11 @@ #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" +#include "chrome/browser/bubble_positioner.h" #include "chrome/browser/cocoa/event_utils.h" #include "gfx/rect.h" #include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" -#import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" namespace { @@ -31,17 +31,17 @@ const int kCellHeightAdjust = 7.0; const CGFloat kPopupRoundingRadius = 3.5; // Gap between the field and the popup. -const CGFloat kPopupFieldGap = 0.0; +const CGFloat kPopupFieldGap = 2.0; // How opaque the popup window should be. This matches Windows (see // autocomplete_popup_contents_view.cc, kGlassPopupTransparency). const CGFloat kPopupAlpha = 240.0 / 255.0; // How much space to leave for the left and right margins. -const CGFloat kLeftRightMargin = 5.0; +const CGFloat kLeftRightMargin = 8.0; // How far to offset the text column from the left. -const CGFloat kTextXOffset = 29.0; +const CGFloat kTextXOffset = 33.0; // Animation duration when animating the popup window smaller. const CGFloat kShrinkAnimationDuration = 0.1; @@ -78,6 +78,54 @@ static const NSColor* DescriptionTextColor() { return [NSColor darkGrayColor]; } +// Helper to fetch and retain an image from the resource bundle. +NSImage* RetainedResourceImage(int resource_id) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + NSImage* image = rb.GetNSImageNamed(resource_id); + DCHECK(image); + return [image retain]; +} + +// Return the appropriate icon for the given match. Derived from the +// gtk code. +NSImage* MatchIcon(const AutocompleteMatch& match) { + if (match.starred) { + static NSImage* starImage = RetainedResourceImage(IDR_O2_STAR); + return starImage; + } + + switch (match.type) { + case AutocompleteMatch::URL_WHAT_YOU_TYPED: + case AutocompleteMatch::NAVSUGGEST: { + static NSImage* globeImage = RetainedResourceImage(IDR_O2_GLOBE); + return globeImage; + } + case AutocompleteMatch::HISTORY_URL: + case AutocompleteMatch::HISTORY_TITLE: + case AutocompleteMatch::HISTORY_BODY: + case AutocompleteMatch::HISTORY_KEYWORD: { + static NSImage* historyImage = RetainedResourceImage(IDR_O2_HISTORY); + return historyImage; + } + case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED: + case AutocompleteMatch::SEARCH_HISTORY: + case AutocompleteMatch::SEARCH_SUGGEST: + case AutocompleteMatch::SEARCH_OTHER_ENGINE: { + static NSImage* searchImage = RetainedResourceImage(IDR_O2_SEARCH); + return searchImage; + } + case AutocompleteMatch::OPEN_HISTORY_PAGE: { + static NSImage* moreImage = RetainedResourceImage(IDR_O2_MORE); + return moreImage; + } + default: + NOTREACHED(); + break; + } + + return nil; +} + } // namespace // Helper for MatchText() to allow sharing code between the contents @@ -245,10 +293,12 @@ NSAttributedString* AutocompletePopupViewMac::MatchText( AutocompletePopupViewMac::AutocompletePopupViewMac( AutocompleteEditViewMac* edit_view, AutocompleteEditModel* edit_model, + const BubblePositioner* bubble_positioner, Profile* profile, NSTextField* field) : model_(new AutocompletePopupModel(this, edit_model, profile)), edit_view_(edit_view), + bubble_positioner_(bubble_positioner), field_(field), popup_(nil) { DCHECK(edit_view); @@ -315,12 +365,8 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() { CreatePopupIfNeeded(); // Layout the popup and size it to land underneath the field. - // The field has a single-pixel border on the left and right. This - // needs to be factored out so that the popup window's border (which - // is outside the frame) lines up. - const int kLocationStackEdgeWidth = 1; - NSRect r = NSInsetRect([field_ convertRect:[field_ bounds] toView:nil], - kLocationStackEdgeWidth, 0); + NSRect r = + NSRectFromCGRect(bubble_positioner_->GetLocationStackBounds().ToCGRect()); r.origin = [[field_ window] convertBaseToScreen:r.origin]; DCHECK_GT(r.size.width, 0.0); @@ -340,9 +386,7 @@ void AutocompletePopupViewMac::UpdatePopupAppearance() { for (size_t ii = 0; ii < rows; ++ii) { AutocompleteButtonCell* cell = [matrix cellAtRow:ii column:0]; const AutocompleteMatch& match = model_->result().match_at(ii); - const int resource_id = match.starred ? IDR_OMNIBOX_STAR - : AutocompleteMatch::TypeToIcon(match.type); - [cell setImage:AutocompleteEditViewMac::ImageForResource(resource_id)]; + [cell setImage:MatchIcon(match)]; [cell setAttributedTitle:MatchText(match, resultFont, r.size.width)]; } @@ -463,11 +507,7 @@ void AutocompletePopupViewMac::OpenURLForRow(int row, bool force_background) { imageRect.origin.y += floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2); imageRect.origin.x += kLeftRightMargin; - [image setFlipped:[controlView isFlipped]]; - [image drawInRect:imageRect - fromRect:NSZeroRect // Entire image - operation:NSCompositeSourceOver - fraction:1.0]; + [self drawImage:image withFrame:imageRect inView:controlView]; } // Adjust the title position to be lined up under the field's text. @@ -664,15 +704,10 @@ void AutocompletePopupViewMac::OpenURLForRow(int row, bool force_background) { // This handles drawing the decorations of the rounded popup window, // calling on NSMatrix to draw the actual contents. - (void)drawRect:(NSRect)rect { - // Apparently this expects flipped coordinates, because in order to - // round the bottom corners visually, I need to specify the top - // corners here. NSBezierPath* path = - [NSBezierPath gtm_bezierPathWithRoundRect:[self bounds] - topLeftCornerRadius:kPopupRoundingRadius - topRightCornerRadius:kPopupRoundingRadius - bottomLeftCornerRadius:0.0 - bottomRightCornerRadius:0.0]; + [NSBezierPath bezierPathWithRoundedRect:[self bounds] + xRadius:kPopupRoundingRadius + yRadius:kPopupRoundingRadius]; // Draw the matrix clipped to our border. [NSGraphicsContext saveGraphicsState]; diff --git a/chrome/browser/autocomplete/history_contents_provider.cc b/chrome/browser/autocomplete/history_contents_provider.cc index 1e72ceb..ac81c31 100644 --- a/chrome/browser/autocomplete/history_contents_provider.cc +++ b/chrome/browser/autocomplete/history_contents_provider.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -207,9 +207,11 @@ AutocompleteMatch HistoryContentsProvider::ResultToMatch( // Also show star in popup. AutocompleteMatch match(this, score, false, MatchInTitle(result) ? AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY); - match.fill_into_edit = StringForURLDisplay(result.url(), true, trim_http_); + match.fill_into_edit = StringForURLDisplay(result.url(), true); match.destination_url = result.url(); match.contents = match.fill_into_edit; + if (trim_http_) + TrimHttpPrefix(&match.contents); match.contents_class.push_back( ACMatchClassification(0, ACMatchClassification::URL)); match.description = result.title(); diff --git a/chrome/browser/autocomplete/history_url_provider.cc b/chrome/browser/autocomplete/history_url_provider.cc index a748700..2708d47 100644 --- a/chrome/browser/autocomplete/history_url_provider.cc +++ b/chrome/browser/autocomplete/history_url_provider.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -256,14 +256,10 @@ AutocompleteMatch HistoryURLProvider::SuggestExactInput( const GURL& url = input.canonicalized_url(); if (url.is_valid()) { match.destination_url = url; - match.fill_into_edit = StringForURLDisplay(url, false, false); + match.fill_into_edit = StringForURLDisplay(url, false); // NOTE: Don't set match.input_location (to allow inline autocompletion) // here, it's surprising and annoying. // Trim off "http://" if the user didn't type it. - // Double NOTE: we use TrimHttpPrefix here rather than StringForURLDisplay - // to strip the http as we need to know the offset so we can adjust the - // match_location below. StringForURLDisplay and TrimHttpPrefix have - // slightly different behavior when stripping http as well. const size_t offset = trim_http ? TrimHttpPrefix(&match.fill_into_edit) : 0; // Try to highlight "innermost" match location. If we fix up "w" into @@ -832,13 +828,17 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( DCHECK(match.destination_url.is_valid()); size_t inline_autocomplete_offset = history_match.input_location + params->input.text().length(); - const net::FormatUrlTypes format_types = - (params->trim_http && !history_match.match_in_scheme) ? - net::kFormatUrlOmitAll : net::kFormatUrlOmitUsernamePassword; match.fill_into_edit = net::FormatUrl(info.url(), - match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, - format_types, UnescapeRule::SPACES, NULL, NULL, - &inline_autocomplete_offset); + match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, true, + UnescapeRule::SPACES, NULL, NULL, &inline_autocomplete_offset); + size_t offset = 0; + if (params->trim_http && !history_match.match_in_scheme) { + offset = TrimHttpPrefix(&match.fill_into_edit); + if (inline_autocomplete_offset != std::wstring::npos) { + DCHECK(inline_autocomplete_offset >= offset); + inline_autocomplete_offset -= offset; + } + } if (!params->input.prevent_inline_autocomplete()) match.inline_autocomplete_offset = inline_autocomplete_offset; DCHECK((match.inline_autocomplete_offset == std::wstring::npos) || @@ -846,8 +846,15 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( size_t match_start = history_match.input_location; match.contents = net::FormatUrl(info.url(), - match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, - format_types, UnescapeRule::SPACES, NULL, NULL, &match_start); + match_type == WHAT_YOU_TYPED ? std::wstring() : params->languages, true, + UnescapeRule::SPACES, NULL, NULL, &match_start); + if (offset) { + TrimHttpPrefix(&match.contents); + if (match_start != std::wstring::npos) { + DCHECK(match_start >= offset); + match_start -= offset; + } + } if ((match_start != std::wstring::npos) && (inline_autocomplete_offset != std::wstring::npos) && (inline_autocomplete_offset != match_start)) { diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index acba81e..5833611 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -98,8 +98,8 @@ void SearchProvider::Start(const AutocompleteInput& input, // User typed "?" alone. Give them a placeholder result indicating what // this syntax does. if (default_provider) { - AutocompleteMatch match; - match.provider = this; + AutocompleteMatch match(this, 0, false, + AutocompleteMatch::SEARCH_WHAT_YOU_TYPED); match.contents.assign(l10n_util::GetString(IDS_EMPTY_KEYWORD_VALUE)); match.contents_class.push_back( ACMatchClassification(0, ACMatchClassification::NONE)); @@ -737,9 +737,10 @@ AutocompleteMatch SearchProvider::NavigationToMatch( AutocompleteMatch match(this, relevance, false, AutocompleteMatch::NAVSUGGEST); match.destination_url = navigation.url; - const bool trim_http = !url_util::FindAndCompareScheme( - WideToUTF8(input_text), chrome::kHttpScheme, NULL); - match.contents = StringForURLDisplay(navigation.url, true, trim_http); + match.contents = StringForURLDisplay(navigation.url, true); + if (!url_util::FindAndCompareScheme(WideToUTF8(input_text), + chrome::kHttpScheme, NULL)) + TrimHttpPrefix(&match.contents); AutocompleteMatch::ClassifyMatchInString(input_text, match.contents, ACMatchClassification::URL, &match.contents_class); |