diff options
author | suzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-28 02:36:49 +0000 |
---|---|---|
committer | suzhe@google.com <suzhe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-28 02:36:49 +0000 |
commit | 911696b92b1b5a666e59433b8b64303a2f4eae62 (patch) | |
tree | a47bab7021b5a34a532b1dae4140b8651558efd5 /chrome/browser/autocomplete | |
parent | b7d6c22f8092a652d6b4572d4800e8a6aac6ccbe (diff) | |
download | chromium_src-911696b92b1b5a666e59433b8b64303a2f4eae62.zip chromium_src-911696b92b1b5a666e59433b8b64303a2f4eae62.tar.gz chromium_src-911696b92b1b5a666e59433b8b64303a2f4eae62.tar.bz2 |
Hitting Tab should always move cursor to end of omnibox text.
BUG=66850
TEST=AutocompleteEditViewTest.TabMoveCursorToEnd and InstantTest.TabKey
Review URL: http://codereview.chromium.org/5966006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72920 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
13 files changed, 243 insertions, 116 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index 54bf5ed..4e88607 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -154,8 +154,16 @@ void AutocompleteEditModel::SetUserText(const string16& text) { void AutocompleteEditModel::FinalizeInstantQuery( const string16& input_text, - const string16& suggest_text) { - popup_->FinalizeInstantQuery(input_text, suggest_text); + const string16& suggest_text, + bool skip_inline_autocomplete) { + if (skip_inline_autocomplete) { + const string16 final_text = input_text + suggest_text; + view_->OnBeforePossibleChange(); + view_->SetWindowTextAndCaretPos(final_text, final_text.length()); + view_->OnAfterPossibleChange(); + } else { + popup_->FinalizeInstantQuery(input_text, suggest_text); + } } void AutocompleteEditModel::GetDataForURLExport(GURL* url, diff --git a/chrome/browser/autocomplete/autocomplete_edit.h b/chrome/browser/autocomplete/autocomplete_edit.h index 7b00fc6..3b8c287 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.h +++ b/chrome/browser/autocomplete/autocomplete_edit.h @@ -48,9 +48,11 @@ class AutocompleteEditController { // OnAutoCompleteAccept. virtual void OnAutocompleteWillAccept() = 0; - // Commits the suggested text. |typed_text| is the current text showing in the - // autocomplete. Returns true if the text was committed. - virtual bool OnCommitSuggestedText(const string16& typed_text) = 0; + // Commits the suggested text. If |skip_inline_autocomplete| is true then the + // suggested text will be committed as final text as if it's inputted by the + // user, rather than as inline autocomplete suggest. + // Returns true if the text was committed. + virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete) = 0; // Accepts the currently showing instant preview, if any, and returns true. // Returns false if there is no instant preview showing. @@ -191,8 +193,11 @@ class AutocompleteEditModel : public NotificationObserver { void SetUserText(const string16& text); // Calls through to SearchProvider::FinalizeInstantQuery. + // If |skip_inline_autocomplete| is true then the |suggest_text| will be + // turned into final text instead of inline autocomplete suggest. void FinalizeInstantQuery(const string16& input_text, - const string16& suggest_text); + const string16& suggest_text, + bool skip_inline_autocomplete); // Reverts the edit model back to its unedited state (permanent text showing, // no user input in progress). diff --git a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc index 7643936..9d54555 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_unittest.cc @@ -56,14 +56,12 @@ class TestingAutocompleteEditView : public AutocompleteEditView { virtual gfx::NativeView GetNativeView() const { return 0; } virtual CommandUpdater* GetCommandUpdater() { return NULL; } virtual void SetInstantSuggestion(const string16& input) {} + virtual string16 GetInstantSuggestion() const { return string16(); } virtual int TextWidth() const { return 0; } virtual bool IsImeComposing() const { return false; } #if defined(TOOLKIT_VIEWS) virtual views::View* AddToView(views::View* parent) { return NULL; } - virtual bool CommitInstantSuggestion( - const string16& typed_text, - const string16& suggested_text) { return false; } #endif private: @@ -76,7 +74,7 @@ class TestingAutocompleteEditController : public AutocompleteEditController { virtual void OnAutocompleteWillClosePopup() {} virtual void OnAutocompleteLosingFocus(gfx::NativeView view_gaining_focus) {} virtual void OnAutocompleteWillAccept() {} - virtual bool OnCommitSuggestedText(const string16& typed_text) { + virtual bool OnCommitSuggestedText(bool skip_inline_autocomplete) { return false; } virtual bool AcceptCurrentInstantPreview() { diff --git a/chrome/browser/autocomplete/autocomplete_edit_view.h b/chrome/browser/autocomplete/autocomplete_edit_view.h index 73ccb46..408c848 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view.h @@ -161,6 +161,9 @@ class AutocompleteEditView { // Shows the instant suggestion text. virtual void SetInstantSuggestion(const string16& input) = 0; + // Returns the current instant suggestion text. + virtual string16 GetInstantSuggestion() const = 0; + // Returns the width in pixels needed to display the current text. The // returned value includes margins. virtual int TextWidth() const = 0; @@ -172,10 +175,6 @@ class AutocompleteEditView { // Adds the autocomplete edit view to view hierarchy and // returns the views::View of the edit view. virtual views::View* AddToView(views::View* parent) = 0; - - // Commits the suggested text. - virtual bool CommitInstantSuggestion(const string16& typed_text, - const string16& suggested_text) = 0; #endif virtual ~AutocompleteEditView() {} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc index 1e79685..f452757 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_browsertest.cc @@ -944,6 +944,52 @@ class AutocompleteEditViewTest : public InProcessBrowserTest, ASSERT_TRUE(edit_view->IsSelectAll()); } + void TabMoveCursorToEndTest() { + AutocompleteEditView* edit_view = NULL; + ASSERT_NO_FATAL_FAILURE(GetAutocompleteEditView(&edit_view)); + + edit_view->SetUserText(ASCIIToUTF16("Hello world")); + + // Move cursor to the beginning. + ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_HOME, false, false, false)); + + string16::size_type start, end; + edit_view->GetSelectionBounds(&start, &end); + EXPECT_EQ(0U, start); + EXPECT_EQ(0U, end); + + // Pressing tab should move cursor to the end. + ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false)); + + edit_view->GetSelectionBounds(&start, &end); + EXPECT_EQ(edit_view->GetText().size(), start); + EXPECT_EQ(edit_view->GetText().size(), end); + + // The location bar should still have focus. + ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR)); + + // Select all text. + edit_view->SelectAll(true); + EXPECT_TRUE(edit_view->IsSelectAll()); + edit_view->GetSelectionBounds(&start, &end); + EXPECT_EQ(0U, start); + EXPECT_EQ(edit_view->GetText().size(), end); + + // Pressing tab should move cursor to the end. + ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false)); + + edit_view->GetSelectionBounds(&start, &end); + EXPECT_EQ(edit_view->GetText().size(), start); + EXPECT_EQ(edit_view->GetText().size(), end); + + // The location bar should still have focus. + ASSERT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR)); + + // Pressing tab when cursor is at the end should change focus. + ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_TAB, false, false, false)); + + ASSERT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_LOCATION_BAR)); + } }; // Test if ctrl-* accelerators are workable in omnibox. @@ -1005,6 +1051,10 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, DeleteItem) { DeleteItemTest(); } +IN_PROC_BROWSER_TEST_F(AutocompleteEditViewTest, TabMoveCursorToEnd) { + TabMoveCursorToEndTest(); +} + #if defined(OS_LINUX) // TODO(oshima): enable these tests for views-implmentation when // these featuers are supported. @@ -1190,4 +1240,11 @@ IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, DeleteItem) { DeleteItemTest(); } +// TODO(suzhe): This test is broken because of broken ViewID support when +// enabling AutocompleteEditViewViews. +IN_PROC_BROWSER_TEST_F(AutocompleteEditViewViewsTest, + DISABLED_TabMoveCursorToEnd) { + TabMoveCursorToEndTest(); +} + #endif diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc index 46ddb70..30db56a 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -779,6 +779,11 @@ void AutocompleteEditViewGtk::SetInstantSuggestion(const string16& suggestion) { UpdateInstantViewColors(); } +string16 AutocompleteEditViewGtk::GetInstantSuggestion() const { + const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); + return suggestion ? UTF8ToUTF16(suggestion) : string16(); +} + int AutocompleteEditViewGtk::TextWidth() const { int horizontal_border_size = gtk_text_view_get_border_window_size(GTK_TEXT_VIEW(text_view_), @@ -834,12 +839,6 @@ views::View* AutocompleteEditViewGtk::AddToView(views::View* parent) { return host; } -bool AutocompleteEditViewGtk::CommitInstantSuggestion( - const string16& typed_text, - const string16& suggestion) { - return CommitInstantSuggestion(); -} - void AutocompleteEditViewGtk::EnableAccessibility() { accessible_widget_helper_.reset( new AccessibleWidgetHelper(text_view(), model_->profile())); @@ -898,7 +897,7 @@ void AutocompleteEditViewGtk::Observe(NotificationType type, } void AutocompleteEditViewGtk::AnimationEnded(const ui::Animation* animation) { - controller_->OnCommitSuggestedText(GetText()); + controller_->OnCommitSuggestedText(false); } void AutocompleteEditViewGtk::AnimationProgressed( @@ -1344,9 +1343,6 @@ void AutocompleteEditViewGtk::HandleViewMoveCursor( if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && (count == 1 || count == -1)) { - gint cursor_pos; - g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL); - // We need to take the content direction into account when handling cursor // movement, because the behavior of Left and Right key will be inverted if // the direction is RTL. Although we should check the direction around the @@ -1369,8 +1365,8 @@ void AutocompleteEditViewGtk::HandleViewMoveCursor( text_buffer_, count == count_towards_end ? &sel_end : &sel_start); OnAfterPossibleChange(); handled = true; - } else if (count == count_towards_end && cursor_pos == GetTextLength()) { - handled = controller_->OnCommitSuggestedText(GetText()); + } else if (count == count_towards_end && !IsCaretAtEnd()) { + handled = controller_->OnCommitSuggestedText(true); } } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. // Multiply by count for the direction (if we move too much that's ok). @@ -1638,15 +1634,29 @@ void AutocompleteEditViewGtk::HandleViewMoveFocus(GtkWidget* widget, bool handled = false; // Trigger Tab to search behavior only when Tab key is pressed. - if (model_->is_keyword_hint()) { + if (model_->is_keyword_hint()) handled = model_->AcceptKeyword(); - } else if (GTK_WIDGET_VISIBLE(instant_view_)) { - controller_->OnCommitSuggestedText(GetText()); + +#if GTK_CHECK_VERSION(2, 20, 0) + if (!handled && !preedit_.empty()) handled = true; - } else { - handled = controller_->AcceptCurrentInstantPreview(); +#endif + + if (!handled && GTK_WIDGET_VISIBLE(instant_view_)) + handled = controller_->OnCommitSuggestedText(true); + + if (!handled) { + if (!IsCaretAtEnd()) { + OnBeforePossibleChange(); + PlaceCaretAt(GetTextLength()); + OnAfterPossibleChange(); + handled = true; + } } + if (!handled) + handled = controller_->AcceptCurrentInstantPreview(); + if (handled) { static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); g_signal_stop_emission(widget, signal_id, 0); @@ -1822,7 +1832,8 @@ void AutocompleteEditViewGtk::FinishUpdatingHighlightedText() { g_signal_handler_unblock(text_buffer_, mark_set_handler_id2_); } -AutocompleteEditViewGtk::CharRange AutocompleteEditViewGtk::GetSelection() { +AutocompleteEditViewGtk::CharRange + AutocompleteEditViewGtk::GetSelection() const { // You can not just use get_selection_bounds here, since the order will be // ascending, and you don't know where the user's start and end of the // selection was (if the selection was forwards or backwards). Get the @@ -1871,6 +1882,18 @@ int AutocompleteEditViewGtk::GetTextLength() const { #endif } +void AutocompleteEditViewGtk::PlaceCaretAt(int pos) { + GtkTextIter cursor; + gtk_text_buffer_get_iter_at_offset(text_buffer_, &cursor, pos); + gtk_text_buffer_place_cursor(text_buffer_, &cursor); +} + +bool AutocompleteEditViewGtk::IsCaretAtEnd() const { + const CharRange selection = GetSelection(); + return selection.cp_min == selection.cp_max && + selection.cp_min == GetTextLength(); +} + void AutocompleteEditViewGtk::EmphasizeURLComponents() { #if GTK_CHECK_VERSION(2, 20, 0) // We can't change the text style easily, if the preedit string (the text @@ -1946,16 +1969,6 @@ void AutocompleteEditViewGtk::StopAnimation() { UpdateInstantViewColors(); } -bool AutocompleteEditViewGtk::CommitInstantSuggestion() { - const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); - if (!suggestion || !*suggestion) - return false; - - model()->FinalizeInstantQuery(GetText(), - UTF8ToUTF16(suggestion)); - return true; -} - void AutocompleteEditViewGtk::TextChanged() { EmphasizeURLComponents(); controller_->OnChanged(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h index 4508ffa..27a3aaa 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -144,13 +144,12 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); virtual void SetInstantSuggestion(const string16& suggestion); + virtual string16 GetInstantSuggestion() const; virtual int TextWidth() const; virtual bool IsImeComposing() const; #if defined(TOOLKIT_VIEWS) virtual views::View* AddToView(views::View* parent); - virtual bool CommitInstantSuggestion(const string16& typed_text, - const string16& suggested_text); // Enables accessibility on AutocompleteEditView. void EnableAccessibility(); @@ -183,8 +182,6 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // the animation state. void UpdateInstantViewColors(); - bool CommitInstantSuggestion(); - GtkWidget* text_view() { return text_view_; } @@ -302,7 +299,7 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // Get the character indices of the current selection. This honors // direction, cp_max is the insertion point, and cp_min is the bound. - CharRange GetSelection(); + CharRange GetSelection() const; // Translate from character positions to iterators for the current buffer. void ItersFromCharRange(const CharRange& range, @@ -312,6 +309,12 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // Return the number of characers in the current buffer. int GetTextLength() const; + // Places the caret at the given position. This clears any selection. + void PlaceCaretAt(int pos); + + // Returns true if the caret is at the end of the content. + bool IsCaretAtEnd() const; + // Try to parse the current text as a URL and colorize the components. void EmphasizeURLComponents(); diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h index a671393..3ba5963 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.h @@ -84,6 +84,7 @@ class AutocompleteEditViewMac : public AutocompleteEditView, virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); virtual void SetInstantSuggestion(const string16& input); + virtual string16 GetInstantSuggestion() const; virtual int TextWidth() const; virtual bool IsImeComposing() const; @@ -104,8 +105,6 @@ class AutocompleteEditViewMac : public AutocompleteEditView, virtual void OnSetFocus(bool control_down); virtual void OnKillFocus(); - bool CommitSuggestText(); - // Helper for LocationBarViewMac. Optionally selects all in |field_|. void FocusLocation(bool select_all); @@ -160,6 +159,9 @@ class AutocompleteEditViewMac : public AutocompleteEditView, // Returns the non-suggest portion of |field_|'s string value. NSString* GetNonSuggestTextSubstring() const; + // Returns the suggest portion of |field_|'s string value. + NSString* GetSuggestTextSubstring() const; + // Pass the current content of |field_| to SetText(), maintaining // any selection. Named to be consistent with GTK and Windows, // though here we cannot really do the in-place operation they do. @@ -170,6 +172,16 @@ class AutocompleteEditViewMac : public AutocompleteEditView, void ApplyTextAttributes(const string16& display_text, NSMutableAttributedString* as); + // Return the number of UTF-16 units in the current buffer, excluding the + // suggested text. + NSUInteger GetTextLength() const; + + // Places the caret at the given position. This clears any selection. + void PlaceCaretAt(NSUInteger pos); + + // Returns true if the caret is at the end of the content. + bool IsCaretAtEnd() const; + scoped_ptr<AutocompleteEditModel> model_; scoped_ptr<AutocompletePopupViewMac> popup_view_; diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm index a003166..c2841f4 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_edit_view_mac.mm @@ -216,7 +216,7 @@ void AutocompleteEditViewMac::SaveStateToTab(TabContents* tab) { } else { // If we are not focussed, there is no selection. Manufacture // something reasonable in case it starts to matter in the future. - range = NSMakeRange(0, [[field_ stringValue] length]); + range = NSMakeRange(0, GetTextLength()); } AutocompleteEditViewMacState state(model_->GetStateForTabSwitch(), @@ -296,8 +296,7 @@ string16 AutocompleteEditViewMac::GetText() const { } bool AutocompleteEditViewMac::IsEditingOrEmpty() const { - return model_->user_input_in_progress() || - ([[field_ stringValue] length] == 0); + return model_->user_input_in_progress() || !GetTextLength(); } int AutocompleteEditViewMac::GetIcon() const { @@ -324,7 +323,6 @@ void AutocompleteEditViewMac::SetUserText(const string16& text, } NSRange AutocompleteEditViewMac::GetSelectedRange() const { - DCHECK([field_ currentEditor]); return [[field_ currentEditor] selectedRange]; } @@ -374,7 +372,7 @@ void AutocompleteEditViewMac::SetForcedQuery() { bool AutocompleteEditViewMac::IsSelectAll() { if (![field_ currentEditor]) return true; - const NSRange all_range = NSMakeRange(0, GetText().length()); + const NSRange all_range = NSMakeRange(0, GetTextLength()); return NSEqualRanges(all_range, GetSelectedRange()); } @@ -401,7 +399,7 @@ void AutocompleteEditViewMac::SelectAll(bool reversed) { // TODO(shess): Verify that we should be stealing focus at this // point. - SetSelectedRange(NSMakeRange(0, GetText().length())); + SetSelectedRange(NSMakeRange(0, GetTextLength())); } void AutocompleteEditViewMac::RevertAll() { @@ -422,16 +420,8 @@ void AutocompleteEditViewMac::UpdatePopup() { // * 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 - bool prevent_inline_autocomplete = IsImeComposing(); - NSTextView* editor = (NSTextView*)[field_ currentEditor]; - if (editor) { - if (NSMaxRange([editor selectedRange]) < - [[editor textStorage] length] - suggest_text_length_) - prevent_inline_autocomplete = true; - } - - model_->StartAutocomplete([editor selectedRange].length != 0, - prevent_inline_autocomplete); + model_->StartAutocomplete(GetSelectedRange().length != 0, + IsImeComposing() || !IsCaretAtEnd()); } void AutocompleteEditViewMac::ClosePopup() { @@ -444,19 +434,6 @@ void AutocompleteEditViewMac::ClosePopup() { void AutocompleteEditViewMac::SetFocus() { } -bool AutocompleteEditViewMac::CommitSuggestText() { - if (suggest_text_length_ == 0) - return false; - - string16 input_text(GetText()); - suggest_text_length_ = 0; - string16 text(GetText()); - // Call SetText() to force a redraw and move the cursor to the end. - SetText(text); - model()->FinalizeInstantQuery(input_text, text.substr(input_text.size())); - return true; -} - void AutocompleteEditViewMac::SetText(const string16& display_text) { // If we are setting the text directly, there cannot be any suggest text. suggest_text_length_ = 0; @@ -507,6 +484,16 @@ NSString* AutocompleteEditViewMac::GetNonSuggestTextSubstring() const { return text; } +NSString* AutocompleteEditViewMac::GetSuggestTextSubstring() const { + if (suggest_text_length_ == 0) + return nil; + + NSString* text = [field_ stringValue]; + NSUInteger length = [text length]; + DCHECK_LE(suggest_text_length_, length); + return [text substringFromIndex:(length - suggest_text_length_)]; +} + void AutocompleteEditViewMac::EmphasizeURLComponents() { NSTextView* editor = (NSTextView*)[field_ currentEditor]; // If the autocomplete text field is in editing mode, then we can just change @@ -723,6 +710,11 @@ void AutocompleteEditViewMac::SetInstantSuggestion( } } +string16 AutocompleteEditViewMac::GetInstantSuggestion() const { + return suggest_text_length_ ? + base::SysNSStringToUTF16(GetSuggestTextSubstring()) : string16(); +} + int AutocompleteEditViewMac::TextWidth() const { // Not used on mac. NOTREACHED(); @@ -785,12 +777,8 @@ bool AutocompleteEditViewMac::OnDoCommandBySelector(SEL cmd) { if (cmd == @selector(moveRight:)) { // Only commit suggested text if the cursor is all the way to the right and // there is no selection. - NSRange range = GetSelectedRange(); - if (range.length == 0 && - suggest_text_length_ > 0 && - (range.location + suggest_text_length_ == - [[field_ stringValue] length])) { - controller_->OnCommitSuggestedText(GetText()); + if (suggest_text_length_ > 0 && IsCaretAtEnd()) { + controller_->OnCommitSuggestedText(true); return true; } } @@ -815,7 +803,15 @@ bool AutocompleteEditViewMac::OnDoCommandBySelector(SEL cmd) { return model_->AcceptKeyword(); if (suggest_text_length_ > 0) { - controller_->OnCommitSuggestedText(GetText()); + controller_->OnCommitSuggestedText(true); + return true; + } + + if (!IsCaretAtEnd()) { + PlaceCaretAt(GetTextLength()); + // OnDidChange() will not be triggered when setting selected range in this + // method, so we need to call it explicitly. + OnDidChange(); return true; } @@ -1094,3 +1090,19 @@ NSFont* AutocompleteEditViewMac::GetFieldFont() { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont(); } + +NSUInteger AutocompleteEditViewMac::GetTextLength() const { + return ([field_ currentEditor] ? + [[[field_ currentEditor] string] length] : + [[field_ stringValue] length]) - suggest_text_length_; +} + +void AutocompleteEditViewMac::PlaceCaretAt(NSUInteger pos) { + DCHECK(pos <= GetTextLength()); + SetSelectedRange(NSMakeRange(pos, pos)); +} + +bool AutocompleteEditViewMac::IsCaretAtEnd() const { + const NSRange selection = GetSelectedRange(); + return selection.length == 0 && selection.location == GetTextLength(); +} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_views.cc b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc index 2b77099..5093873 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_views.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.cc @@ -197,10 +197,20 @@ bool AutocompleteEditViewViews::HandleAfterKeyEvent( event.GetKeyCode() == ui::VKEY_TAB && !event.IsShiftDown() && !event.IsControlDown()) { - if (model_->is_keyword_hint() && !model_->keyword().empty()) { - model_->AcceptKeyword(); - handled = true; + if (model_->is_keyword_hint()) { + handled = model_->AcceptKeyword(); } else { + string16::size_type start = 0; + string16::size_type end = 0; + size_t length = GetTextLength(); + GetSelectionBounds(&start, &end); + if (start != end || start < length) { + OnBeforePossibleChange(); + SelectRange(length, length); + OnAfterPossibleChange(); + handled = true; + } + // TODO(Oshima): handle instant } } @@ -527,10 +537,13 @@ CommandUpdater* AutocompleteEditViewViews::GetCommandUpdater() { return command_updater_; } -views::View* AutocompleteEditViewViews::AddToView(views::View* parent) { - parent->AddChildView(this); - AddChildView(textfield_); - return this; +void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input) { + NOTIMPLEMENTED(); +} + +string16 AutocompleteEditViewViews::GetInstantSuggestion() const { + NOTIMPLEMENTED(); + return string16(); } int AutocompleteEditViewViews::TextWidth() const { @@ -542,15 +555,10 @@ bool AutocompleteEditViewViews::IsImeComposing() const { return false; } -bool AutocompleteEditViewViews::CommitInstantSuggestion( - const string16& typed_text, - const string16& suggested_text) { - model_->FinalizeInstantQuery(typed_text, suggested_text); - return true; -} - -void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input) { - NOTIMPLEMENTED(); +views::View* AutocompleteEditViewViews::AddToView(views::View* parent) { + parent->AddChildView(this); + AddChildView(textfield_); + return this; } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_views.h b/chrome/browser/autocomplete/autocomplete_edit_view_views.h index a6ca9db..e347aa2 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_views.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_views.h @@ -111,12 +111,11 @@ class AutocompleteEditViewViews : public views::View, virtual bool OnAfterPossibleChange(); virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); - virtual views::View* AddToView(views::View* parent); + virtual void SetInstantSuggestion(const string16& input); + virtual string16 GetInstantSuggestion() const; virtual int TextWidth() const; virtual bool IsImeComposing() const; - virtual bool CommitInstantSuggestion(const string16& typed_text, - const string16& suggested_text); - virtual void SetInstantSuggestion(const string16& input); + virtual views::View* AddToView(views::View* parent); // Overridden from NotificationObserver: virtual void Observe(NotificationType type, diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 89d8f55..cca0d08 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -924,6 +924,12 @@ void AutocompleteEditViewWin::SetInstantSuggestion(const string16& suggestion) { NOTREACHED(); } +string16 AutocompleteEditViewWin::GetInstantSuggestion() const { + // On Windows, we shows the suggestion in LocationBarView. + NOTREACHED(); + return string16(); +} + int AutocompleteEditViewWin::TextWidth() const { return WidthNeededToDisplay(GetText()); } @@ -946,13 +952,6 @@ views::View* AutocompleteEditViewWin::AddToView(views::View* parent) { return host; } -bool AutocompleteEditViewWin::CommitInstantSuggestion( - const string16& typed_text, - const string16& suggested_text) { - model_->FinalizeInstantQuery(typed_text, suggested_text); - return true; -} - void AutocompleteEditViewWin::PasteAndGo(const string16& text) { if (CanPasteAndGo(text)) model_->PasteAndGo(); @@ -1848,7 +1847,7 @@ bool AutocompleteEditViewWin::OnKeyDownOnlyWritable(TCHAR key, GetSel(selection); return (selection.cpMin == selection.cpMax) && (selection.cpMin == GetTextLength()) && - controller_->OnCommitSuggestedText(GetText()); + controller_->OnCommitSuggestedText(true); } case VK_RETURN: @@ -1977,8 +1976,13 @@ bool AutocompleteEditViewWin::OnKeyDownOnlyWritable(TCHAR key, // Accept the keyword. ScopedFreeze freeze(this, GetTextObjectModel()); model_->AcceptKeyword(); + } else if (!IsCaretAtEnd()) { + ScopedFreeze freeze(this, GetTextObjectModel()); + OnBeforePossibleChange(); + PlaceCaretAt(GetTextLength()); + OnAfterPossibleChange(); } else { - controller_->OnCommitSuggestedText(GetText()); + controller_->OnCommitSuggestedText(true); } return true; } @@ -2568,3 +2572,10 @@ int AutocompleteEditViewWin::WidthNeededToDisplay( // PosFromChar(i) might return 0 when i is greater than 1. return font_.GetStringWidth(text) + GetHorizontalMargin(); } + +bool AutocompleteEditViewWin::IsCaretAtEnd() const { + long length = GetTextLength(); + CHARRANGE sel; + GetSelection(sel); + return sel.cpMin == sel.cpMax && sel.cpMin == length; +} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.h b/chrome/browser/autocomplete/autocomplete_edit_view_win.h index 1b81787..5e4efdb 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.h @@ -134,12 +134,11 @@ class AutocompleteEditViewWin virtual gfx::NativeView GetNativeView() const; virtual CommandUpdater* GetCommandUpdater(); virtual void SetInstantSuggestion(const string16& suggestion); + virtual string16 GetInstantSuggestion() const; virtual int TextWidth() const; virtual bool IsImeComposing() const; virtual views::View* AddToView(views::View* parent); - virtual bool CommitInstantSuggestion(const string16& typed_text, - const string16& suggested_text); int GetPopupMaxYCoordinate(); @@ -216,6 +215,9 @@ class AutocompleteEditViewWin virtual string16 GetLabelForCommandId(int command_id) const; virtual void ExecuteCommand(int command_id); + // Returns true if the caret is at the end of the content. + bool IsCaretAtEnd() const; + private: enum MouseButton { kLeft = 0, |