OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/property_bag.h" | 9 #include "base/property_bag.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 void OmniboxViewMac::SetUserText(const string16& text) { | 322 void OmniboxViewMac::SetUserText(const string16& text) { |
323 SetUserText(text, text, true); | 323 SetUserText(text, text, true); |
324 } | 324 } |
325 | 325 |
326 void OmniboxViewMac::SetUserText(const string16& text, | 326 void OmniboxViewMac::SetUserText(const string16& text, |
327 const string16& display_text, | 327 const string16& display_text, |
328 bool update_popup) { | 328 bool update_popup) { |
329 model_->SetUserText(text); | 329 model_->SetUserText(text); |
330 // TODO(shess): TODO below from gtk. | 330 // TODO(shess): TODO below from gtk. |
331 // TODO(deanm): something about selection / focus change here. | 331 // TODO(deanm): something about selection / focus change here. |
332 SetText(display_text); | 332 SetWindowTextAndCaretPos(display_text, display_text.length(), update_popup, |
333 if (update_popup) { | 333 true); |
334 UpdatePopup(); | |
335 } | |
336 model_->OnChanged(); | |
337 } | 334 } |
338 | 335 |
339 NSRange OmniboxViewMac::GetSelectedRange() const { | 336 NSRange OmniboxViewMac::GetSelectedRange() const { |
340 return [[field_ currentEditor] selectedRange]; | 337 return [[field_ currentEditor] selectedRange]; |
341 } | 338 } |
342 | 339 |
343 NSRange OmniboxViewMac::GetMarkedRange() const { | 340 NSRange OmniboxViewMac::GetMarkedRange() const { |
344 DCHECK([field_ currentEditor]); | 341 DCHECK([field_ currentEditor]); |
345 return [(NSTextView*)[field_ currentEditor] markedRange]; | 342 return [(NSTextView*)[field_ currentEditor] markedRange]; |
346 } | 343 } |
(...skipping 10 matching lines...) Expand all Loading... |
357 | 354 |
358 // TODO(shess): What if it didn't get first responder, and there is | 355 // TODO(shess): What if it didn't get first responder, and there is |
359 // no field editor? This will do nothing. Well, at least it won't | 356 // no field editor? This will do nothing. Well, at least it won't |
360 // crash. Think of something more productive to do, or prove that | 357 // crash. Think of something more productive to do, or prove that |
361 // it cannot occur and DCHECK appropriately. | 358 // it cannot occur and DCHECK appropriately. |
362 [[field_ currentEditor] setSelectedRange:range]; | 359 [[field_ currentEditor] setSelectedRange:range]; |
363 } | 360 } |
364 } | 361 } |
365 | 362 |
366 void OmniboxViewMac::SetWindowTextAndCaretPos(const string16& text, | 363 void OmniboxViewMac::SetWindowTextAndCaretPos(const string16& text, |
367 size_t caret_pos) { | 364 size_t caret_pos, |
| 365 bool update_popup, |
| 366 bool notify_text_changed) { |
368 DCHECK_LE(caret_pos, text.size()); | 367 DCHECK_LE(caret_pos, text.size()); |
369 SetTextAndSelectedRange(text, NSMakeRange(caret_pos, caret_pos)); | 368 SetTextAndSelectedRange(text, NSMakeRange(caret_pos, caret_pos)); |
| 369 |
| 370 if (update_popup) |
| 371 UpdatePopup(); |
| 372 |
| 373 if (notify_text_changed) |
| 374 TextChanged(); |
370 } | 375 } |
371 | 376 |
372 void OmniboxViewMac::SetForcedQuery() { | 377 void OmniboxViewMac::SetForcedQuery() { |
373 // We need to do this first, else |SetSelectedRange()| won't work. | 378 // We need to do this first, else |SetSelectedRange()| won't work. |
374 FocusLocation(true); | 379 FocusLocation(true); |
375 | 380 |
376 const string16 current_text(GetText()); | 381 const string16 current_text(GetText()); |
377 const size_t start = current_text.find_first_not_of(kWhitespaceUTF16); | 382 const size_t start = current_text.find_first_not_of(kWhitespaceUTF16); |
378 if (start == string16::npos || (current_text[start] != '?')) { | 383 if (start == string16::npos || (current_text[start] != '?')) { |
379 SetUserText(ASCIIToUTF16("?")); | 384 SetUserText(ASCIIToUTF16("?")); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 [storage setAttributes:[NSDictionary dictionary] | 530 [storage setAttributes:[NSDictionary dictionary] |
526 range:NSMakeRange(0, [storage length])]; | 531 range:NSMakeRange(0, [storage length])]; |
527 ApplyTextAttributes(GetText(), storage); | 532 ApplyTextAttributes(GetText(), storage); |
528 | 533 |
529 [storage endEditing]; | 534 [storage endEditing]; |
530 } else { | 535 } else { |
531 SetText(GetText()); | 536 SetText(GetText()); |
532 } | 537 } |
533 } | 538 } |
534 | 539 |
| 540 void OmniboxViewMac::TextChanged() { |
| 541 EmphasizeURLComponents(); |
| 542 model_->OnChanged(); |
| 543 } |
| 544 |
535 void OmniboxViewMac::ApplyTextAttributes(const string16& display_text, | 545 void OmniboxViewMac::ApplyTextAttributes(const string16& display_text, |
536 NSMutableAttributedString* as) { | 546 NSMutableAttributedString* as) { |
537 NSUInteger as_length = [as length]; | 547 NSUInteger as_length = [as length]; |
538 NSRange as_entire_string = NSMakeRange(0, as_length); | 548 NSRange as_entire_string = NSMakeRange(0, as_length); |
539 | 549 |
540 [as addAttribute:NSFontAttributeName value:GetFieldFont() | 550 [as addAttribute:NSFontAttributeName value:GetFieldFont() |
541 range:as_entire_string]; | 551 range:as_entire_string]; |
542 | 552 |
543 // A kinda hacky way to add breaking at periods. This is what Safari does. | 553 // A kinda hacky way to add breaking at periods. This is what Safari does. |
544 // This works for IDNs too, despite the "en_US". | 554 // This works for IDNs too, despite the "en_US". |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 range:ComponentToNSRange(scheme)]; | 609 range:ComponentToNSRange(scheme)]; |
600 } | 610 } |
601 } | 611 } |
602 | 612 |
603 void OmniboxViewMac::OnTemporaryTextMaybeChanged(const string16& display_text, | 613 void OmniboxViewMac::OnTemporaryTextMaybeChanged(const string16& display_text, |
604 bool save_original_selection) { | 614 bool save_original_selection) { |
605 if (save_original_selection) | 615 if (save_original_selection) |
606 saved_temporary_selection_ = GetSelectedRange(); | 616 saved_temporary_selection_ = GetSelectedRange(); |
607 | 617 |
608 suggest_text_length_ = 0; | 618 suggest_text_length_ = 0; |
609 SetWindowTextAndCaretPos(display_text, display_text.size()); | 619 SetWindowTextAndCaretPos(display_text, display_text.size(), false, false); |
610 model_->OnChanged(); | 620 model_->OnChanged(); |
611 [field_ clearUndoChain]; | 621 [field_ clearUndoChain]; |
612 } | 622 } |
613 | 623 |
614 void OmniboxViewMac::OnStartingIME() { | 624 void OmniboxViewMac::OnStartingIME() { |
615 // Reset the suggest text just before starting an IME composition session, | 625 // Reset the suggest text just before starting an IME composition session, |
616 // otherwise the IME composition may be interrupted when the suggest text | 626 // otherwise the IME composition may be interrupted when the suggest text |
617 // gets reset by the IME composition change. | 627 // gets reset by the IME composition change. |
618 SetInstantSuggestion(string16(), false); | 628 SetInstantSuggestion(string16(), false); |
619 } | 629 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 !IsImeComposing()); | 701 !IsImeComposing()); |
692 | 702 |
693 if (delete_was_pressed_ && at_end_of_edit) | 703 if (delete_was_pressed_ && at_end_of_edit) |
694 delete_at_end_pressed_ = true; | 704 delete_at_end_pressed_ = true; |
695 | 705 |
696 // Restyle in case the user changed something. | 706 // Restyle in case the user changed something. |
697 // TODO(shess): I believe there are multiple-redraw cases, here. | 707 // TODO(shess): I believe there are multiple-redraw cases, here. |
698 // Linux watches for something_changed && text_differs, but that | 708 // Linux watches for something_changed && text_differs, but that |
699 // fails for us in case you copy the URL and paste the identical URL | 709 // fails for us in case you copy the URL and paste the identical URL |
700 // back (we'll lose the styling). | 710 // back (we'll lose the styling). |
701 EmphasizeURLComponents(); | 711 TextChanged(); |
702 model_->OnChanged(); | |
703 | 712 |
704 delete_was_pressed_ = false; | 713 delete_was_pressed_ = false; |
705 | 714 |
706 return something_changed; | 715 return something_changed; |
707 } | 716 } |
708 | 717 |
709 gfx::NativeView OmniboxViewMac::GetNativeView() const { | 718 gfx::NativeView OmniboxViewMac::GetNativeView() const { |
710 return field_; | 719 return field_; |
711 } | 720 } |
712 | 721 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 cmd != @selector(insertTabIgnoringFieldEditor:)) { | 795 cmd != @selector(insertTabIgnoringFieldEditor:)) { |
787 // Reset the suggest text for any change other than key right or tab. | 796 // Reset the suggest text for any change other than key right or tab. |
788 // TODO(rohitrao): This is here to prevent complications when editing text. | 797 // TODO(rohitrao): This is here to prevent complications when editing text. |
789 // See if this can be removed. | 798 // See if this can be removed. |
790 SetInstantSuggestion(string16(), false); | 799 SetInstantSuggestion(string16(), false); |
791 } | 800 } |
792 | 801 |
793 if (cmd == @selector(deleteForward:)) | 802 if (cmd == @selector(deleteForward:)) |
794 delete_was_pressed_ = true; | 803 delete_was_pressed_ = true; |
795 | 804 |
796 // Don't intercept up/down-arrow if the popup isn't open. | 805 // Don't intercept up/down-arrow or backtab if the popup isn't open. |
797 if (popup_view_->IsOpen()) { | 806 if (popup_view_->IsOpen()) { |
798 if (cmd == @selector(moveDown:)) { | 807 if (cmd == @selector(moveDown:)) { |
799 model_->OnUpOrDownKeyPressed(1); | 808 model_->OnUpOrDownKeyPressed(1); |
800 return true; | 809 return true; |
801 } | 810 } |
802 | 811 |
803 if (cmd == @selector(moveUp:)) { | 812 if (cmd == @selector(moveUp:)) { |
804 model_->OnUpOrDownKeyPressed(-1); | 813 model_->OnUpOrDownKeyPressed(-1); |
805 return true; | 814 return true; |
806 } | 815 } |
| 816 |
| 817 if (cmd == @selector(insertBacktab:)) { |
| 818 if (model_->popup_model()->selected_line_state() == |
| 819 AutocompletePopupModel::KEYWORD) { |
| 820 model_->ClearKeyword(GetText()); |
| 821 return true; |
| 822 } |
| 823 } |
807 } | 824 } |
808 | 825 |
809 if (cmd == @selector(moveRight:)) { | 826 if (cmd == @selector(moveRight:)) { |
810 // Only commit suggested text if the cursor is all the way to the right and | 827 // Only commit suggested text if the cursor is all the way to the right and |
811 // there is no selection. | 828 // there is no selection. |
812 if (suggest_text_length_ > 0 && IsCaretAtEnd()) { | 829 if (suggest_text_length_ > 0 && IsCaretAtEnd()) { |
813 model_->CommitSuggestedText(true); | 830 model_->CommitSuggestedText(true); |
814 return true; | 831 return true; |
815 } | 832 } |
816 } | 833 } |
817 | 834 |
818 if (cmd == @selector(scrollPageDown:)) { | 835 if (cmd == @selector(scrollPageDown:)) { |
819 model_->OnUpOrDownKeyPressed(model_->result().size()); | 836 model_->OnUpOrDownKeyPressed(model_->result().size()); |
820 return true; | 837 return true; |
821 } | 838 } |
822 | 839 |
823 if (cmd == @selector(scrollPageUp:)) { | 840 if (cmd == @selector(scrollPageUp:)) { |
824 model_->OnUpOrDownKeyPressed(-model_->result().size()); | 841 model_->OnUpOrDownKeyPressed(-model_->result().size()); |
825 return true; | 842 return true; |
826 } | 843 } |
827 | 844 |
828 if (cmd == @selector(cancelOperation:)) { | 845 if (cmd == @selector(cancelOperation:)) { |
829 return model_->OnEscapeKeyPressed(); | 846 return model_->OnEscapeKeyPressed(); |
830 } | 847 } |
831 | 848 |
832 if (cmd == @selector(insertTab:) || | 849 if (cmd == @selector(insertTab:) || |
833 cmd == @selector(insertTabIgnoringFieldEditor:)) { | 850 cmd == @selector(insertTabIgnoringFieldEditor:)) { |
834 if (model_->is_keyword_hint()) | 851 if (model_->is_keyword_hint()) |
835 return model_->AcceptKeyword(); | 852 return model_->AcceptKeyword(); |
836 | |
837 if (suggest_text_length_ > 0) { | |
838 model_->CommitSuggestedText(true); | |
839 return true; | |
840 } | |
841 | |
842 if (!IsCaretAtEnd()) { | |
843 PlaceCaretAt(GetTextLength()); | |
844 // OnDidChange() will not be triggered when setting selected range in this | |
845 // method, so we need to call it explicitly. | |
846 OnDidChange(); | |
847 return true; | |
848 } | |
849 | |
850 if (model_->AcceptCurrentInstantPreview()) | |
851 return true; | |
852 } | 853 } |
853 | 854 |
854 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op | 855 // |-noop:| is sent when the user presses Cmd+Return. Override the no-op |
855 // behavior with the proper WindowOpenDisposition. | 856 // behavior with the proper WindowOpenDisposition. |
856 NSEvent* event = [NSApp currentEvent]; | 857 NSEvent* event = [NSApp currentEvent]; |
857 if (cmd == @selector(insertNewline:) || | 858 if (cmd == @selector(insertNewline:) || |
858 (cmd == @selector(noop:) && | 859 (cmd == @selector(noop:) && |
859 ([event type] == NSKeyDown || [event type] == NSKeyUp) && | 860 ([event type] == NSKeyDown || [event type] == NSKeyUp) && |
860 [event keyCode] == kVK_Return)) { | 861 [event keyCode] == kVK_Return)) { |
861 WindowOpenDisposition disposition = | 862 WindowOpenDisposition disposition = |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 | 1126 |
1126 void OmniboxViewMac::PlaceCaretAt(NSUInteger pos) { | 1127 void OmniboxViewMac::PlaceCaretAt(NSUInteger pos) { |
1127 DCHECK(pos <= GetTextLength()); | 1128 DCHECK(pos <= GetTextLength()); |
1128 SetSelectedRange(NSMakeRange(pos, pos)); | 1129 SetSelectedRange(NSMakeRange(pos, pos)); |
1129 } | 1130 } |
1130 | 1131 |
1131 bool OmniboxViewMac::IsCaretAtEnd() const { | 1132 bool OmniboxViewMac::IsCaretAtEnd() const { |
1132 const NSRange selection = GetSelectedRange(); | 1133 const NSRange selection = GetSelectedRange(); |
1133 return selection.length == 0 && selection.location == GetTextLength(); | 1134 return selection.length == 0 && selection.location == GetTextLength(); |
1134 } | 1135 } |
OLD | NEW |