summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/autocomplete_edit.cc
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-10 19:35:52 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-10 19:35:52 +0000
commit81c2122f16c82b52c19b474775d2a15aa065e77a (patch)
treebeee93270b997c49f83ba0233ac1dd12cebaf3a8 /chrome/browser/autocomplete/autocomplete_edit.cc
parent8fbab00264861b95a99a8232ba75e0994c46c185 (diff)
downloadchromium_src-81c2122f16c82b52c19b474775d2a15aa065e77a.zip
chromium_src-81c2122f16c82b52c19b474775d2a15aa065e77a.tar.gz
chromium_src-81c2122f16c82b52c19b474775d2a15aa065e77a.tar.bz2
First pass at splitting the AutocompleteEdit into Model and View. This was noticeably harder than with the Popup and I'm not at all sure I've made the right decisions :(. The View code is about 3x larger than the model.
BUG=1343512 Review URL: http://codereview.chromium.org/1872 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2004 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete/autocomplete_edit.cc')
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit.cc1700
1 files changed, 916 insertions, 784 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc
index 4c06a1c..a48d4e8 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc
@@ -39,22 +39,570 @@
#pragma comment(lib, "oleacc.lib") // Needed for accessibility support.
-// TODO (jcampan): these colors should be derived from the system colors to
-// ensure they show properly. Bug #948807.
-// Colors used to emphasize the scheme in the URL.
-static const COLORREF kSecureSchemeColor = RGB(0, 150, 20);
-static const COLORREF kInsecureSchemeColor = RGB(200, 0, 0);
+///////////////////////////////////////////////////////////////////////////////
+// AutocompleteEditModel
-// Colors used to strike-out the scheme when it is insecure.
-static const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0);
-static const SkColor kSchemeSelectedStrikeoutColor =
- SkColorSetRGB(255, 255, 255);
+// A single AutocompleteController used solely for making synchronous calls to
+// determine how to deal with the clipboard contents for Paste And Go
+// functionality. We avoid using the popup's controller here because we don't
+// want to interrupt in-progress queries or modify the popup state just
+// because the user right-clicked the edit. We don't need a controller for
+// every edit because this will always be accessed on the main thread, so we
+// won't have thread-safety problems.
+static AutocompleteController* paste_and_go_controller = NULL;
+static int paste_and_go_controller_refcount = 0;
+
+AutocompleteEditModel::AutocompleteEditModel(
+ AutocompleteEditView* view,
+ AutocompleteEditController* controller,
+ Profile* profile)
+ : view_(view),
+ controller_(controller),
+ has_focus_(false),
+ user_input_in_progress_(false),
+ just_deleted_text_(false),
+ has_temporary_text_(false),
+ paste_state_(NONE),
+ control_key_state_(UP),
+ is_keyword_hint_(false),
+ disable_keyword_ui_(false),
+ show_search_hint_(true),
+ profile_(profile) {
+ if (++paste_and_go_controller_refcount == 1) {
+ // We don't have a controller yet, so create one. No listener is needed
+ // since we'll only be doing synchronous calls, and no profile is set since
+ // we'll set this before each call to the controller.
+ paste_and_go_controller = new AutocompleteController(NULL, NULL);
+ }
+}
+
+AutocompleteEditModel::~AutocompleteEditModel() {
+ if (--paste_and_go_controller_refcount == 0)
+ delete paste_and_go_controller;
+}
+
+void AutocompleteEditModel::SetProfile(Profile* profile) {
+ DCHECK(profile);
+ profile_ = profile;
+ popup_->SetProfile(profile);
+}
+
+const AutocompleteEditModel::State
+ AutocompleteEditModel::GetStateForTabSwitch() {
+ // Like typing, switching tabs "accepts" the temporary text as the user
+ // text, because it makes little sense to have temporary text when the
+ // popup is closed.
+ if (user_input_in_progress_)
+ InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
+
+ return State(user_input_in_progress_, user_text_,
+ popup_->manually_selected_match_, keyword_, is_keyword_hint_,
+ disable_keyword_ui_, show_search_hint_);
+}
+
+void AutocompleteEditModel::RestoreState(const State& state) {
+ // Restore any user editing.
+ if (state.user_input_in_progress) {
+ // NOTE: Be sure and set keyword-related state BEFORE invoking
+ // DisplayTextFromUserText(), as its result depends upon this state.
+ keyword_ = state.keyword;
+ is_keyword_hint_ = state.is_keyword_hint;
+ disable_keyword_ui_ = state.disable_keyword_ui;
+ show_search_hint_ = state.show_search_hint;
+ view_->SetUserText(state.user_text,
+ DisplayTextFromUserText(state.user_text), false);
+ popup_->manually_selected_match_ = state.manually_selected_match;
+ }
+}
+
+bool AutocompleteEditModel::UpdatePermanentText(
+ const std::wstring& new_permanent_text) {
+ // When there's a new URL, and the user is not editing anything or the edit
+ // doesn't have focus, we want to revert the edit to show the new URL. (The
+ // common case where the edit doesn't have focus is when the user has started
+ // an edit and then abandoned it and clicked a link on the page.)
+ const bool visibly_changed_permanent_text =
+ (permanent_text_ != new_permanent_text) &&
+ (!user_input_in_progress_ || !has_focus_);
+
+ permanent_text_ = new_permanent_text;
+ return visibly_changed_permanent_text;
+}
+
+void AutocompleteEditModel::SetUserText(const std::wstring& text) {
+ SetInputInProgress(true);
+ InternalSetUserText(text);
+ paste_state_ = NONE;
+ has_temporary_text_ = false;
+ popup_->manually_selected_match_.Clear();
+}
+
+void AutocompleteEditModel::GetDataForURLExport(GURL* url,
+ std::wstring* title,
+ SkBitmap* favicon) {
+ const std::wstring url_str(GetURLForCurrentText(NULL, NULL, NULL));
+ *url = GURL(url_str);
+ if (url_str == permanent_text_) {
+ *title = controller_->GetTitle();
+ *favicon = controller_->GetFavIcon();
+ }
+}
+
+std::wstring AutocompleteEditModel::GetDesiredTLD() const {
+ return (control_key_state_ == DOWN_WITHOUT_CHANGE) ?
+ std::wstring(L"com") : std::wstring();
+}
+
+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
+ // initializing the history system, as long as possible, which speeds startup.
+ if (!user_input_in_progress_)
+ return true;
+
+ PageTransition::Type transition = PageTransition::LINK;
+ GetURLForCurrentText(&transition, NULL, NULL);
+ return transition == PageTransition::TYPED;
+}
+
+bool AutocompleteEditModel::GetURLForText(const std::wstring& text,
+ GURL* url) const {
+ url_parse::Parsed parts;
+ const AutocompleteInput::Type type = AutocompleteInput::Parse(
+ UserTextFromDisplayText(text), std::wstring(), &parts, NULL);
+ if (type != AutocompleteInput::URL)
+ return false;
+
+ *url = GURL(URLFixerUpper::FixupURL(text, std::wstring()));
+ return true;
+}
+
+void AutocompleteEditModel::SetInputInProgress(bool in_progress) {
+ if (user_input_in_progress_ == in_progress)
+ return;
+
+ user_input_in_progress_ = in_progress;
+ controller_->OnInputInProgress(in_progress);
+}
+
+void AutocompleteEditModel::Revert() {
+ SetInputInProgress(false);
+ paste_state_ = NONE;
+ InternalSetUserText(std::wstring());
+ keyword_.clear();
+ is_keyword_hint_ = false;
+ disable_keyword_ui_ = false;
+ show_search_hint_ = permanent_text_.empty();
+ has_temporary_text_ = false;
+ view_->SetWindowTextAndCaretPos(permanent_text_,
+ has_focus_ ? permanent_text_.length() : 0);
+}
+
+void AutocompleteEditModel::StartAutocomplete(
+ bool prevent_inline_autocomplete) const {
+ popup_->StartAutocomplete(user_text_, GetDesiredTLD(),
+ prevent_inline_autocomplete || just_deleted_text_ ||
+ (paste_state_ != NONE));
+}
+
+bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const {
+ // Reset local state.
+ paste_and_go_url_.clear();
+ paste_and_go_transition_ = PageTransition::TYPED;
+ paste_and_go_alternate_nav_url_.clear();
+
+ // See if the clipboard text can be parsed.
+ const AutocompleteInput input(text, std::wstring(), true);
+ if (input.type() == AutocompleteInput::INVALID)
+ return false;
+
+ // Ask the controller what do do with this input.
+ paste_and_go_controller->SetProfile(profile_);
+ // This is cheap, and since there's one
+ // paste_and_go_controller for many tabs which
+ // may all have different profiles, it ensures
+ // we're always using the right one.
+ const bool done = paste_and_go_controller->Start(input, false, true);
+ DCHECK(done);
+ AutocompleteResult result;
+ paste_and_go_controller->GetResult(&result);
+ if (result.empty())
+ return false;
+
+ // Set local state based on the default action for this input.
+ result.SetDefaultMatch(AutocompleteResult::Selection());
+ const AutocompleteResult::const_iterator match(result.default_match());
+ DCHECK(match != result.end());
+ paste_and_go_url_ = match->destination_url;
+ paste_and_go_transition_ = match->transition;
+ paste_and_go_alternate_nav_url_ = result.GetAlternateNavURL(input, match);
+
+ return !paste_and_go_url_.empty();
+}
+
+void AutocompleteEditModel::PasteAndGo() {
+ // The final parameter to OpenURL, keyword, is not quite correct here: it's
+ // possible to "paste and go" a string that contains a keyword. This is
+ // enough of an edge case that we ignore this possibility.
+ view_->RevertAll();
+ view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_,
+ paste_and_go_alternate_nav_url_, AutocompletePopupModel::kNoMatch,
+ std::wstring());
+}
+
+void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition,
+ bool for_drop) {
+ // Get the URL and transition type for the selected entry.
+ PageTransition::Type transition;
+ bool is_history_what_you_typed_match;
+ std::wstring alternate_nav_url;
+ const std::wstring url(GetURLForCurrentText(&transition,
+ &is_history_what_you_typed_match,
+ &alternate_nav_url));
+ if (url.empty())
+ return;
+
+ if (url == 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.
+ transition = PageTransition::RELOAD;
+ } else if (for_drop || ((paste_state_ != NONE) &&
+ 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.
+ transition = PageTransition::LINK;
+ }
+
+ view_->OpenURL(url, disposition, transition, alternate_nav_url,
+ AutocompletePopupModel::kNoMatch,
+ is_keyword_hint_ ? std::wstring() : keyword_);
+}
+
+void AutocompleteEditModel::SendOpenNotification(size_t selected_line,
+ const std::wstring& keyword) {
+ // We only care about cases where there is a selection (i.e. the popup is
+ // open).
+ if (popup_->is_open()) {
+ scoped_ptr<AutocompleteLog> log(popup_->GetAutocompleteLog());
+ if (selected_line != AutocompletePopupModel::kNoMatch)
+ log->selected_index = selected_line;
+ else if (!has_temporary_text_)
+ log->inline_autocompleted_length = inline_autocomplete_text_.length();
+ NotificationService::current()->Notify(
+ NOTIFY_OMNIBOX_OPENED_URL, Source<Profile>(profile_),
+ Details<AutocompleteLog>(log.get()));
+ }
+
+ TemplateURLModel* template_url_model = profile_->GetTemplateURLModel();
+ if (keyword.empty() || !template_url_model)
+ return;
+
+ const TemplateURL* const template_url =
+ template_url_model->GetTemplateURLForKeyword(keyword);
+ if (template_url) {
+ UserMetrics::RecordAction(L"AcceptedKeyword", profile_);
+ template_url_model->IncrementUsageCount(template_url);
+ }
+
+ // NOTE: We purposefully don't increment the usage count of the default search
+ // engine, if applicable; see comments in template_url.h.
+}
+
+void AutocompleteEditModel::AcceptKeyword() {
+ view_->OnBeforePossibleChange();
+ view_->SetWindowText(L"");
+ popup_->manually_selected_match_.Clear();
+ popup_->manually_selected_match_.provider_affinity =
+ popup_->autocomplete_controller()->keyword_provider();
+ is_keyword_hint_ = false;
+ disable_keyword_ui_ = false;
+ view_->OnAfterPossibleChange();
+ just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this
+ // since the edit contents have disappeared. It
+ // doesn't really matter, but we clear it to be
+ // consistent.
+ UserMetrics::RecordAction(L"AcceptedKeywordHint", profile_);
+}
+
+void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) {
+ view_->OnBeforePossibleChange();
+ const std::wstring window_text(keyword_ + visible_text);
+ view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length());
+ popup_->manually_selected_match_.Clear();
+ keyword_.clear();
+ view_->OnAfterPossibleChange();
+ just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this
+ // since the edit contents have actually grown
+ // longer.
+}
+
+bool AutocompleteEditModel::query_in_progress() const {
+ return popup_->query_in_progress();
+}
+
+const AutocompleteResult* AutocompleteEditModel::latest_result() const {
+ return popup_->latest_result();
+}
+
+void AutocompleteEditModel::OnSetFocus(bool control_down) {
+ has_focus_ = true;
+ control_key_state_ = control_down ? DOWN_WITHOUT_CHANGE : UP;
+}
+
+void AutocompleteEditModel::OnKillFocus() {
+ has_focus_ = false;
+ control_key_state_ = UP;
+ paste_state_ = NONE;
+
+ // Like typing, killing focus "accepts" the temporary text as the user
+ // text, because it makes little sense to have temporary text when the
+ // popup is closed.
+ InternalSetUserText(UserTextFromDisplayText(view_->GetText()));
+ has_temporary_text_ = false;
+}
+
+bool AutocompleteEditModel::OnEscapeKeyPressed() {
+ // Only do something when there is input in progress -- otherwise, if focus
+ // happens to be in the location bar, users can't still hit <esc> to stop a
+ // load.
+ if (!user_input_in_progress_)
+ return false;
+
+ if (!has_temporary_text_ ||
+ (popup_->URLsForCurrentSelection(NULL, NULL, NULL) == original_url_)) {
+ // The popup isn't open or the selection in it is still the default
+ // selection, so revert the box all the way back to its unedited state.
+ view_->RevertAll();
+ return true;
+ }
+
+ // 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;
+ popup_->manually_selected_match_ = original_selected_match_;
+ view_->OnRevertTemporaryText(user_text_ + inline_autocomplete_text_);
+ return true;
+}
+
+void AutocompleteEditModel::OnControlKeyChanged(bool pressed) {
+ // Don't change anything unless the key state is actually toggling.
+ if (pressed == (control_key_state_ == UP)) {
+ control_key_state_ = pressed ? DOWN_WITHOUT_CHANGE : UP;
+ if (popup_->is_open()) {
+ // Autocomplete history provider results may change, so refresh the
+ // popup. This will force user_input_in_progress_ to true, but if the
+ // popup is open, that should have already been the case.
+ view_->UpdatePopup();
+ }
+ }
+}
+
+void AutocompleteEditModel::OnUpOrDownKeyPressed(int count) {
+ // NOTE: This purposefully don't trigger any code that resets paste_state_.
+ disable_keyword_ui_ = false;
+ if (!popup_->is_open()) {
+ if (!popup_->query_in_progress()) {
+ // The popup is neither open nor working on a query already. So, start an
+ // autocomplete query for the current text. This also sets
+ // user_input_in_progress_ to true, which we want: if the user has started
+ // to interact with the popup, changing the permanent_text_ shouldn't
+ // change the displayed text.
+ // Note: This does not force the popup to open immediately.
+ if (!user_input_in_progress_)
+ InternalSetUserText(permanent_text_);
+ view_->UpdatePopup();
+ }
+
+ // Now go ahead and force the popup to open, and copy the text of the
+ // default item into the edit. We ignore |count|, since without the popup
+ // open, the user doesn't really know what they're interacting with. Since
+ // the user hit an arrow key to explicitly open the popup, we assume that
+ // they prefer the temporary text of the default item to their own text,
+ // like we do when they arrow around an already-open popup. In many cases
+ // the existing text in the edit and the new text will be the same, and the
+ // only visible effect will be to cancel any selection and place the cursor
+ // at the end of the edit.
+ popup_->Move(0);
+ } else {
+ // The popup is open, so the user should be able to interact with it
+ // normally.
+ popup_->Move(count);
+ }
+}
+
+void AutocompleteEditModel::OnPopupDataChanged(
+ const std::wstring& text,
+ bool is_temporary_text,
+ const AutocompleteResult::Selection& previous_selected_match,
+ const std::wstring& keyword,
+ bool is_keyword_hint,
+ bool can_show_search_hint) {
+ // 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 disable_keyword_ui_.
+ can_show_search_hint &= keyword.empty();
+
+ // Update keyword/hint-related local state.
+ bool keyword_state_changed = (keyword_ != keyword) ||
+ ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()) ||
+ (show_search_hint_ != can_show_search_hint);
+ if (keyword_state_changed) {
+ keyword_ = keyword;
+ is_keyword_hint_ = is_keyword_hint;
+ show_search_hint_ = can_show_search_hint;
+ }
+
+ // Handle changes to temporary text.
+ 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_ = popup_->URLsForCurrentSelection(NULL, NULL, NULL);
+ original_selected_match_ = previous_selected_match;
+ }
+ view_->OnTemporaryTextMaybeChanged(DisplayTextFromUserText(text),
+ save_original_selection);
+ return;
+ }
+
+ // Handle changes to inline autocomplete text. Don't make changes if the user
+ // is showing temporary text. Making display changes would be obviously
+ // wrong; making changes to the inline_autocomplete_text_ itself turns out to
+ // be more subtlely wrong, because it means hitting esc will no longer revert
+ // to the original state before arrowing.
+ if (!has_temporary_text_) {
+ inline_autocomplete_text_ = text;
+ if (view_->OnInlineAutocompleteTextMaybeChanged(
+ DisplayTextFromUserText(user_text_ + inline_autocomplete_text_),
+ DisplayTextFromUserText(user_text_).length()))
+ return;
+ }
+
+ // If the above changes didn't warrant a text update but we did change keyword
+ // state, we have yet to notify the controller about it.
+ if (keyword_state_changed)
+ controller_->OnChanged();
+}
+
+bool AutocompleteEditModel::OnAfterPossibleChange(const std::wstring& new_text,
+ bool selection_differs,
+ bool select_all_before_change,
+ bool text_differs,
+ bool just_deleted_text,
+ bool at_end_of_edit) {
+ // Update the paste state as appropriate: if we're just finishing a paste
+ // that replaced all the text, preserve that information; otherwise, if we've
+ // made some other edit, clear paste tracking.
+ if (paste_state_ == REPLACING_ALL)
+ paste_state_ = REPLACED_ALL;
+ else if (text_differs)
+ paste_state_ = NONE;
+
+ // If something has changed while the control key is down, prevent
+ // "ctrl-enter" until the control key is released. When we do this, we need
+ // to update the popup if it's open, since the desired_tld will have changed.
+ if ((text_differs || selection_differs) &&
+ (control_key_state_ == DOWN_WITHOUT_CHANGE)) {
+ control_key_state_ = DOWN_WITH_CHANGE;
+ if (!text_differs && !popup_->is_open())
+ return false; // Don't open the popup for no reason.
+ } else if (!text_differs &&
+ (inline_autocomplete_text_.empty() || !selection_differs)) {
+ return false;
+ }
+
+ const bool had_keyword = !is_keyword_hint_ && !keyword_.empty();
+
+ // Modifying the selection counts as accepting the autocompleted text.
+ InternalSetUserText(UserTextFromDisplayText(new_text));
+ has_temporary_text_ = false;
+
+ if (text_differs) {
+ // When the user has deleted text, don't allow inline autocomplete.
+ just_deleted_text_ = just_deleted_text;
+
+ // When the user doesn't have a selected keyword, deleting text or replacing
+ // all of it with something else should reset the provider affinity. The
+ // typical use case for deleting is that the user starts typing, sees that
+ // some entry is close to what he wants, arrows to it, and then deletes some
+ // unnecessary bit from the end of the string. In this case the user didn't
+ // actually want "provider X", he wanted the string from that entry for
+ // editing purposes, and he's no longer looking at the popup to notice that,
+ // despite deleting some text, the action we'll take on enter hasn't changed
+ // at all.
+ if (!had_keyword && (just_deleted_text_ || select_all_before_change)) {
+ popup_->manually_selected_match_.Clear();
+ }
+ }
+
+ // Disable the fancy keyword UI if the user didn't already have a visible
+ // keyword and is not at the end of the edit. This prevents us from showing
+ // the fancy UI (and interrupting the user's editing) if the user happens to
+ // have a keyword for 'a', types 'ab' then puts a space between the 'a' and
+ // the 'b'.
+ disable_keyword_ui_ = (is_keyword_hint_ || keyword_.empty()) &&
+ !at_end_of_edit;
+
+ view_->UpdatePopup();
+
+ if (!had_keyword && !is_keyword_hint_ && !keyword_.empty()) {
+ // Went from no selected keyword to a selected keyword. Set the affinity to
+ // the keyword provider. This forces the selected keyword to persist even
+ // if the user deletes all the text.
+ popup_->manually_selected_match_.Clear();
+ popup_->manually_selected_match_.provider_affinity =
+ popup_->autocomplete_controller()->keyword_provider();
+ }
+
+ return true;
+}
+
+void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) {
+ user_text_ = text;
+ just_deleted_text_ = false;
+ inline_autocomplete_text_.clear();
+}
+
+std::wstring AutocompleteEditModel::DisplayTextFromUserText(
+ const std::wstring& text) const {
+ return (is_keyword_hint_ || keyword_.empty()) ?
+ text : KeywordProvider::SplitReplacementStringFromInput(text);
+}
+
+std::wstring AutocompleteEditModel::UserTextFromDisplayText(
+ const std::wstring& text) const {
+ return (is_keyword_hint_ || keyword_.empty()) ?
+ text : (keyword_ + L" " + text);
+}
+
+std::wstring AutocompleteEditModel::GetURLForCurrentText(
+ PageTransition::Type* transition,
+ bool* is_history_what_you_typed_match,
+ std::wstring* alternate_nav_url) {
+ return (popup_->is_open() || popup_->query_in_progress()) ?
+ popup_->URLsForCurrentSelection(transition,
+ is_history_what_you_typed_match,
+ alternate_nav_url) :
+ popup_->URLsForDefaultMatch(UserTextFromDisplayText(view_->GetText()),
+ GetDesiredTLD(), transition,
+ is_history_what_you_typed_match,
+ alternate_nav_url);
+}
///////////////////////////////////////////////////////////////////////////////
// Helper classes
-AutocompleteEdit::ScopedFreeze::ScopedFreeze(AutocompleteEdit* edit,
- ITextDocument* text_object_model)
+AutocompleteEditView::ScopedFreeze::ScopedFreeze(
+ AutocompleteEditView* edit,
+ ITextDocument* text_object_model)
: edit_(edit),
text_object_model_(text_object_model) {
// Freeze the screen.
@@ -64,7 +612,7 @@ AutocompleteEdit::ScopedFreeze::ScopedFreeze(AutocompleteEdit* edit,
}
}
-AutocompleteEdit::ScopedFreeze::~ScopedFreeze() {
+AutocompleteEditView::ScopedFreeze::~ScopedFreeze() {
// Unfreeze the screen.
// NOTE: If this destructor is reached while the edit is being destroyed (for
// example, because we double-clicked the edit of a popup and caused it to
@@ -83,7 +631,7 @@ AutocompleteEdit::ScopedFreeze::~ScopedFreeze() {
}
}
-AutocompleteEdit::ScopedSuspendUndo::ScopedSuspendUndo(
+AutocompleteEditView::ScopedSuspendUndo::ScopedSuspendUndo(
ITextDocument* text_object_model)
: text_object_model_(text_object_model) {
// Suspend Undo processing.
@@ -91,71 +639,60 @@ AutocompleteEdit::ScopedSuspendUndo::ScopedSuspendUndo(
text_object_model_->Undo(tomSuspend, NULL);
}
-AutocompleteEdit::ScopedSuspendUndo::~ScopedSuspendUndo() {
+AutocompleteEditView::ScopedSuspendUndo::~ScopedSuspendUndo() {
// Resume Undo processing.
if (text_object_model_)
text_object_model_->Undo(tomResume, NULL);
}
///////////////////////////////////////////////////////////////////////////////
-// AutocompleteEdit
+// AutocompleteEditView
+
+// TODO (jcampan): these colors should be derived from the system colors to
+// ensure they show properly. Bug #948807.
+// Colors used to emphasize the scheme in the URL.
+static const COLORREF kSecureSchemeColor = RGB(0, 150, 20);
+static const COLORREF kInsecureSchemeColor = RGB(200, 0, 0);
+
+// Colors used to strike-out the scheme when it is insecure.
+static const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0);
+static const SkColor kSchemeSelectedStrikeoutColor =
+ SkColorSetRGB(255, 255, 255);
// These are used to hook the CRichEditCtrl's calls to BeginPaint() and
// EndPaint() and provide a memory DC instead. See OnPaint().
static HWND edit_hwnd = NULL;
static PAINTSTRUCT paint_struct;
-// A single AutocompleteController used solely for making synchronous calls to
-// determine how to deal with the clipboard contents for Paste And Go
-// functionality. We avoid using the popup's controller here because we don't
-// want to interrupt in-progress queries or modify the popup state just
-// because the user right-clicked the edit. We don't need a controller for
-// every edit because this will always be accessed on the main thread, so we
-// won't have thread-safety problems.
-static AutocompleteController* paste_and_go_controller = NULL;
-static int paste_and_go_controller_refcount = 0;
-
-AutocompleteEdit::AutocompleteEdit(const ChromeFont& font,
- Controller* controller,
- ToolbarModel* model,
- ChromeViews::View* parent_view,
- HWND hwnd,
- Profile* profile,
- CommandController* command_controller,
- bool popup_window_mode)
- : controller_(controller),
- model_(model),
- popup_(new AutocompletePopupModel(font, this, profile)),
+AutocompleteEditView::AutocompleteEditView(
+ const ChromeFont& font,
+ AutocompleteEditController* controller,
+ ToolbarModel* toolbar_model,
+ ChromeViews::View* parent_view,
+ HWND hwnd,
+ Profile* profile,
+ CommandController* command_controller,
+ bool popup_window_mode)
+ : model_(new AutocompleteEditModel(this, controller, profile)),
+ popup_model_(new AutocompletePopupModel(font, this, model_.get(),
+ profile)),
+ controller_(controller),
+ parent_view_(parent_view),
+ toolbar_model_(toolbar_model),
+ command_controller_(command_controller),
popup_window_mode_(popup_window_mode),
- has_focus_(false),
- user_input_in_progress_(false),
- just_deleted_text_(false),
- has_temporary_text_(false),
- paste_state_(NONE),
tracking_click_(false),
tracking_double_click_(false),
double_click_time_(0),
can_discard_mousemove_(false),
- control_key_state_(UP),
- command_controller_(command_controller),
- parent_view_(parent_view),
font_(font),
- profile_(profile),
possible_drag_(false),
in_drag_(false),
initiated_drag_(false),
drop_highlight_position_(-1),
- is_keyword_hint_(false),
- disable_keyword_ui_(false),
- show_search_hint_(true),
background_color_(0),
scheme_security_level_(ToolbarModel::NORMAL) {
- if (!popup_window_mode_ && ++paste_and_go_controller_refcount == 1) {
- // We don't have a controller yet, so create one. No listener is needed
- // since we'll only be doing synchronous calls, and no profile is set since
- // we'll set this before each call to the controller.
- paste_and_go_controller = new AutocompleteController(NULL, NULL);
- }
+ model_->set_popup_model(popup_model_.get());
saved_selection_for_focus_change_.cpMin = -1;
@@ -256,35 +793,38 @@ AutocompleteEdit::AutocompleteEdit(const ChromeFont& font,
}
}
-AutocompleteEdit::~AutocompleteEdit() {
+AutocompleteEditView::~AutocompleteEditView() {
NotificationService::current()->Notify(NOTIFY_AUTOCOMPLETE_EDIT_DESTROYED,
- Source<AutocompleteEdit>(this), NotificationService::NoDetails());
+ Source<AutocompleteEditView>(this), NotificationService::NoDetails());
+}
- if (!popup_window_mode_ && --paste_and_go_controller_refcount == 0)
- delete paste_and_go_controller;
+void AutocompleteEditView::SaveStateToTab(TabContents* tab) {
+ DCHECK(tab);
+
+ const AutocompleteEditModel::State model_state(
+ model_->GetStateForTabSwitch());
+
+ CHARRANGE selection;
+ GetSelection(selection);
+ tab->set_saved_location_bar_state(new AutocompleteEditState(model_state,
+ State(selection, saved_selection_for_focus_change_)));
}
-void AutocompleteEdit::Update(const TabContents* tab_for_state_restoring) {
- // When there's a new URL, and the user is not editing anything or the edit
- // doesn't have focus, we want to revert the edit to show the new URL. (The
- // common case where the edit doesn't have focus is when the user has started
- // an edit and then abandoned it and clicked a link on the page.)
- std::wstring permanent_text = model_->GetText();
+void AutocompleteEditView::Update(const TabContents* tab_for_state_restoring) {
const bool visibly_changed_permanent_text =
- (permanent_text_ != permanent_text) &&
- (!user_input_in_progress_ || !has_focus_);
-
- permanent_text_ = permanent_text;
+ model_->UpdatePermanentText(toolbar_model_->GetText());
- COLORREF background_color =
- LocationBarView::kBackgroundColorByLevel[model_->GetSchemeSecurityLevel()];
+ const ToolbarModel::SecurityLevel security_level =
+ toolbar_model_->GetSchemeSecurityLevel();
+ const COLORREF background_color =
+ LocationBarView::kBackgroundColorByLevel[security_level];
+ 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 ((background_color == background_color_) &&
- (model_->GetSchemeSecurityLevel() == scheme_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 scheme_security_level_ here so
@@ -295,9 +835,7 @@ void AutocompleteEdit::Update(const TabContents* tab_for_state_restoring) {
background_color_ = background_color;
SetBackgroundColor(background_color_);
}
- const bool changed_security_level =
- (model_->GetSchemeSecurityLevel() != scheme_security_level_);
- scheme_security_level_ = model_->GetSchemeSecurityLevel();
+ scheme_security_level_ = security_level;
// When we're switching to a new tab, restore its state, if any.
if (tab_for_state_restoring) {
@@ -306,27 +844,16 @@ void AutocompleteEdit::Update(const TabContents* tab_for_state_restoring) {
// won't overwrite all our local state.
RevertAll();
- const AutocompleteEdit::State* const state =
+ const AutocompleteEditState* const state =
tab_for_state_restoring->saved_location_bar_state();
if (state) {
- // Restore any user editing.
- if (state->user_input_in_progress) {
- // NOTE: Be sure and set keyword-related state BEFORE invoking
- // DisplayTextFromUserText(), as its result depends upon this state.
- keyword_ = state->keyword;
- is_keyword_hint_ = state->is_keyword_hint;
- disable_keyword_ui_ = state->disable_keyword_ui;
- show_search_hint_ = state->show_search_hint;
- SetUserText(state->user_text, DisplayTextFromUserText(state->user_text),
- false);
- popup_->manually_selected_match_ = state->manually_selected_match;
- }
+ model_->RestoreState(state->model_state);
// Restore user's selection. We do this after restoring the user_text
// above so we're selecting in the correct string.
- SetSelectionRange(state->selection);
+ SetSelectionRange(state->view_state.selection);
saved_selection_for_focus_change_ =
- state->saved_selection_for_focus_change;
+ state->view_state.saved_selection_for_focus_change;
}
} else if (visibly_changed_permanent_text) {
// Not switching tabs, just updating the permanent text. (In the case where
@@ -358,138 +885,103 @@ void AutocompleteEdit::Update(const TabContents* tab_for_state_restoring) {
}
}
-void AutocompleteEdit::SetProfile(Profile* profile) {
- DCHECK(profile);
- profile_ = profile;
- popup_->SetProfile(profile);
-}
-
-void AutocompleteEdit::SaveStateToTab(TabContents* tab) {
- DCHECK(tab);
+void AutocompleteEditView::OpenURL(const std::wstring& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition,
+ const std::wstring& alternate_nav_url,
+ size_t selected_line,
+ const std::wstring& keyword) {
+ if (url.empty())
+ return;
- // Like typing, switching tabs "accepts" the temporary text as the user
- // text, because it makes little sense to have temporary text when the
- // popup is closed.
- if (user_input_in_progress_)
- InternalSetUserText(UserTextFromDisplayText(GetText()));
+ model_->SendOpenNotification(selected_line, keyword);
- CHARRANGE selection;
- GetSelection(selection);
- tab->set_saved_location_bar_state(new State(selection,
- saved_selection_for_focus_change_, user_input_in_progress_, user_text_,
- popup_->manually_selected_match_, keyword_, is_keyword_hint_,
- disable_keyword_ui_, show_search_hint_));
+ ScopedFreeze freeze(this, GetTextObjectModel());
+ if (disposition != NEW_BACKGROUND_TAB)
+ RevertAll(); // Revert the box to its unedited state
+ controller_->OnAutocompleteAccept(url, disposition, transition,
+ alternate_nav_url);
}
-std::wstring AutocompleteEdit::GetText() const {
+std::wstring AutocompleteEditView::GetText() const {
const int len = GetTextLength() + 1;
std::wstring str;
GetWindowText(WriteInto(&str, len), len);
return str;
}
-std::wstring AutocompleteEdit::GetURLForCurrentText(
- PageTransition::Type* transition,
- bool* is_history_what_you_typed_match,
- std::wstring* alternate_nav_url) {
- return (popup_->is_open() || popup_->query_in_progress()) ?
- popup_->URLsForCurrentSelection(transition,
- is_history_what_you_typed_match,
- alternate_nav_url) :
- popup_->URLsForDefaultMatch(UserTextFromDisplayText(GetText()),
- GetDesiredTLD(), transition,
- is_history_what_you_typed_match,
- alternate_nav_url);
+void AutocompleteEditView::SetUserText(const std::wstring& text,
+ const std::wstring& display_text,
+ bool update_popup) {
+ ScopedFreeze freeze(this, GetTextObjectModel());
+ model_->SetUserText(text);
+ saved_selection_for_focus_change_.cpMin = -1;
+ SetWindowTextAndCaretPos(display_text, display_text.length());
+ if (update_popup)
+ UpdatePopup();
+ TextChanged();
}
-void AutocompleteEdit::SelectAll(bool reversed) {
+void AutocompleteEditView::SetWindowTextAndCaretPos(const std::wstring& text,
+ size_t caret_pos) {
+ SetWindowText(text.c_str());
+ PlaceCaretAt(caret_pos);
+}
+
+void AutocompleteEditView::SelectAll(bool reversed) {
if (reversed)
SetSelection(GetTextLength(), 0);
else
SetSelection(0, GetTextLength());
}
-void AutocompleteEdit::RevertAll() {
+void AutocompleteEditView::RevertAll() {
ScopedFreeze freeze(this, GetTextObjectModel());
ClosePopup();
- popup_->manually_selected_match_.Clear();
- SetInputInProgress(false);
- paste_state_ = NONE;
- InternalSetUserText(std::wstring());
- SetWindowText(permanent_text_.c_str());
- keyword_.clear();
- is_keyword_hint_ = false;
- disable_keyword_ui_ = false;
- show_search_hint_ = permanent_text_.empty();
- PlaceCaretAt(has_focus_ ? permanent_text_.length() : 0);
+ model_->Revert();
saved_selection_for_focus_change_.cpMin = -1;
- has_temporary_text_ = false;
TextChanged();
}
-void AutocompleteEdit::AcceptInput(WindowOpenDisposition disposition,
- bool for_drop) {
- // Get the URL and transition type for the selected entry.
- PageTransition::Type transition;
- bool is_history_what_you_typed_match;
- std::wstring alternate_nav_url;
- const std::wstring url(GetURLForCurrentText(&transition,
- &is_history_what_you_typed_match,
- &alternate_nav_url));
- if (url.empty())
- return;
-
- if (url == 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.
- transition = PageTransition::RELOAD;
- } else if (for_drop || ((paste_state_ != NONE) &&
- 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.
- transition = PageTransition::LINK;
- }
-
- OpenURL(url, disposition, transition, alternate_nav_url,
- AutocompletePopupModel::kNoMatch,
- is_keyword_hint_ ? std::wstring() : keyword_);
-}
-
-void AutocompleteEdit::OpenURL(const std::wstring& url,
- WindowOpenDisposition disposition,
- PageTransition::Type transition,
- const std::wstring& alternate_nav_url,
- size_t selected_line,
- const std::wstring& keyword) {
- if (url.empty())
- return;
-
+void AutocompleteEditView::UpdatePopup() {
ScopedFreeze freeze(this, GetTextObjectModel());
- SendOpenNotification(selected_line, keyword);
+ model_->SetInputInProgress(true);
- if (disposition != NEW_BACKGROUND_TAB)
- RevertAll(); // Revert the box to its unedited state
- controller_->OnAutocompleteAccept(url, disposition, transition,
- alternate_nav_url);
-}
+ if (!model_->has_focus()) {
+ // When we're in the midst of losing focus, don't rerun autocomplete. This
+ // can happen when losing focus causes the IME to cancel/finalize a
+ // composition. We still want to note that user input is in progress, we
+ // just don't want to do anything else.
+ //
+ // Note that in this case the ScopedFreeze above was unnecessary; however,
+ // we're inside the callstack of OnKillFocus(), which has already frozen the
+ // edit, so this will never result in an unnecessary UpdateWindow() call.
+ return;
+ }
-void AutocompleteEdit::ClosePopup() {
- popup_->StopAutocomplete();
-}
+ // Figure out whether the user is trying to compose something in an IME.
+ bool ime_composing = false;
+ HIMC context = ImmGetContext(m_hWnd);
+ if (context) {
+ ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
+ ImmReleaseContext(m_hWnd, context);
+ }
-bool AutocompleteEdit::query_in_progress() const {
- return popup_->query_in_progress();
+ // Don't inline autocomplete when:
+ // * The user is deleting text
+ // * The caret/selection isn't at the end of the text
+ // * The user has just pasted in something that replaced all the text
+ // * The user is trying to compose something in an IME
+ CHARRANGE sel;
+ GetSel(sel);
+ model_->StartAutocomplete((sel.cpMax < GetTextLength()) || ime_composing);
}
-const AutocompleteResult* AutocompleteEdit::latest_result() const {
- return popup_->latest_result();
+void AutocompleteEditView::ClosePopup() {
+ popup_model_->StopAutocomplete();
}
-IAccessible* AutocompleteEdit::GetIAccessible() {
+IAccessible* AutocompleteEditView::GetIAccessible() {
if (!autocomplete_accessibility_) {
CComObject<AutocompleteAccessibility>* accessibility = NULL;
if (!SUCCEEDED(CComObject<AutocompleteAccessibility>::CreateInstance(
@@ -510,7 +1002,7 @@ IAccessible* AutocompleteEdit::GetIAccessible() {
return autocomplete_accessibility_.Detach();
}
-void AutocompleteEdit::SetDropHighlightPosition(int position) {
+void AutocompleteEditView::SetDropHighlightPosition(int position) {
if (drop_highlight_position_ != position) {
RepaintDropHighlight(drop_highlight_position_);
drop_highlight_position_ = position;
@@ -518,7 +1010,7 @@ void AutocompleteEdit::SetDropHighlightPosition(int position) {
}
}
-void AutocompleteEdit::MoveSelectedText(int new_position) {
+void AutocompleteEditView::MoveSelectedText(int new_position) {
const std::wstring selected_text(GetSelectedText());
CHARRANGE sel;
GetSel(sel);
@@ -540,7 +1032,7 @@ void AutocompleteEdit::MoveSelectedText(int new_position) {
OnAfterPossibleChange();
}
-void AutocompleteEdit::InsertText(int position, const std::wstring& text) {
+void AutocompleteEditView::InsertText(int position, const std::wstring& text) {
DCHECK((position >= 0) && (position <= GetTextLength()));
ScopedFreeze freeze(this, GetTextObjectModel());
OnBeforePossibleChange();
@@ -549,138 +1041,132 @@ void AutocompleteEdit::InsertText(int position, const std::wstring& text) {
OnAfterPossibleChange();
}
-void AutocompleteEdit::PasteAndGo(const std::wstring& text) {
- if (CanPasteAndGo(text))
- PasteAndGo();
+void AutocompleteEditView::OnTemporaryTextMaybeChanged(
+ const std::wstring& display_text,
+ bool save_original_selection) {
+ if (save_original_selection)
+ GetSelection(original_selection_);
+
+ // Set new text and cursor position. Sometimes this does extra work (e.g.
+ // when the new text and the old text are identical), but it's only called
+ // when the user manually changes the selected line in the popup, so that's
+ // not really a problem. Also, even when the text hasn't changed we'd want to
+ // update the caret, because if the user had the cursor in the middle of the
+ // text and then arrowed to another entry with the same text, we'd still want
+ // to move the caret.
+ ScopedFreeze freeze(this, GetTextObjectModel());
+ SetWindowTextAndCaretPos(display_text, display_text.length());
+ TextChanged();
}
-bool AutocompleteEdit::OverrideAccelerator(
- const ChromeViews::Accelerator& accelerator) {
- // Only override <esc>, and only when there is input in progress -- otherwise,
- // if focus happens to be in the location bar, users can't still hit <esc> to
- // stop a load.
- if ((accelerator.GetKeyCode() != VK_ESCAPE) || accelerator.IsAltDown() ||
- !user_input_in_progress_)
+bool AutocompleteEditView::OnInlineAutocompleteTextMaybeChanged(
+ const std::wstring& display_text,
+ size_t user_text_length) {
+ // Update the text and selection. Because this can be called repeatedly while
+ // typing, we've careful not to freeze the edit unless we really need to.
+ // Also, unlike in the temporary text case above, here we don't want to update
+ // the caret/selection unless we have to, since this might make the user's
+ // caret position change without warning during typing.
+ if (display_text == GetText())
return false;
- if (!has_temporary_text_ ||
- (popup_->URLsForCurrentSelection(NULL, NULL, NULL) == original_url_)) {
- // The popup isn't open or the selection in it is still the default
- // selection, so revert the box all the way back to its unedited state.
- RevertAll();
- return true;
- }
+ ScopedFreeze freeze(this, GetTextObjectModel());
+ SetWindowText(display_text.c_str());
+ // Set a reversed selection to keep the caret in the same position, which
+ // avoids scrolling the user's text.
+ SetSelection(static_cast<LONG>(display_text.length()),
+ static_cast<LONG>(user_text_length));
+ TextChanged();
+ return true;
+}
- // 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_.
+void AutocompleteEditView::OnRevertTemporaryText(const std::wstring& text) {
ScopedFreeze freeze(this, GetTextObjectModel());
- just_deleted_text_ = false;
- const std::wstring new_window_text(user_text_ +
- inline_autocomplete_text_);
- SetWindowText(new_window_text.c_str());
+ SetWindowText(text.c_str());
SetSelectionRange(original_selection_);
- has_temporary_text_ = false;
- popup_->manually_selected_match_ = original_selected_match_;
UpdatePopup();
TextChanged();
- return true;
}
-void AutocompleteEdit::HandleExternalMsg(UINT msg,
- UINT flags,
- const CPoint& screen_point) {
- if (msg == WM_CAPTURECHANGED) {
- SendMessage(msg, 0, NULL);
- return;
+void AutocompleteEditView::OnBeforePossibleChange() {
+ // Record our state.
+ text_before_change_ = GetText();
+ GetSelection(sel_before_change_);
+ select_all_before_change_ = IsSelectAll(sel_before_change_);
+}
+
+bool AutocompleteEditView::OnAfterPossibleChange() {
+ // Prevent the user from selecting the "phantom newline" at the end of the
+ // edit. If they try, we just silently move the end of the selection back to
+ // the end of the real text.
+ CHARRANGE new_sel;
+ GetSelection(new_sel);
+ const int length = GetTextLength();
+ if ((new_sel.cpMin > length) || (new_sel.cpMax > length)) {
+ if (new_sel.cpMin > length)
+ new_sel.cpMin = length;
+ if (new_sel.cpMax > length)
+ new_sel.cpMax = length;
+ SetSelectionRange(new_sel);
}
+ const bool selection_differs = (new_sel.cpMin != sel_before_change_.cpMin) ||
+ (new_sel.cpMax != sel_before_change_.cpMax);
+ const bool at_end_of_edit =
+ (new_sel.cpMin == length) && (new_sel.cpMax == length);
- CPoint client_point(screen_point);
- ::MapWindowPoints(NULL, m_hWnd, &client_point, 1);
- SendMessage(msg, flags, MAKELPARAM(client_point.x, client_point.y));
-}
+ // See if the text or selection have changed since OnBeforePossibleChange().
+ const std::wstring new_text(GetText());
+ const bool text_differs = (new_text != text_before_change_);
-void AutocompleteEdit::OnPopupDataChanged(
- const std::wstring& text,
- bool is_temporary_text,
- const AutocompleteResult::Selection& previous_selected_match,
- const std::wstring& keyword,
- bool is_keyword_hint,
- bool can_show_search_hint) {
- // 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 disable_keyword_ui_.
- can_show_search_hint &= keyword.empty();
+ // When the user has deleted text, we don't allow inline autocomplete. Make
+ // sure to not flag cases like selecting part of the text and then pasting
+ // (or typing) the prefix of that selection. (We detect these by making
+ // sure the caret, which should be after any insertion, hasn't moved
+ // forward of the old selection start.)
+ const bool just_deleted_text =
+ (text_before_change_.length() > new_text.length()) &&
+ (new_sel.cpMin <= std::min(sel_before_change_.cpMin,
+ sel_before_change_.cpMax));
- // Update keyword/hint-related local state.
- bool keyword_state_changed = (keyword_ != keyword) ||
- ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()) ||
- (show_search_hint_ != can_show_search_hint);
- if (keyword_state_changed) {
- keyword_ = keyword;
- is_keyword_hint_ = is_keyword_hint;
- show_search_hint_ = can_show_search_hint;
- }
- // Handle changes to temporary text.
- if (is_temporary_text) {
- if (!has_temporary_text_) {
- // Save the original selection and URL so it can be reverted later.
- has_temporary_text_ = true;
- GetSelection(original_selection_);
- original_url_ = popup_->URLsForCurrentSelection(NULL, NULL, NULL);
- original_selected_match_ = previous_selected_match;
- }
+ const bool something_changed = model_->OnAfterPossibleChange(new_text,
+ selection_differs, select_all_before_change_, text_differs,
+ just_deleted_text, at_end_of_edit);
- // Set new text and cursor position. Sometimes this does extra work (e.g.
- // when the new text and the old text are identical), but it's only called
- // when the user manually changes the selected line in the popup, so that's
- // not really a problem. Also, even when the text hasn't changed we'd want
- // to update the caret, because if the user had the cursor in the middle of
- // the text and then arrowed to another entry with the same text, we'd still
- // want to move the caret.
- const std::wstring display_text(DisplayTextFromUserText(text));
- ScopedFreeze freeze(this, GetTextObjectModel());
- SetWindowText(display_text.c_str());
- PlaceCaretAt(display_text.length());
+ if (something_changed && text_differs)
TextChanged();
- return;
- }
- // Handle changes to inline autocomplete text. Don't make changes if the user
- // is showing temporary text. Making display changes would be obviously
- // wrong; making changes to the inline_autocomplete_text_ itself turns out to
- // be more subtlely wrong, because it means hitting esc will no longer revert
- // to the original state before arrowing.
- if (!has_temporary_text_) {
- inline_autocomplete_text_ = text;
- // Update the text and selection. Because this can be called repeatedly
- // while typing, we've careful not to freeze the edit unless we really need
- // to. Also, unlike in the temporary text case above, here we don't want to
- // update the caret/selection unless we have to, since this might make the
- // user's caret position change without warning during typing.
- const std::wstring display_text(
- DisplayTextFromUserText(user_text_ + inline_autocomplete_text_));
- if (display_text != GetText()) {
- ScopedFreeze freeze(this, GetTextObjectModel());
- SetWindowText(display_text.c_str());
- // Set a reversed selection to keep the caret in the same position, which
- // avoids scrolling the user's text.
- SetSelection(
- static_cast<LONG>(display_text.length()),
- static_cast<LONG>(DisplayTextFromUserText(user_text_).length()));
- TextChanged();
- return;
- }
+ return something_changed;
+}
+
+void AutocompleteEditView::PasteAndGo(const std::wstring& text) {
+ if (CanPasteAndGo(text))
+ model_->PasteAndGo();
+}
+
+bool AutocompleteEditView::OverrideAccelerator(
+ const ChromeViews::Accelerator& accelerator) {
+ // Only override <esc>.
+ if ((accelerator.GetKeyCode() != VK_ESCAPE) || accelerator.IsAltDown())
+ return false;
+
+ return model_->OnEscapeKeyPressed();
+}
+
+void AutocompleteEditView::HandleExternalMsg(UINT msg,
+ UINT flags,
+ const CPoint& screen_point) {
+ if (msg == WM_CAPTURECHANGED) {
+ SendMessage(msg, 0, NULL);
+ return;
}
- // If the above changes didn't warrant a text update but we did change keyword
- // state, we have yet to notify the controller about it.
- if (keyword_state_changed)
- controller_->OnChanged();
+ CPoint client_point(screen_point);
+ ::MapWindowPoints(NULL, m_hWnd, &client_point, 1);
+ SendMessage(msg, flags, MAKELPARAM(client_point.x, client_point.y));
}
-bool AutocompleteEdit::IsCommandEnabled(int id) const {
+bool AutocompleteEditView::IsCommandEnabled(int id) const {
switch (id) {
case IDS_UNDO: return !!CanUndo();
case IDS_CUT: return !!CanCut();
@@ -694,23 +1180,23 @@ bool AutocompleteEdit::IsCommandEnabled(int id) const {
}
}
-bool AutocompleteEdit::GetContextualLabel(int id, std::wstring* out) const {
+bool AutocompleteEditView::GetContextualLabel(int id, std::wstring* out) const {
if ((id != IDS_PASTE_AND_GO) ||
- // No need to change the default IDS_PASTE_AND_GO label for a typed
- // destination (this is also the type set when Paste And Go is disabled).
- (paste_and_go_transition_ == PageTransition::TYPED))
+ // No need to change the default IDS_PASTE_AND_GO label unless this is a
+ // search.
+ !model_->is_paste_and_search())
return false;
out->assign(l10n_util::GetString(IDS_PASTE_AND_SEARCH));
return true;
}
-void AutocompleteEdit::ExecuteCommand(int id) {
+void AutocompleteEditView::ExecuteCommand(int id) {
ScopedFreeze freeze(this, GetTextObjectModel());
if (id == IDS_PASTE_AND_GO) {
// This case is separate from the switch() below since we don't want to wrap
// it in OnBefore/AfterPossibleChange() calls.
- PasteAndGo();
+ model_->PasteAndGo();
return;
}
@@ -748,10 +1234,10 @@ void AutocompleteEdit::ExecuteCommand(int id) {
}
// static
-int CALLBACK AutocompleteEdit::WordBreakProc(LPTSTR edit_text,
- int current_pos,
- int num_bytes,
- int action) {
+int CALLBACK AutocompleteEditView::WordBreakProc(LPTSTR edit_text,
+ int current_pos,
+ int num_bytes,
+ int action) {
// TODO(pkasting): http://b/1111308 We should let other people, like ICU and
// GURL, do the work for us here instead of writing all this ourselves.
@@ -866,9 +1352,9 @@ int CALLBACK AutocompleteEdit::WordBreakProc(LPTSTR edit_text,
}
// static
-bool AutocompleteEdit::SchemeEnd(LPTSTR edit_text,
- int current_pos,
- int length) {
+bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text,
+ int current_pos,
+ int length) {
return (current_pos >= 0) &&
((length - current_pos) > 2) &&
(edit_text[current_pos] == ':') &&
@@ -877,7 +1363,8 @@ bool AutocompleteEdit::SchemeEnd(LPTSTR edit_text,
}
// static
-HDC AutocompleteEdit::BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) {
+HDC AutocompleteEditView::BeginPaintIntercept(HWND hWnd,
+ LPPAINTSTRUCT lpPaint) {
if (!edit_hwnd || (hWnd != edit_hwnd))
return ::BeginPaint(hWnd, lpPaint);
@@ -886,13 +1373,13 @@ HDC AutocompleteEdit::BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) {
}
// static
-BOOL AutocompleteEdit::EndPaintIntercept(HWND hWnd,
- CONST PAINTSTRUCT* lpPaint) {
+BOOL AutocompleteEditView::EndPaintIntercept(HWND hWnd,
+ const PAINTSTRUCT* lpPaint) {
return (edit_hwnd && (hWnd == edit_hwnd)) ?
true : ::EndPaint(hWnd, lpPaint);
}
-void AutocompleteEdit::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
+void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
// Don't let alt-enter beep. Not sure this is necessary, as the standard
// alt-enter will hit DiscardWMSysChar() and get thrown away, and
// ctrl-alt-enter doesn't seem to reach here for some reason? At least not on
@@ -913,7 +1400,7 @@ void AutocompleteEdit::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags);
}
-void AutocompleteEdit::OnContextMenu(HWND window, const CPoint& point) {
+void AutocompleteEditView::OnContextMenu(HWND window, const CPoint& point) {
if (point.x == -1 || point.y == -1) {
POINT p;
GetCaretPos(&p);
@@ -924,7 +1411,7 @@ void AutocompleteEdit::OnContextMenu(HWND window, const CPoint& point) {
}
}
-void AutocompleteEdit::OnCopy() {
+void AutocompleteEditView::OnCopy() {
const std::wstring text(GetSelectedText());
if (text.empty())
return;
@@ -939,20 +1426,16 @@ void AutocompleteEdit::OnCopy() {
if (static_cast<int>(text.length()) < GetTextLength())
return;
- // The entire control is selected. Let's see what the user typed. Usually
- // we'd use GetDesiredTLD() to figure out the TLD, but right now the user is
- // probably holding down control to cause the copy (which would make us always
- // think the user wanted ".com" added).
- url_parse::Parsed parts;
- const AutocompleteInput::Type type = AutocompleteInput::Parse(
- UserTextFromDisplayText(text), std::wstring(), &parts, NULL);
- if (type == AutocompleteInput::URL) {
- const GURL url(URLFixerUpper::FixupURL(text, std::wstring()));
+ // The entire control is selected. Let's see what the user typed. We can't
+ // use model_->CurrentTextIsURL() or model_->GetDataForURLExport() because
+ // right now the user is probably holding down control to cause the copy,
+ // which will screw up our calculation of the desired_tld.
+ GURL url;
+ if (model_->GetURLForText(text, &url))
clipboard->WriteHyperlink(text, url.spec());
- }
}
-void AutocompleteEdit::OnCut() {
+void AutocompleteEditView::OnCut() {
OnCopy();
// This replace selection will have no effect (even on the undo stack) if the
@@ -960,7 +1443,9 @@ void AutocompleteEdit::OnCut() {
ReplaceSel(L"", true);
}
-LRESULT AutocompleteEdit::OnGetObject(UINT uMsg, WPARAM wparam, LPARAM lparam) {
+LRESULT AutocompleteEditView::OnGetObject(UINT uMsg,
+ WPARAM wparam,
+ LPARAM lparam) {
// Accessibility readers will send an OBJID_CLIENT message.
if (lparam == OBJID_CLIENT) {
// Re-attach for internal re-usage of accessibility pointer.
@@ -974,7 +1459,7 @@ LRESULT AutocompleteEdit::OnGetObject(UINT uMsg, WPARAM wparam, LPARAM lparam) {
return 0;
}
-LRESULT AutocompleteEdit::OnImeComposition(UINT message,
+LRESULT AutocompleteEditView::OnImeComposition(UINT message,
WPARAM wparam,
LPARAM lparam) {
ScopedFreeze freeze(this, GetTextObjectModel());
@@ -993,7 +1478,7 @@ LRESULT AutocompleteEdit::OnImeComposition(UINT message,
return result;
}
-void AutocompleteEdit::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) {
+void AutocompleteEditView::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) {
if (OnKeyDownAllModes(key, repeat_count, flags) || popup_window_mode_ ||
OnKeyDownOnlyWritable(key, repeat_count, flags))
return;
@@ -1003,42 +1488,28 @@ void AutocompleteEdit::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) {
HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags);
}
-void AutocompleteEdit::OnKeyUp(TCHAR key, UINT repeat_count, UINT flags) {
- if ((key == VK_CONTROL) && (control_key_state_ != UP)) {
- control_key_state_ = UP;
- if (popup_->is_open()) {
- // Autocomplete history provider results may change, so refresh the
- // popup. This will force user_input_in_progress_ to true, but if the
- // popup is open, that should have already been the case.
- UpdatePopup();
- }
- }
+void AutocompleteEditView::OnKeyUp(TCHAR key, UINT repeat_count, UINT flags) {
+ if (key == VK_CONTROL)
+ model_->OnControlKeyChanged(false);
SetMsgHandled(false);
}
-void AutocompleteEdit::OnKillFocus(HWND focus_wnd) {
+void AutocompleteEditView::OnKillFocus(HWND focus_wnd) {
if (m_hWnd == focus_wnd) {
// Focus isn't actually leaving.
SetMsgHandled(false);
return;
}
- has_focus_ = false;
- control_key_state_ = UP;
- paste_state_ = NONE;
-
// Close the popup.
ClosePopup();
// Save the user's existing selection to restore it later.
GetSelection(saved_selection_for_focus_change_);
- // Like typing, killing focus "accepts" the temporary text as the user
- // text, because it makes little sense to have temporary text when the
- // popup is closed.
- InternalSetUserText(UserTextFromDisplayText(GetText()));
- has_temporary_text_ = false;
+ // Tell the model to reset itself.
+ model_->OnKillFocus();
// Let the CRichEditCtrl do its default handling. This will complete any
// in-progress IME composition. We must do this after setting has_focus_ to
@@ -1051,7 +1522,8 @@ void AutocompleteEdit::OnKillFocus(HWND focus_wnd) {
// 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 (show_search_hint_ || (is_keyword_hint_ && !keyword_.empty()))
+ 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
@@ -1061,7 +1533,7 @@ void AutocompleteEdit::OnKillFocus(HWND focus_wnd) {
PlaceCaretAt(0);
}
-void AutocompleteEdit::OnLButtonDblClk(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnLButtonDblClk(UINT keys, const CPoint& point) {
// Save the double click info for later triple-click detection.
tracking_double_click_ = true;
double_click_point_ = point;
@@ -1079,7 +1551,7 @@ void AutocompleteEdit::OnLButtonDblClk(UINT keys, const CPoint& point) {
gaining_focus_.reset(); // See NOTE in OnMouseActivate().
}
-void AutocompleteEdit::OnLButtonDown(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnLButtonDown(UINT keys, const CPoint& point) {
if (gaining_focus_.get()) {
// This click is giving us focus, so we need to track how much the mouse
// moves to see if it's a drag or just a click. Clicks should select all
@@ -1129,7 +1601,7 @@ void AutocompleteEdit::OnLButtonDown(UINT keys, const CPoint& point) {
gaining_focus_.reset();
}
-void AutocompleteEdit::OnLButtonUp(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnLButtonUp(UINT keys, const CPoint& point) {
// default processing should happen first so we can see the result of the
// selection
ScopedFreeze freeze(this, GetTextObjectModel());
@@ -1149,9 +1621,9 @@ void AutocompleteEdit::OnLButtonUp(UINT keys, const CPoint& point) {
UpdateDragDone(keys);
}
-LRESULT AutocompleteEdit::OnMouseActivate(HWND window,
- UINT hit_test,
- UINT mouse_message) {
+LRESULT AutocompleteEditView::OnMouseActivate(HWND window,
+ UINT hit_test,
+ UINT mouse_message) {
// First, give other handlers a chance to handle the message to see if we are
// actually going to activate and gain focus.
LRESULT result = DefWindowProc(WM_MOUSEACTIVATE,
@@ -1162,7 +1634,7 @@ LRESULT AutocompleteEdit::OnMouseActivate(HWND window,
// reached before OnLButtonDown(), preventing us from detecting this properly
// there. Also in those cases, we need to already know in OnSetFocus() that
// we should not restore the saved selection.
- if (!has_focus_ && (mouse_message == WM_LBUTTONDOWN) &&
+ if (!model_->has_focus() && (mouse_message == WM_LBUTTONDOWN) &&
(result == MA_ACTIVATE)) {
DCHECK(!gaining_focus_.get());
gaining_focus_.reset(new ScopedFreeze(this, GetTextObjectModel()));
@@ -1179,7 +1651,7 @@ LRESULT AutocompleteEdit::OnMouseActivate(HWND window,
return result;
}
-void AutocompleteEdit::OnMouseMove(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnMouseMove(UINT keys, const CPoint& point) {
if (possible_drag_) {
StartDragIfNecessary(point);
// Don't fall through to default mouse handling, otherwise a second
@@ -1252,7 +1724,7 @@ void AutocompleteEdit::OnMouseMove(UINT keys, const CPoint& point) {
}
}
-void AutocompleteEdit::OnPaint(HDC bogus_hdc) {
+void AutocompleteEditView::OnPaint(HDC bogus_hdc) {
// We need to paint over the top of the edit. If we simply let the edit do
// its default painting, then do ours into the window DC, the screen is
// updated in between and we can get flicker. To avoid this, we force the
@@ -1316,7 +1788,7 @@ void AutocompleteEdit::OnPaint(HDC bogus_hdc) {
edit_hwnd = old_edit_hwnd;
}
-void AutocompleteEdit::OnNonLButtonDown(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnNonLButtonDown(UINT keys, const CPoint& point) {
// Interestingly, the edit doesn't seem to cancel triple clicking when the
// x-buttons (which usually means "thumb buttons") are pressed, so we only
// call this for M and R down.
@@ -1327,14 +1799,14 @@ void AutocompleteEdit::OnNonLButtonDown(UINT keys, const CPoint& point) {
SetMsgHandled(false);
}
-void AutocompleteEdit::OnNonLButtonUp(UINT keys, const CPoint& point) {
+void AutocompleteEditView::OnNonLButtonUp(UINT keys, const CPoint& point) {
UpdateDragDone(keys);
// Let default handler have a crack at this.
SetMsgHandled(false);
}
-void AutocompleteEdit::OnPaste() {
+void AutocompleteEditView::OnPaste() {
// Replace the selection if we have something to paste.
const std::wstring text(GetClipboardText());
if (!text.empty()) {
@@ -1343,18 +1815,18 @@ void AutocompleteEdit::OnPaste() {
CHARRANGE sel;
GetSel(sel);
if (IsSelectAll(sel))
- paste_state_ = REPLACING_ALL;
+ model_->on_paste_replacing_all();
ReplaceSel(text.c_str(), true);
}
}
-void AutocompleteEdit::OnSetFocus(HWND focus_wnd) {
- has_focus_ = true;
- control_key_state_ = (GetKeyState(VK_CONTROL) < 0) ? DOWN_WITHOUT_CHANGE : UP;
+void AutocompleteEditView::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 (show_search_hint_ || (is_keyword_hint_ && !keyword_.empty()))
+ if (model_->show_search_hint() ||
+ (model_->is_keyword_hint() && !model_->keyword().empty()))
controller_->OnChanged();
// Restore saved selection if available.
@@ -1366,7 +1838,7 @@ void AutocompleteEdit::OnSetFocus(HWND focus_wnd) {
SetMsgHandled(false);
}
-void AutocompleteEdit::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
+void AutocompleteEditView::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
// Nearly all alt-<xxx> combos result in beeping rather than doing something
// useful, so we discard most. Exceptions:
// * ctrl-alt-<xxx>, which is sometimes important, generates WM_CHAR instead
@@ -1378,17 +1850,19 @@ void AutocompleteEdit::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) {
SetMsgHandled(false);
}
-void AutocompleteEdit::HandleKeystroke(UINT message, TCHAR key,
- UINT repeat_count, UINT flags) {
+void AutocompleteEditView::HandleKeystroke(UINT message,
+ TCHAR key,
+ UINT repeat_count,
+ UINT flags) {
ScopedFreeze freeze(this, GetTextObjectModel());
OnBeforePossibleChange();
DefWindowProc(message, key, MAKELPARAM(repeat_count, flags));
OnAfterPossibleChange();
}
-bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
- UINT repeat_count,
- UINT flags) {
+bool AutocompleteEditView::OnKeyDownOnlyWritable(TCHAR key,
+ UINT repeat_count,
+ UINT flags) {
// NOTE: Annoyingly, ctrl-alt-<key> generates WM_KEYDOWN rather than
// WM_SYSKEYDOWN, so we need to check (flags & KF_ALTDOWN) in various places
// in this function even with a WM_SYSKEYDOWN handler.
@@ -1396,8 +1870,8 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
int count = repeat_count;
switch (key) {
case VK_RETURN:
- AcceptInput((flags & KF_ALTDOWN) ? NEW_FOREGROUND_TAB : CURRENT_TAB,
- false);
+ model_->AcceptInput((flags & KF_ALTDOWN) ?
+ NEW_FOREGROUND_TAB : CURRENT_TAB, false);
return true;
case VK_UP:
@@ -1407,38 +1881,7 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
if (flags & KF_ALTDOWN)
return false;
- // NOTE: VK_DOWN/VK_UP purposefully don't trigger any code that resets
- // paste_state_.
- disable_keyword_ui_ = false;
- if (!popup_->is_open()) {
- if (!popup_->query_in_progress()) {
- // The popup is neither open nor working on a query already. So,
- // start an autocomplete query for the current text. This also sets
- // user_input_in_progress_ to true, which we want: if the user has
- // started to interact with the popup, changing the permanent_text_
- // shouldn't change the displayed text.
- // Note: This does not force the popup to open immediately.
- if (!user_input_in_progress_)
- InternalSetUserText(permanent_text_);
- DCHECK(user_text_ == UserTextFromDisplayText(GetText()));
- UpdatePopup();
- }
-
- // Now go ahead and force the popup to open, and copy the text of the
- // default item into the edit. We ignore |count|, since without the
- // popup open, the user doesn't really know what they're interacting
- // with. Since the user hit an arrow key to explicitly open the popup,
- // we assume that they prefer the temporary text of the default item
- // to their own text, like we do when they arrow around an already-open
- // popup. In many cases the existing text in the edit and the new text
- // will be the same, and the only visible effect will be to cancel any
- // selection and place the cursor at the end of the edit.
- popup_->Move(0);
- } else {
- // The popup is open, so the user should be able to interact with it
- // normally.
- popup_->Move(count);
- }
+ model_->OnUpOrDownKeyPressed(count);
return true;
// Hijacking Editing Commands
@@ -1463,7 +1906,7 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
case VK_DELETE:
if ((flags & KF_ALTDOWN) || GetKeyState(VK_SHIFT) >= 0)
return false;
- if (control_key_state_ == UP) {
+ if (GetKeyState(VK_CONTROL) >= 0) {
// Cut text if possible.
CHARRANGE selection;
GetSel(selection);
@@ -1472,18 +1915,18 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
OnBeforePossibleChange();
Cut();
OnAfterPossibleChange();
- } else if (popup_->is_open()) {
+ } else if (popup_model_->is_open()) {
// This is a bit overloaded, but we hijack Shift-Delete in this
// case to delete the current item from the pop-up. We prefer cutting
// to this when possible since that's the behavior more people expect
// from Shift-Delete, and it's more commonly useful.
- popup_->TryDeletingCurrentItem();
+ popup_model_->TryDeletingCurrentItem();
}
}
return true;
case 'X':
- if ((flags & KF_ALTDOWN) || (control_key_state_ == UP))
+ if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0))
return false;
if (GetKeyState(VK_SHIFT) >= 0) {
ScopedFreeze freeze(this, GetTextObjectModel());
@@ -1495,11 +1938,10 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
case VK_INSERT:
case 'V':
- if ((flags & KF_ALTDOWN) || ((key == 'V') ?
- (control_key_state_ == UP) : (GetKeyState(VK_SHIFT) >= 0)))
+ if ((flags & KF_ALTDOWN) ||
+ (GetKeyState((key == 'V') ? VK_CONTROL : VK_SHIFT) >= 0))
return false;
- if ((key == 'V') ?
- (GetKeyState(VK_SHIFT) >= 0) : (control_key_state_ == UP)) {
+ if (GetKeyState((key == 'V') ? VK_SHIFT : VK_CONTROL) >= 0) {
ScopedFreeze freeze(this, GetTextObjectModel());
OnBeforePossibleChange();
Paste();
@@ -1508,7 +1950,8 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
return true;
case VK_BACK: {
- if ((flags & KF_ALTDOWN) || is_keyword_hint_ || keyword_.empty())
+ if ((flags & KF_ALTDOWN) || model_->is_keyword_hint() ||
+ model_->keyword().empty())
return false;
{
@@ -1519,41 +1962,17 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
}
// We're showing a keyword and the user pressed backspace at the beginning
- // of the text. Delete the trailing space from the keyword forcing the
- // selected keyword to become empty.
+ // of the text. Delete the selected keyword.
ScopedFreeze freeze(this, GetTextObjectModel());
- OnBeforePossibleChange();
- const std::wstring window_text(keyword_ + GetText());
- SetWindowText(window_text.c_str());
- PlaceCaretAt(keyword_.length());
- popup_->manually_selected_match_.Clear();
- keyword_.clear();
- OnAfterPossibleChange();
- just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this
- // since the edit contents have actually grown
- // longer.
+ model_->ClearKeyword(GetText());
return true;
}
case VK_TAB: {
- if (is_keyword_hint_ && !keyword_.empty()) {
+ if (model_->is_keyword_hint() && !model_->keyword().empty()) {
// Accept the keyword.
ScopedFreeze freeze(this, GetTextObjectModel());
- OnBeforePossibleChange();
- SetWindowText(L"");
- popup_->manually_selected_match_.Clear();
- popup_->manually_selected_match_.provider_affinity =
- popup_->autocomplete_controller()->keyword_provider();
- is_keyword_hint_ = false;
- disable_keyword_ui_ = false;
- OnAfterPossibleChange();
- just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets
- // this since the edit contents have
- // disappeared. It doesn't really matter,
- // but we clear it to be consistent.
-
- // Send out notification (primarily for logging).
- UserMetrics::RecordAction(L"AcceptedKeywordHint", profile_);
+ model_->AcceptKeyword();
}
return true;
}
@@ -1566,28 +1985,19 @@ bool AutocompleteEdit::OnKeyDownOnlyWritable(TCHAR key,
}
}
-bool AutocompleteEdit::OnKeyDownAllModes(TCHAR key,
- UINT repeat_count,
- UINT flags) {
+bool AutocompleteEditView::OnKeyDownAllModes(TCHAR key,
+ UINT repeat_count,
+ UINT flags) {
// See KF_ALTDOWN comment atop OnKeyDownOnlyWriteable().
switch (key) {
case VK_CONTROL:
- if (control_key_state_ == UP) {
- control_key_state_ = DOWN_WITHOUT_CHANGE;
- if (popup_->is_open()) {
- DCHECK(!popup_window_mode_); // How did the popup get open in read-only mode?
- // Autocomplete history provider results may change, so refresh the
- // popup. This will force user_input_in_progress_ to true, but if the
- // popup is open, that should have already been the case.
- UpdatePopup();
- }
- }
+ model_->OnControlKeyChanged(true);
return false;
case 'C':
// See more detailed comments in OnKeyDownOnlyWriteable().
- if ((flags & KF_ALTDOWN) || (control_key_state_ == UP))
+ if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0))
return false;
if (GetKeyState(VK_SHIFT) >= 0)
Copy();
@@ -1598,134 +2008,7 @@ bool AutocompleteEdit::OnKeyDownAllModes(TCHAR key,
}
}
-void AutocompleteEdit::OnBeforePossibleChange() {
- // Record our state.
- text_before_change_ = GetText();
- GetSelection(sel_before_change_);
- select_all_before_change_ = IsSelectAll(sel_before_change_);
-}
-
-bool AutocompleteEdit::OnAfterPossibleChange() {
- // Prevent the user from selecting the "phantom newline" at the end of the
- // edit. If they try, we just silently move the end of the selection back to
- // the end of the real text.
- CHARRANGE new_sel;
- GetSelection(new_sel);
- const int length = GetTextLength();
- if ((new_sel.cpMin > length) || (new_sel.cpMax > length)) {
- if (new_sel.cpMin > length)
- new_sel.cpMin = length;
- if (new_sel.cpMax > length)
- new_sel.cpMax = length;
- SetSelectionRange(new_sel);
- }
- const bool selection_differs = (new_sel.cpMin != sel_before_change_.cpMin) ||
- (new_sel.cpMax != sel_before_change_.cpMax);
-
- // See if the text or selection have changed since OnBeforePossibleChange().
- const std::wstring new_text(GetText());
- const bool text_differs = (new_text != text_before_change_);
-
- // Update the paste state as appropriate: if we're just finishing a paste
- // that replaced all the text, preserve that information; otherwise, if we've
- // made some other edit, clear paste tracking.
- if (paste_state_ == REPLACING_ALL)
- paste_state_ = REPLACED_ALL;
- else if (text_differs)
- paste_state_ = NONE;
-
- // If something has changed while the control key is down, prevent
- // "ctrl-enter" until the control key is released. When we do this, we need
- // to update the popup if it's open, since the desired_tld will have changed.
- if ((text_differs || selection_differs) &&
- (control_key_state_ == DOWN_WITHOUT_CHANGE)) {
- control_key_state_ = DOWN_WITH_CHANGE;
- if (!text_differs && !popup_->is_open())
- return false; // Don't open the popup for no reason.
- } else if (!text_differs &&
- (inline_autocomplete_text_.empty() || !selection_differs)) {
- return false;
- }
-
- const bool had_keyword = !is_keyword_hint_ && !keyword_.empty();
-
- // Modifying the selection counts as accepting the autocompleted text.
- InternalSetUserText(UserTextFromDisplayText(new_text));
- has_temporary_text_ = false;
-
- if (text_differs) {
- // When the user has deleted text, don't allow inline autocomplete. Make
- // sure to not flag cases like selecting part of the text and then pasting
- // (or typing) the prefix of that selection. (We detect these by making
- // sure the caret, which should be after any insertion, hasn't moved
- // forward of the old selection start.)
- just_deleted_text_ = (text_before_change_.length() > new_text.length()) &&
- (new_sel.cpMin <= std::min(sel_before_change_.cpMin,
- sel_before_change_.cpMax));
-
- // When the user doesn't have a selected keyword, deleting text or replacing
- // all of it with something else should reset the provider affinity. The
- // typical use case for deleting is that the user starts typing, sees that
- // some entry is close to what he wants, arrows to it, and then deletes some
- // unnecessary bit from the end of the string. In this case the user didn't
- // actually want "provider X", he wanted the string from that entry for
- // editing purposes, and he's no longer looking at the popup to notice that,
- // despite deleting some text, the action we'll take on enter hasn't changed
- // at all.
- if (!had_keyword && (just_deleted_text_ || select_all_before_change_)) {
- popup_->manually_selected_match_.Clear();
- }
- }
-
- // Disable the fancy keyword UI if the user didn't already have a visible
- // keyword and is not at the end of the edit. This prevents us from showing
- // the fancy UI (and interrupting the user's editing) if the user happens to
- // have a keyword for 'a', types 'ab' then puts a space between the 'a' and
- // the 'b'.
- disable_keyword_ui_ = (is_keyword_hint_ || keyword_.empty()) &&
- ((new_sel.cpMax != length) || (new_sel.cpMin != length));
-
- UpdatePopup();
-
- if (!had_keyword && !is_keyword_hint_ && !keyword_.empty()) {
- // Went from no selected keyword to a selected keyword. Set the affinity to
- // the keyword provider. This forces the selected keyword to persist even
- // if the user deletes all the text.
- popup_->manually_selected_match_.Clear();
- popup_->manually_selected_match_.provider_affinity =
- popup_->autocomplete_controller()->keyword_provider();
- }
-
- if (text_differs)
- TextChanged();
-
- return true;
-}
-
-void AutocompleteEdit::SetUserText(const std::wstring& text,
- const std::wstring& display_text,
- bool update_popup) {
- ScopedFreeze freeze(this, GetTextObjectModel());
- SetInputInProgress(true);
- paste_state_ = NONE;
- InternalSetUserText(text);
- SetWindowText(display_text.c_str());
- PlaceCaretAt(display_text.length());
- saved_selection_for_focus_change_.cpMin = -1;
- has_temporary_text_ = false;
- popup_->manually_selected_match_.Clear();
- if (update_popup)
- UpdatePopup();
- TextChanged();
-}
-
-void AutocompleteEdit::InternalSetUserText(const std::wstring& text) {
- user_text_ = text;
- just_deleted_text_ = false;
- inline_autocomplete_text_.clear();
-}
-
-void AutocompleteEdit::GetSelection(CHARRANGE& sel) const {
+void AutocompleteEditView::GetSelection(CHARRANGE& sel) const {
GetSel(sel);
// See if we need to reverse the direction of the selection.
@@ -1738,7 +2021,7 @@ void AutocompleteEdit::GetSelection(CHARRANGE& sel) const {
std::swap(sel.cpMin, sel.cpMax);
}
-std::wstring AutocompleteEdit::GetSelectedText() const {
+std::wstring AutocompleteEditView::GetSelectedText() const {
// Figure out the length of the selection.
CHARRANGE sel;
GetSel(sel);
@@ -1749,7 +2032,7 @@ std::wstring AutocompleteEdit::GetSelectedText() const {
return str;
}
-void AutocompleteEdit::SetSelection(LONG start, LONG end) {
+void AutocompleteEditView::SetSelection(LONG start, LONG end) {
SetSel(start, end);
if (start <= end)
@@ -1762,18 +2045,18 @@ void AutocompleteEdit::SetSelection(LONG start, LONG end) {
selection->SetFlags(tomSelStartActive);
}
-void AutocompleteEdit::PlaceCaretAt(std::wstring::size_type pos) {
+void AutocompleteEditView::PlaceCaretAt(std::wstring::size_type pos) {
SetSelection(static_cast<LONG>(pos), static_cast<LONG>(pos));
}
-bool AutocompleteEdit::IsSelectAll(const CHARRANGE& sel) const {
+bool AutocompleteEditView::IsSelectAll(const CHARRANGE& sel) const {
const int text_length = GetTextLength();
return ((sel.cpMin == 0) && (sel.cpMax >= text_length)) ||
((sel.cpMax == 0) && (sel.cpMin >= text_length));
}
-LONG AutocompleteEdit::ClipXCoordToVisibleText(LONG x,
- bool is_triple_click) const {
+LONG AutocompleteEditView::ClipXCoordToVisibleText(LONG x,
+ bool is_triple_click) const {
// Clip the X coordinate to the left edge of the text. Careful:
// PosFromChar(0) may return a negative X coordinate if the beginning of the
// text has scrolled off the edit, so don't go past the clip rect's edge.
@@ -1804,7 +2087,7 @@ LONG AutocompleteEdit::ClipXCoordToVisibleText(LONG x,
return is_triple_click ? (right_bound - 1) : right_bound;
}
-void AutocompleteEdit::EmphasizeURLComponents() {
+void AutocompleteEditView::EmphasizeURLComponents() {
ITextDocument* const text_object_model = GetTextObjectModel();
ScopedFreeze freeze(this, text_object_model);
ScopedSuspendUndo suspend_undo(text_object_model);
@@ -1814,31 +2097,20 @@ void AutocompleteEdit::EmphasizeURLComponents() {
GetSelection(saved_sel);
// See whether the contents are a URL with a non-empty host portion, which we
- // should emphasize.
+ // should emphasize. To check for a URL, rather than using the type returned
+ // by Parse(), ask the model, which will check the desired page transition for
+ // this input. This can tell us whether an UNKNOWN input string is going to
+ // be treated as a search or a navigation, and is the same method the Paste
+ // And Go system uses.
url_parse::Parsed parts;
- AutocompleteInput::Parse(GetText(), GetDesiredTLD(), &parts, NULL);
- bool emphasize = (parts.host.len > 0);
- // 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
- // initializing the history system, as long as possible, which speeds startup.
- if (user_input_in_progress_) {
- // Rather than using the type returned by Parse(), key off the desired page
- // transition for this input since that can tell us whether an UNKNOWN input
- // string is going to be treated as a search or a navigation. This is the
- // same method the Paste And Go system uses.
- PageTransition::Type transition = PageTransition::LINK;
- GetURLForCurrentText(&transition, NULL, NULL);
- if (transition != PageTransition::TYPED)
- emphasize = false;
- }
+ AutocompleteInput::Parse(GetText(), model_->GetDesiredTLD(), &parts, NULL);
+ const bool emphasize = model_->CurrentTextIsURL() && (parts.host.len > 0);
// Set the baseline emphasis.
CHARFORMAT cf = {0};
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0;
- cf.crTextColor = (emphasize ? GetSysColor(COLOR_GRAYTEXT) :
- GetSysColor(COLOR_WINDOWTEXT));
+ cf.crTextColor = GetSysColor(emphasize ? COLOR_GRAYTEXT : COLOR_WINDOWTEXT);
SelectAll(false);
SetSelectionCharFormat(cf);
@@ -1851,9 +2123,8 @@ void AutocompleteEdit::EmphasizeURLComponents() {
// Emphasize the scheme for security UI display purposes (if necessary).
insecure_scheme_component_.reset();
- if (!user_input_in_progress_ && parts.scheme.is_nonempty() &&
- ((scheme_security_level_ == ToolbarModel::SECURE) ||
- (scheme_security_level_ == ToolbarModel::INSECURE))) {
+ if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() &&
+ (scheme_security_level_ != ToolbarModel::NORMAL)) {
if (scheme_security_level_ == ToolbarModel::SECURE) {
cf.crTextColor = kSecureSchemeColor;
} else {
@@ -1869,9 +2140,9 @@ void AutocompleteEdit::EmphasizeURLComponents() {
SetSelectionRange(saved_sel);
}
-void AutocompleteEdit::EraseTopOfSelection(CDC* dc,
- const CRect& client_rect,
- const CRect& paint_clip_rect) {
+void AutocompleteEditView::EraseTopOfSelection(CDC* dc,
+ const CRect& client_rect,
+ const CRect& paint_clip_rect) {
// Find the area we care about painting. We could calculate the rect
// containing just the selected portion, but there's no harm in simply erasing
// the whole top of the client area, and at least once I saw us manage to
@@ -1886,7 +2157,7 @@ void AutocompleteEdit::EraseTopOfSelection(CDC* dc,
dc->FillSolidRect(&erase_rect, background_color_);
}
-void AutocompleteEdit::DrawSlashForInsecureScheme(
+void AutocompleteEditView::DrawSlashForInsecureScheme(
HDC hdc,
const CRect& client_rect,
const CRect& paint_clip_rect) {
@@ -1978,9 +2249,9 @@ void AutocompleteEdit::DrawSlashForInsecureScheme(
canvas_clip_rect.top, &canvas_paint_clip_rect);
}
-void AutocompleteEdit::DrawDropHighlight(HDC hdc,
- const CRect& client_rect,
- const CRect& paint_clip_rect) {
+void AutocompleteEditView::DrawDropHighlight(HDC hdc,
+ const CRect& client_rect,
+ const CRect& paint_clip_rect) {
DCHECK(drop_highlight_position_ != -1);
const int highlight_y = client_rect.top + font_y_adjustment_;
@@ -2002,65 +2273,13 @@ void AutocompleteEdit::DrawDropHighlight(HDC hdc,
DeleteObject(SelectObject(hdc, last_pen));
}
-std::wstring AutocompleteEdit::GetDesiredTLD() const {
- return (control_key_state_ == DOWN_WITHOUT_CHANGE) ? L"com" : L"";
-}
-
-void AutocompleteEdit::UpdatePopup() {
- ScopedFreeze freeze(this, GetTextObjectModel());
- SetInputInProgress(true);
-
- if (!has_focus_) {
- // When we're in the midst of losing focus, don't rerun autocomplete. This
- // can happen when losing focus causes the IME to cancel/finalize a
- // composition. We still want to note that user input is in progress, we
- // just don't want to do anything else.
- //
- // Note that in this case the ScopedFreeze above was unnecessary; however,
- // we're inside the callstack of OnKillFocus(), which has already frozen the
- // edit, so this will never result in an unnecessary UpdateWindow() call.
- return;
- }
-
- // Figure out whether the user is trying to compose something in an IME.
- bool ime_composing = false;
- HIMC context = ImmGetContext(m_hWnd);
- if (context) {
- ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
- ImmReleaseContext(m_hWnd, context);
- }
-
- // Don't inline autocomplete when:
- // * The user is deleting text
- // * The caret/selection isn't at the end of the text
- // * The user has just pasted in something that replaced all the text
- // * The user is trying to compose something in an IME
- CHARRANGE sel;
- GetSel(sel);
- popup_->StartAutocomplete(user_text_, GetDesiredTLD(),
- just_deleted_text_ || (sel.cpMax < GetTextLength()) ||
- (paste_state_ != NONE) || ime_composing);
-}
-
-void AutocompleteEdit::TextChanged() {
+void AutocompleteEditView::TextChanged() {
ScopedFreeze freeze(this, GetTextObjectModel());
EmphasizeURLComponents();
controller_->OnChanged();
}
-std::wstring AutocompleteEdit::DisplayTextFromUserText(
- const std::wstring& text) const {
- return (is_keyword_hint_ || keyword_.empty()) ?
- text : KeywordProvider::SplitReplacementStringFromInput(text);
-}
-
-std::wstring AutocompleteEdit::UserTextFromDisplayText(
- const std::wstring& text) const {
- return (is_keyword_hint_ || keyword_.empty()) ?
- text : (keyword_ + L" " + text);
-}
-
-std::wstring AutocompleteEdit::GetClipboardText() const {
+std::wstring AutocompleteEditView::GetClipboardText() const {
// Try text format.
ClipboardService* clipboard = g_browser_process->clipboard_service();
if (clipboard->IsFormatAvailable(CF_UNICODETEXT)) {
@@ -2095,93 +2314,11 @@ std::wstring AutocompleteEdit::GetClipboardText() const {
return std::wstring();
}
-bool AutocompleteEdit::CanPasteAndGo(const std::wstring& text) const {
- if (popup_window_mode_)
- return false;
-
- // Reset local state.
- paste_and_go_url_.clear();
- paste_and_go_transition_ = PageTransition::TYPED;
- paste_and_go_alternate_nav_url_.clear();
-
- // See if the clipboard text can be parsed.
- const AutocompleteInput input(text, std::wstring(), true);
- if (input.type() == AutocompleteInput::INVALID)
- return false;
-
- // Ask the controller what do do with this input.
- paste_and_go_controller->SetProfile(profile_);
- // This is cheap, and since there's one
- // paste_and_go_controller for many tabs which
- // may all have different profiles, it ensures
- // we're always using the right one.
- const bool done = paste_and_go_controller->Start(input, false, true);
- DCHECK(done);
- AutocompleteResult result;
- paste_and_go_controller->GetResult(&result);
- if (result.empty())
- return false;
-
- // Set local state based on the default action for this input.
- result.SetDefaultMatch(AutocompleteResult::Selection());
- const AutocompleteResult::const_iterator match(result.default_match());
- DCHECK(match != result.end());
- paste_and_go_url_ = match->destination_url;
- paste_and_go_transition_ = match->transition;
- paste_and_go_alternate_nav_url_ = result.GetAlternateNavURL(input, match);
-
- return !paste_and_go_url_.empty();
-}
-
-void AutocompleteEdit::PasteAndGo() {
- // The final parameter to OpenURL, keyword, is not quite correct here: it's
- // possible to "paste and go" a string that contains a keyword. This is
- // enough of an edge case that we ignore this possibility.
- RevertAll();
- OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_,
- paste_and_go_alternate_nav_url_, AutocompletePopupModel::kNoMatch,
- std::wstring());
+bool AutocompleteEditView::CanPasteAndGo(const std::wstring& text) const {
+ return !popup_window_mode_ && model_->CanPasteAndGo(text);
}
-void AutocompleteEdit::SetInputInProgress(bool in_progress) {
- if (user_input_in_progress_ == in_progress)
- return;
-
- user_input_in_progress_ = in_progress;
- controller_->OnInputInProgress(in_progress);
-}
-
-void AutocompleteEdit::SendOpenNotification(size_t selected_line,
- const std::wstring& keyword) {
- // We only care about cases where there is a selection (i.e. the popup is
- // open).
- if (popup_->is_open()) {
- scoped_ptr<AutocompleteLog> log(popup_->GetAutocompleteLog());
- if (selected_line != AutocompletePopupModel::kNoMatch)
- log->selected_index = selected_line;
- else if (!has_temporary_text_)
- log->inline_autocompleted_length = inline_autocomplete_text_.length();
- NotificationService::current()->Notify(
- NOTIFY_OMNIBOX_OPENED_URL, Source<Profile>(profile_),
- Details<AutocompleteLog>(log.get()));
- }
-
- TemplateURLModel* template_url_model = profile_->GetTemplateURLModel();
- if (keyword.empty() || !template_url_model)
- return;
-
- const TemplateURL* const template_url =
- template_url_model->GetTemplateURLForKeyword(keyword);
- if (template_url) {
- UserMetrics::RecordAction(L"AcceptedKeyword", profile_);
- template_url_model->IncrementUsageCount(template_url);
- }
-
- // NOTE: We purposefully don't increment the usage count of the default search
- // engine, if applicable; see comments in template_url.h.
-}
-
-ITextDocument* AutocompleteEdit::GetTextObjectModel() const {
+ITextDocument* AutocompleteEditView::GetTextObjectModel() const {
if (!text_object_model_) {
// This is lazily initialized, instead of being initialized in the
// constructor, in order to avoid hurting startup performance.
@@ -2192,7 +2329,7 @@ ITextDocument* AutocompleteEdit::GetTextObjectModel() const {
return text_object_model_;
}
-void AutocompleteEdit::StartDragIfNecessary(const CPoint& point) {
+void AutocompleteEditView::StartDragIfNecessary(const CPoint& point) {
if (initiated_drag_ || !win_util::IsDrag(mouse_down_point_, point))
return;
@@ -2220,21 +2357,17 @@ void AutocompleteEdit::StartDragIfNecessary(const CPoint& point) {
const std::wstring start_text(GetText());
if (IsSelectAll(sel)) {
// All the text is selected, export as URL.
- const std::wstring url(GetURLForCurrentText(NULL, NULL, NULL));
+ GURL url;
std::wstring title;
SkBitmap favicon;
- if (url == permanent_text_) {
- title = controller_->GetTitle();
- favicon = controller_->GetFavIcon();
- }
- const GURL gurl(url);
- drag_utils::SetURLAndDragImage(gurl, title, favicon, data.get());
- data->SetURL(gurl, title);
+ model_->GetDataForURLExport(&url, &title, &favicon);
+ drag_utils::SetURLAndDragImage(url, title, favicon, data.get());
+ data->SetURL(url, title);
supported_modes |= DROPEFFECT_LINK;
- UserMetrics::RecordAction(L"Omnibox_DragURL", profile_);
+ UserMetrics::RecordAction(L"Omnibox_DragURL", model_->profile());
} else {
supported_modes |= DROPEFFECT_MOVE;
- UserMetrics::RecordAction(L"Omnibox_DragString", profile_);
+ UserMetrics::RecordAction(L"Omnibox_DragString", model_->profile());
}
data->SetString(GetSelectedText());
@@ -2284,7 +2417,7 @@ void AutocompleteEdit::StartDragIfNecessary(const CPoint& point) {
tracking_click_ = false;
}
-void AutocompleteEdit::OnPossibleDrag(const CPoint& point) {
+void AutocompleteEditView::OnPossibleDrag(const CPoint& point) {
if (possible_drag_)
return;
@@ -2304,12 +2437,12 @@ void AutocompleteEdit::OnPossibleDrag(const CPoint& point) {
}
}
-void AutocompleteEdit::UpdateDragDone(UINT keys) {
+void AutocompleteEditView::UpdateDragDone(UINT keys) {
possible_drag_ = (possible_drag_ &&
((keys & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) != 0));
}
-void AutocompleteEdit::RepaintDropHighlight(int position) {
+void AutocompleteEditView::RepaintDropHighlight(int position) {
if ((position != -1) && (position <= GetTextLength())) {
const POINT min_loc(PosFromChar(position));
const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_,
@@ -2317,4 +2450,3 @@ void AutocompleteEdit::RepaintDropHighlight(int position) {
InvalidateRect(&highlight_bounds, false);
}
}
-