Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm

Issue 1855423003: Interpret '?' and Ctrl-K or Ctrl-E as putting omnibox in keyword search mode for Default Search Pro… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix bug in OmniboxView::GetStateChanges Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" 5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
6 6
7 #include <Carbon/Carbon.h> // kVK_Return 7 #include <Carbon/Carbon.h> // kVK_Return
8 8
9 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 Profile* profile, 200 Profile* profile,
201 CommandUpdater* command_updater, 201 CommandUpdater* command_updater,
202 AutocompleteTextField* field) 202 AutocompleteTextField* field)
203 : OmniboxView( 203 : OmniboxView(
204 controller, 204 controller,
205 base::WrapUnique(new ChromeOmniboxClient(controller, profile))), 205 base::WrapUnique(new ChromeOmniboxClient(controller, profile))),
206 profile_(profile), 206 profile_(profile),
207 popup_view_(new OmniboxPopupViewMac(this, model(), field)), 207 popup_view_(new OmniboxPopupViewMac(this, model(), field)),
208 field_(field), 208 field_(field),
209 saved_temporary_selection_(NSMakeRange(0, 0)), 209 saved_temporary_selection_(NSMakeRange(0, 0)),
210 selection_before_change_(NSMakeRange(0, 0)),
211 marked_range_before_change_(NSMakeRange(0, 0)), 210 marked_range_before_change_(NSMakeRange(0, 0)),
212 delete_was_pressed_(false), 211 delete_was_pressed_(false),
213 delete_at_end_pressed_(false), 212 delete_at_end_pressed_(false),
214 in_coalesced_update_block_(false), 213 in_coalesced_update_block_(false),
215 do_coalesced_text_update_(false), 214 do_coalesced_text_update_(false),
216 do_coalesced_range_update_(false) { 215 do_coalesced_range_update_(false) {
217 [field_ setObserver:this]; 216 [field_ setObserver:this];
218 217
219 // Needed so that editing doesn't lose the styling. 218 // Needed so that editing doesn't lose the styling.
220 [field_ setAllowsEditingTextAttributes:YES]; 219 [field_ setAllowsEditingTextAttributes:YES];
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 DCHECK_LE(caret_pos, text.size()); 373 DCHECK_LE(caret_pos, text.size());
375 SetTextAndSelectedRange(text, NSMakeRange(caret_pos, 0)); 374 SetTextAndSelectedRange(text, NSMakeRange(caret_pos, 0));
376 375
377 if (update_popup) 376 if (update_popup)
378 UpdatePopup(); 377 UpdatePopup();
379 378
380 if (notify_text_changed) 379 if (notify_text_changed)
381 TextChanged(); 380 TextChanged();
382 } 381 }
383 382
384 void OmniboxViewMac::SetForcedQuery() { 383 void OmniboxViewMac::EnterKeywordModeForDefaultSearchProvider() {
385 // We need to do this first, else |SetSelectedRange()| won't work. 384 // We need to do this first, else |SetSelectedRange()| won't work.
386 FocusLocation(true); 385 FocusLocation(true);
387 386
388 const base::string16 current_text(GetText()); 387 // Transition the user into keyword mode using their default search provider.
389 const size_t start = current_text.find_first_not_of(base::kWhitespaceUTF16); 388 // Select their query if they typed one.
390 if (start == base::string16::npos || (current_text[start] != '?')) { 389 model()->EnterKeywordModeForDefaultSearchProvider(
391 SetUserText(base::ASCIIToUTF16("?")); 390 KeywordModeEntryMethod::KEYBOARD_SHORTCUT);
392 } else { 391 SelectAll(false);
393 NSRange range = NSMakeRange(start + 1, current_text.size() - start - 1);
394 [[field_ currentEditor] setSelectedRange:range];
395 }
396 } 392 }
397 393
398 bool OmniboxViewMac::IsSelectAll() const { 394 bool OmniboxViewMac::IsSelectAll() const {
399 if (![field_ currentEditor]) 395 if (![field_ currentEditor])
400 return true; 396 return true;
401 const NSRange all_range = NSMakeRange(0, GetTextLength()); 397 const NSRange all_range = NSMakeRange(0, GetTextLength());
402 return NSEqualRanges(all_range, GetSelectedRange()); 398 return NSEqualRanges(all_range, GetSelectedRange());
403 } 399 }
404 400
405 bool OmniboxViewMac::DeleteAtEndPressed() { 401 bool OmniboxViewMac::DeleteAtEndPressed() {
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 } 674 }
679 675
680 bool OmniboxViewMac::IsFirstResponder() const { 676 bool OmniboxViewMac::IsFirstResponder() const {
681 return [field_ currentEditor] != nil ? true : false; 677 return [field_ currentEditor] != nil ? true : false;
682 } 678 }
683 679
684 void OmniboxViewMac::OnBeforePossibleChange() { 680 void OmniboxViewMac::OnBeforePossibleChange() {
685 // We should only arrive here when the field is focused. 681 // We should only arrive here when the field is focused.
686 DCHECK(IsFirstResponder()); 682 DCHECK(IsFirstResponder());
687 683
688 selection_before_change_ = GetSelectedRange(); 684 GetState(&state_before_change_);
689 text_before_change_ = GetText();
690 marked_range_before_change_ = GetMarkedRange(); 685 marked_range_before_change_ = GetMarkedRange();
691 } 686 }
692 687
693 bool OmniboxViewMac::OnAfterPossibleChange(bool allow_keyword_ui_change) { 688 bool OmniboxViewMac::OnAfterPossibleChange(bool allow_keyword_ui_change) {
694 // We should only arrive here when the field is focused. 689 // We should only arrive here when the field is focused.
695 DCHECK(IsFirstResponder()); 690 DCHECK(IsFirstResponder());
696 691
697 const NSRange new_selection(GetSelectedRange()); 692 State new_state;
698 const base::string16 new_text(GetText()); 693 GetState(&new_state);
699 const size_t length = new_text.length(); 694 OmniboxViewStateChanges state_changes =
695 GetStateChanges(state_before_change_, new_state);
700 696
701 const bool selection_differs = 697 const bool at_end_of_edit = (new_state.text.length() == new_state.sel_end);
702 (new_selection.length || selection_before_change_.length) &&
703 !NSEqualRanges(new_selection, selection_before_change_);
704 const bool at_end_of_edit = (length == new_selection.location);
705 const bool text_differs = (new_text != text_before_change_) ||
706 !NSEqualRanges(marked_range_before_change_, GetMarkedRange());
707
708 // When the user has deleted text, we don't allow inline
709 // autocomplete. This is assumed if the text has gotten shorter AND
710 // the selection has shifted towards the front of the text. During
711 // normal typing the text will almost always be shorter (as the new
712 // input replaces the autocomplete suggestion), but in that case the
713 // selection point will have moved towards the end of the text.
714 // TODO(shess): In our implementation, we can catch -deleteBackward:
715 // and other methods to provide positive knowledge that a delete
716 // occurred, rather than intuiting it from context. Consider whether
717 // that would be a stronger approach.
718 const bool just_deleted_text =
719 (length < text_before_change_.length() &&
720 new_selection.location <= selection_before_change_.location);
721 698
722 delete_at_end_pressed_ = false; 699 delete_at_end_pressed_ = false;
723 700
724 const bool something_changed = model()->OnAfterPossibleChange( 701 const bool something_changed = model()->OnAfterPossibleChange(
725 text_before_change_, new_text, new_selection.location, 702 state_changes, allow_keyword_ui_change && !IsImeComposing());
726 NSMaxRange(new_selection), selection_differs, text_differs,
727 just_deleted_text, allow_keyword_ui_change && !IsImeComposing());
728 703
729 if (delete_was_pressed_ && at_end_of_edit) 704 if (delete_was_pressed_ && at_end_of_edit)
730 delete_at_end_pressed_ = true; 705 delete_at_end_pressed_ = true;
731 706
732 // Restyle in case the user changed something. 707 // Restyle in case the user changed something.
733 // TODO(shess): I believe there are multiple-redraw cases, here. 708 // TODO(shess): I believe there are multiple-redraw cases, here.
734 // Linux watches for something_changed && text_differs, but that 709 // Linux watches for something_changed && text_differs, but that
735 // fails for us in case you copy the URL and paste the identical URL 710 // fails for us in case you copy the URL and paste the identical URL
736 // back (we'll lose the styling). 711 // back (we'll lose the styling).
737 TextChanged(); 712 TextChanged();
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 return true; 840 return true;
866 } 841 }
867 842
868 if (cmd == @selector(cancelOperation:)) { 843 if (cmd == @selector(cancelOperation:)) {
869 return model()->OnEscapeKeyPressed(); 844 return model()->OnEscapeKeyPressed();
870 } 845 }
871 846
872 if ((cmd == @selector(insertTab:) || 847 if ((cmd == @selector(insertTab:) ||
873 cmd == @selector(insertTabIgnoringFieldEditor:)) && 848 cmd == @selector(insertTabIgnoringFieldEditor:)) &&
874 model()->is_keyword_hint()) { 849 model()->is_keyword_hint()) {
875 return model()->AcceptKeyword(ENTERED_KEYWORD_MODE_VIA_TAB); 850 return model()->AcceptKeyword(KeywordModeEntryMethod::TAB);
876 } 851 }
877 852
878 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op 853 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op
879 // behavior with the proper WindowOpenDisposition. 854 // behavior with the proper WindowOpenDisposition.
880 NSEvent* event = [NSApp currentEvent]; 855 NSEvent* event = [NSApp currentEvent];
881 if (cmd == @selector(insertNewline:) || 856 if (cmd == @selector(insertNewline:) ||
882 (cmd == @selector(noop:) && 857 (cmd == @selector(noop:) &&
883 ([event type] == NSKeyDown || [event type] == NSKeyUp) && 858 ([event type] == NSKeyDown || [event type] == NSKeyUp) &&
884 [event keyCode] == kVK_Return)) { 859 [event keyCode] == kVK_Return)) {
885 WindowOpenDisposition disposition = 860 WindowOpenDisposition disposition =
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 // from the Chrome-specific code. 993 // from the Chrome-specific code.
1019 NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]); 994 NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]);
1020 const NSRange selectedRange = GetSelectedRange(); 995 const NSRange selectedRange = GetSelectedRange();
1021 if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) { 996 if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) {
1022 // Record this paste, so we can do different behavior. 997 // Record this paste, so we can do different behavior.
1023 model()->OnPaste(); 998 model()->OnPaste();
1024 999
1025 // Force a Paste operation to trigger the text_changed code in 1000 // Force a Paste operation to trigger the text_changed code in
1026 // OnAfterPossibleChange(), even if identical contents are pasted 1001 // OnAfterPossibleChange(), even if identical contents are pasted
1027 // into the text box. 1002 // into the text box.
1028 text_before_change_.clear(); 1003 state_before_change_.text.clear();
1029 1004
1030 [editor replaceCharactersInRange:selectedRange withString:s]; 1005 [editor replaceCharactersInRange:selectedRange withString:s];
1031 [editor didChangeText]; 1006 [editor didChangeText];
1032 } 1007 }
1033 } 1008 }
1034 1009
1035 // TODO(dominich): Move to OmniboxView base class? Currently this is defined on 1010 // TODO(dominich): Move to OmniboxView base class? Currently this is defined on
1036 // the AutocompleteTextFieldObserver but the logic is shared between all 1011 // the AutocompleteTextFieldObserver but the logic is shared between all
1037 // platforms. Some refactor might be necessary to simplify this. Or at least 1012 // platforms. Some refactor might be necessary to simplify this. Or at least
1038 // this method could call the OmniboxView version. 1013 // this method could call the OmniboxView version.
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 display_text); 1136 display_text);
1162 NSDictionary* notification_info = @{ 1137 NSDictionary* notification_info = @{
1163 NSAccessibilityAnnouncementKey : announcement, 1138 NSAccessibilityAnnouncementKey : announcement,
1164 NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh) 1139 NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh)
1165 }; 1140 };
1166 NSAccessibilityPostNotificationWithUserInfo( 1141 NSAccessibilityPostNotificationWithUserInfo(
1167 [field_ window], 1142 [field_ window],
1168 NSAccessibilityAnnouncementRequestedNotification, 1143 NSAccessibilityAnnouncementRequestedNotification,
1169 notification_info); 1144 notification_info);
1170 } 1145 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698