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

Side by Side Diff: chrome/browser/autocomplete/autocomplete_edit_view_mac.mm

Issue 5966006: Hitting Tab should always move cursor to end of omnibox text. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Mac build. Created 9 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/autocomplete/autocomplete_edit_view_mac.h" 5 #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h"
6 6
7 #include <Carbon/Carbon.h> // kVK_Return 7 #include <Carbon/Carbon.h> // kVK_Return
8 8
9 #include "app/mac/nsimage_cache.h" 9 #include "app/mac/nsimage_cache.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 DCHECK(tab); 209 DCHECK(tab);
210 210
211 const bool hasFocus = [field_ currentEditor] ? true : false; 211 const bool hasFocus = [field_ currentEditor] ? true : false;
212 212
213 NSRange range; 213 NSRange range;
214 if (hasFocus) { 214 if (hasFocus) {
215 range = GetSelectedRange(); 215 range = GetSelectedRange();
216 } else { 216 } else {
217 // If we are not focussed, there is no selection. Manufacture 217 // If we are not focussed, there is no selection. Manufacture
218 // something reasonable in case it starts to matter in the future. 218 // something reasonable in case it starts to matter in the future.
219 range = NSMakeRange(0, [[field_ stringValue] length]); 219 range = NSMakeRange(0, GetTextLength());
220 } 220 }
221 221
222 AutocompleteEditViewMacState state(model_->GetStateForTabSwitch(), 222 AutocompleteEditViewMacState state(model_->GetStateForTabSwitch(),
223 hasFocus, range); 223 hasFocus, range);
224 StoreStateToTab(tab, state); 224 StoreStateToTab(tab, state);
225 } 225 }
226 226
227 void AutocompleteEditViewMac::Update( 227 void AutocompleteEditViewMac::Update(
228 const TabContents* tab_for_state_restoring) { 228 const TabContents* tab_for_state_restoring) {
229 // TODO(shess): It seems like if the tab is non-NULL, then this code 229 // TODO(shess): It seems like if the tab is non-NULL, then this code
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 289
290 model_->OpenURL(url, disposition, transition, alternate_nav_url, 290 model_->OpenURL(url, disposition, transition, alternate_nav_url,
291 selected_line, keyword); 291 selected_line, keyword);
292 } 292 }
293 293
294 string16 AutocompleteEditViewMac::GetText() const { 294 string16 AutocompleteEditViewMac::GetText() const {
295 return base::SysNSStringToUTF16(GetNonSuggestTextSubstring()); 295 return base::SysNSStringToUTF16(GetNonSuggestTextSubstring());
296 } 296 }
297 297
298 bool AutocompleteEditViewMac::IsEditingOrEmpty() const { 298 bool AutocompleteEditViewMac::IsEditingOrEmpty() const {
299 return model_->user_input_in_progress() || 299 return model_->user_input_in_progress() || !GetTextLength();
300 ([[field_ stringValue] length] == 0);
301 } 300 }
302 301
303 int AutocompleteEditViewMac::GetIcon() const { 302 int AutocompleteEditViewMac::GetIcon() const {
304 return IsEditingOrEmpty() ? 303 return IsEditingOrEmpty() ?
305 AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) : 304 AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
306 toolbar_model_->GetIcon(); 305 toolbar_model_->GetIcon();
307 } 306 }
308 307
309 void AutocompleteEditViewMac::SetUserText(const string16& text) { 308 void AutocompleteEditViewMac::SetUserText(const string16& text) {
310 SetUserText(text, text, true); 309 SetUserText(text, text, true);
311 } 310 }
312 311
313 void AutocompleteEditViewMac::SetUserText(const string16& text, 312 void AutocompleteEditViewMac::SetUserText(const string16& text,
314 const string16& display_text, 313 const string16& display_text,
315 bool update_popup) { 314 bool update_popup) {
316 model_->SetUserText(text); 315 model_->SetUserText(text);
317 // TODO(shess): TODO below from gtk. 316 // TODO(shess): TODO below from gtk.
318 // TODO(deanm): something about selection / focus change here. 317 // TODO(deanm): something about selection / focus change here.
319 SetText(display_text); 318 SetText(display_text);
320 if (update_popup) { 319 if (update_popup) {
321 UpdatePopup(); 320 UpdatePopup();
322 } 321 }
323 controller_->OnChanged(); 322 controller_->OnChanged();
324 } 323 }
325 324
326 NSRange AutocompleteEditViewMac::GetSelectedRange() const { 325 NSRange AutocompleteEditViewMac::GetSelectedRange() const {
327 DCHECK([field_ currentEditor]);
328 return [[field_ currentEditor] selectedRange]; 326 return [[field_ currentEditor] selectedRange];
329 } 327 }
330 328
331 NSRange AutocompleteEditViewMac::GetMarkedRange() const { 329 NSRange AutocompleteEditViewMac::GetMarkedRange() const {
332 DCHECK([field_ currentEditor]); 330 DCHECK([field_ currentEditor]);
333 return [(NSTextView*)[field_ currentEditor] markedRange]; 331 return [(NSTextView*)[field_ currentEditor] markedRange];
334 } 332 }
335 333
336 void AutocompleteEditViewMac::SetSelectedRange(const NSRange range) { 334 void AutocompleteEditViewMac::SetSelectedRange(const NSRange range) {
337 // This can be called when we don't have focus. For instance, when 335 // This can be called when we don't have focus. For instance, when
(...skipping 29 matching lines...) Expand all
367 SetUserText(ASCIIToUTF16("?")); 365 SetUserText(ASCIIToUTF16("?"));
368 } else { 366 } else {
369 NSRange range = NSMakeRange(start + 1, current_text.size() - start - 1); 367 NSRange range = NSMakeRange(start + 1, current_text.size() - start - 1);
370 [[field_ currentEditor] setSelectedRange:range]; 368 [[field_ currentEditor] setSelectedRange:range];
371 } 369 }
372 } 370 }
373 371
374 bool AutocompleteEditViewMac::IsSelectAll() { 372 bool AutocompleteEditViewMac::IsSelectAll() {
375 if (![field_ currentEditor]) 373 if (![field_ currentEditor])
376 return true; 374 return true;
377 const NSRange all_range = NSMakeRange(0, GetText().length()); 375 const NSRange all_range = NSMakeRange(0, GetTextLength());
378 return NSEqualRanges(all_range, GetSelectedRange()); 376 return NSEqualRanges(all_range, GetSelectedRange());
379 } 377 }
380 378
381 bool AutocompleteEditViewMac::DeleteAtEndPressed() { 379 bool AutocompleteEditViewMac::DeleteAtEndPressed() {
382 return delete_at_end_pressed_; 380 return delete_at_end_pressed_;
383 } 381 }
384 382
385 void AutocompleteEditViewMac::GetSelectionBounds(string16::size_type* start, 383 void AutocompleteEditViewMac::GetSelectionBounds(string16::size_type* start,
386 string16::size_type* end) { 384 string16::size_type* end) {
387 if (![field_ currentEditor]) { 385 if (![field_ currentEditor]) {
388 *start = *end = 0; 386 *start = *end = 0;
389 return; 387 return;
390 } 388 }
391 389
392 const NSRange selected_range = GetSelectedRange(); 390 const NSRange selected_range = GetSelectedRange();
393 *start = static_cast<size_t>(selected_range.location); 391 *start = static_cast<size_t>(selected_range.location);
394 *end = static_cast<size_t>(NSMaxRange(selected_range)); 392 *end = static_cast<size_t>(NSMaxRange(selected_range));
395 } 393 }
396 394
397 void AutocompleteEditViewMac::SelectAll(bool reversed) { 395 void AutocompleteEditViewMac::SelectAll(bool reversed) {
398 // TODO(shess): Figure out what |reversed| implies. The gtk version 396 // TODO(shess): Figure out what |reversed| implies. The gtk version
399 // has it imply inverting the selection front to back, but I don't 397 // has it imply inverting the selection front to back, but I don't
400 // even know if that makes sense for Mac. 398 // even know if that makes sense for Mac.
401 399
402 // TODO(shess): Verify that we should be stealing focus at this 400 // TODO(shess): Verify that we should be stealing focus at this
403 // point. 401 // point.
404 SetSelectedRange(NSMakeRange(0, GetText().length())); 402 SetSelectedRange(NSMakeRange(0, GetTextLength()));
405 } 403 }
406 404
407 void AutocompleteEditViewMac::RevertAll() { 405 void AutocompleteEditViewMac::RevertAll() {
408 ClosePopup(); 406 ClosePopup();
409 model_->Revert(); 407 model_->Revert();
410 controller_->OnChanged(); 408 controller_->OnChanged();
411 [field_ clearUndoChain]; 409 [field_ clearUndoChain];
412 } 410 }
413 411
414 void AutocompleteEditViewMac::UpdatePopup() { 412 void AutocompleteEditViewMac::UpdatePopup() {
415 model_->SetInputInProgress(true); 413 model_->SetInputInProgress(true);
416 if (!model_->has_focus()) 414 if (!model_->has_focus())
417 return; 415 return;
418 416
419 // Comment copied from AutocompleteEditViewWin::UpdatePopup(): 417 // Comment copied from AutocompleteEditViewWin::UpdatePopup():
420 // Don't inline autocomplete when: 418 // Don't inline autocomplete when:
421 // * The user is deleting text 419 // * The user is deleting text
422 // * The caret/selection isn't at the end of the text 420 // * The caret/selection isn't at the end of the text
423 // * The user has just pasted in something that replaced all the text 421 // * The user has just pasted in something that replaced all the text
424 // * The user is trying to compose something in an IME 422 // * The user is trying to compose something in an IME
425 bool prevent_inline_autocomplete = IsImeComposing(); 423 model_->StartAutocomplete(GetSelectedRange().length != 0,
426 NSTextView* editor = (NSTextView*)[field_ currentEditor]; 424 IsImeComposing() || !IsCaretAtEnd());
427 if (editor) {
428 if (NSMaxRange([editor selectedRange]) <
429 [[editor textStorage] length] - suggest_text_length_)
430 prevent_inline_autocomplete = true;
431 }
432
433 model_->StartAutocomplete([editor selectedRange].length != 0,
434 prevent_inline_autocomplete);
435 } 425 }
436 426
437 void AutocompleteEditViewMac::ClosePopup() { 427 void AutocompleteEditViewMac::ClosePopup() {
438 if (popup_view_->GetModel()->IsOpen()) 428 if (popup_view_->GetModel()->IsOpen())
439 controller_->OnAutocompleteWillClosePopup(); 429 controller_->OnAutocompleteWillClosePopup();
440 430
441 popup_view_->GetModel()->StopAutocomplete(); 431 popup_view_->GetModel()->StopAutocomplete();
442 } 432 }
443 433
444 void AutocompleteEditViewMac::SetFocus() { 434 void AutocompleteEditViewMac::SetFocus() {
445 } 435 }
446 436
447 bool AutocompleteEditViewMac::CommitSuggestText() {
448 if (suggest_text_length_ == 0)
449 return false;
450
451 string16 input_text(GetText());
452 suggest_text_length_ = 0;
453 string16 text(GetText());
454 // Call SetText() to force a redraw and move the cursor to the end.
455 SetText(text);
456 model()->FinalizeInstantQuery(input_text, text.substr(input_text.size()));
457 return true;
458 }
459
460 void AutocompleteEditViewMac::SetText(const string16& display_text) { 437 void AutocompleteEditViewMac::SetText(const string16& display_text) {
461 // If we are setting the text directly, there cannot be any suggest text. 438 // If we are setting the text directly, there cannot be any suggest text.
462 suggest_text_length_ = 0; 439 suggest_text_length_ = 0;
463 SetTextInternal(display_text); 440 SetTextInternal(display_text);
464 } 441 }
465 442
466 void AutocompleteEditViewMac::SetTextInternal( 443 void AutocompleteEditViewMac::SetTextInternal(
467 const string16& display_text) { 444 const string16& display_text) {
468 NSString* ss = base::SysUTF16ToNSString(display_text); 445 NSString* ss = base::SysUTF16ToNSString(display_text);
469 NSMutableAttributedString* as = 446 NSMutableAttributedString* as =
(...skipping 30 matching lines...) Expand all
500 NSString* text = [field_ stringValue]; 477 NSString* text = [field_ stringValue];
501 if (suggest_text_length_ > 0) { 478 if (suggest_text_length_ > 0) {
502 NSUInteger length = [text length]; 479 NSUInteger length = [text length];
503 480
504 DCHECK_LE(suggest_text_length_, length); 481 DCHECK_LE(suggest_text_length_, length);
505 text = [text substringToIndex:(length - suggest_text_length_)]; 482 text = [text substringToIndex:(length - suggest_text_length_)];
506 } 483 }
507 return text; 484 return text;
508 } 485 }
509 486
487 NSString* AutocompleteEditViewMac::GetSuggestTextSubstring() const {
488 if (suggest_text_length_ == 0)
489 return nil;
490
491 NSString* text = [field_ stringValue];
492 NSUInteger length = [text length];
493 DCHECK_LE(suggest_text_length_, length);
494 return [text substringFromIndex:(length - suggest_text_length_)];
495 }
496
510 void AutocompleteEditViewMac::EmphasizeURLComponents() { 497 void AutocompleteEditViewMac::EmphasizeURLComponents() {
511 NSTextView* editor = (NSTextView*)[field_ currentEditor]; 498 NSTextView* editor = (NSTextView*)[field_ currentEditor];
512 // If the autocomplete text field is in editing mode, then we can just change 499 // If the autocomplete text field is in editing mode, then we can just change
513 // its attributes through its editor. Otherwise, we simply reset its content. 500 // its attributes through its editor. Otherwise, we simply reset its content.
514 if (editor) { 501 if (editor) {
515 NSTextStorage* storage = [editor textStorage]; 502 NSTextStorage* storage = [editor textStorage];
516 [storage beginEditing]; 503 [storage beginEditing];
517 504
518 // Clear the existing attributes from the text storage, then 505 // Clear the existing attributes from the text storage, then
519 // overlay the appropriate Omnibox attributes. 506 // overlay the appropriate Omnibox attributes.
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 if (needs_update) { 703 if (needs_update) {
717 NSRange current_range = GetSelectedRange(); 704 NSRange current_range = GetSelectedRange();
718 SetTextInternal(base::SysNSStringToUTF16(text)); 705 SetTextInternal(base::SysNSStringToUTF16(text));
719 if (NSMaxRange(current_range) <= [text length] - suggest_text_length_) 706 if (NSMaxRange(current_range) <= [text length] - suggest_text_length_)
720 SetSelectedRange(current_range); 707 SetSelectedRange(current_range);
721 else 708 else
722 SetSelectedRange(NSMakeRange([text length] - suggest_text_length_, 0)); 709 SetSelectedRange(NSMakeRange([text length] - suggest_text_length_, 0));
723 } 710 }
724 } 711 }
725 712
713 string16 AutocompleteEditViewMac::GetInstantSuggestion() const {
714 return suggest_text_length_ ?
715 base::SysNSStringToUTF16(GetSuggestTextSubstring()) : string16();
716 }
717
726 int AutocompleteEditViewMac::TextWidth() const { 718 int AutocompleteEditViewMac::TextWidth() const {
727 // Not used on mac. 719 // Not used on mac.
728 NOTREACHED(); 720 NOTREACHED();
729 return 0; 721 return 0;
730 } 722 }
731 723
732 bool AutocompleteEditViewMac::IsImeComposing() const { 724 bool AutocompleteEditViewMac::IsImeComposing() const {
733 return [(NSTextView*)[field_ currentEditor] hasMarkedText]; 725 return [(NSTextView*)[field_ currentEditor] hasMarkedText];
734 } 726 }
735 727
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 770
779 if (cmd == @selector(moveUp:)) { 771 if (cmd == @selector(moveUp:)) {
780 model_->OnUpOrDownKeyPressed(-1); 772 model_->OnUpOrDownKeyPressed(-1);
781 return true; 773 return true;
782 } 774 }
783 } 775 }
784 776
785 if (cmd == @selector(moveRight:)) { 777 if (cmd == @selector(moveRight:)) {
786 // Only commit suggested text if the cursor is all the way to the right and 778 // Only commit suggested text if the cursor is all the way to the right and
787 // there is no selection. 779 // there is no selection.
788 NSRange range = GetSelectedRange(); 780 if (suggest_text_length_ > 0 && IsCaretAtEnd()) {
789 if (range.length == 0 && 781 controller_->OnCommitSuggestedText(true);
790 suggest_text_length_ > 0 &&
791 (range.location + suggest_text_length_ ==
792 [[field_ stringValue] length])) {
793 controller_->OnCommitSuggestedText(GetText());
794 return true; 782 return true;
795 } 783 }
796 } 784 }
797 785
798 if (cmd == @selector(scrollPageDown:)) { 786 if (cmd == @selector(scrollPageDown:)) {
799 model_->OnUpOrDownKeyPressed(model_->result().size()); 787 model_->OnUpOrDownKeyPressed(model_->result().size());
800 return true; 788 return true;
801 } 789 }
802 790
803 if (cmd == @selector(scrollPageUp:)) { 791 if (cmd == @selector(scrollPageUp:)) {
804 model_->OnUpOrDownKeyPressed(-model_->result().size()); 792 model_->OnUpOrDownKeyPressed(-model_->result().size());
805 return true; 793 return true;
806 } 794 }
807 795
808 if (cmd == @selector(cancelOperation:)) { 796 if (cmd == @selector(cancelOperation:)) {
809 return model_->OnEscapeKeyPressed(); 797 return model_->OnEscapeKeyPressed();
810 } 798 }
811 799
812 if (cmd == @selector(insertTab:) || 800 if (cmd == @selector(insertTab:) ||
813 cmd == @selector(insertTabIgnoringFieldEditor:)) { 801 cmd == @selector(insertTabIgnoringFieldEditor:)) {
814 if (model_->is_keyword_hint()) 802 if (model_->is_keyword_hint())
815 return model_->AcceptKeyword(); 803 return model_->AcceptKeyword();
816 804
817 if (suggest_text_length_ > 0) { 805 if (suggest_text_length_ > 0) {
818 controller_->OnCommitSuggestedText(GetText()); 806 controller_->OnCommitSuggestedText(true);
819 return true; 807 return true;
820 } 808 }
821 809
810 if (!IsCaretAtEnd()) {
811 PlaceCaretAt(GetTextLength());
812 // OnDidChange() will not be triggered when setting selected range in this
813 // method, so we need to call it explicitly.
814 OnDidChange();
815 return true;
816 }
817
822 if (controller_->AcceptCurrentInstantPreview()) 818 if (controller_->AcceptCurrentInstantPreview())
823 return true; 819 return true;
824 } 820 }
825 821
826 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op 822 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op
827 // behavior with the proper WindowOpenDisposition. 823 // behavior with the proper WindowOpenDisposition.
828 NSEvent* event = [NSApp currentEvent]; 824 NSEvent* event = [NSApp currentEvent];
829 if (cmd == @selector(insertNewline:) || 825 if (cmd == @selector(insertNewline:) ||
830 (cmd == @selector(noop:) && [event keyCode] == kVK_Return)) { 826 (cmd == @selector(noop:) && [event keyCode] == kVK_Return)) {
831 WindowOpenDisposition disposition = 827 WindowOpenDisposition disposition =
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 } 1083 }
1088 1084
1089 return string16(); 1085 return string16();
1090 } 1086 }
1091 1087
1092 // static 1088 // static
1093 NSFont* AutocompleteEditViewMac::GetFieldFont() { 1089 NSFont* AutocompleteEditViewMac::GetFieldFont() {
1094 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1090 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
1095 return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont(); 1091 return rb.GetFont(ResourceBundle::BaseFont).GetNativeFont();
1096 } 1092 }
1093
1094 NSUInteger AutocompleteEditViewMac::GetTextLength() const {
1095 return ([field_ currentEditor] ?
1096 [[[field_ currentEditor] string] length] :
1097 [[field_ stringValue] length]) - suggest_text_length_;
1098 }
1099
1100 void AutocompleteEditViewMac::PlaceCaretAt(NSUInteger pos) {
1101 DCHECK(pos <= GetTextLength());
1102 SetSelectedRange(NSMakeRange(pos, pos));
1103 }
1104
1105 bool AutocompleteEditViewMac::IsCaretAtEnd() const {
1106 const NSRange selection = GetSelectedRange();
1107 return selection.length == 0 && selection.location == GetTextLength();
1108 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit_view_mac.h ('k') | chrome/browser/autocomplete/autocomplete_edit_view_views.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698