OLD | NEW |
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/gtk/omnibox/omnibox_view_gtk.h" | 5 #include "chrome/browser/ui/gtk/omnibox/omnibox_view_gtk.h" |
6 | 6 |
7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" | 33 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h" |
34 #include "chrome/browser/ui/search/search.h" | 34 #include "chrome/browser/ui/search/search.h" |
35 #include "chrome/browser/ui/toolbar/toolbar_model.h" | 35 #include "chrome/browser/ui/toolbar/toolbar_model.h" |
36 #include "chrome/common/chrome_notification_types.h" | 36 #include "chrome/common/chrome_notification_types.h" |
37 #include "content/public/browser/notification_source.h" | 37 #include "content/public/browser/notification_source.h" |
38 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
39 #include "googleurl/src/gurl.h" | 39 #include "googleurl/src/gurl.h" |
40 #include "grit/generated_resources.h" | 40 #include "grit/generated_resources.h" |
41 #include "net/base/escape.h" | 41 #include "net/base/escape.h" |
42 #include "third_party/undoview/undo_view.h" | 42 #include "third_party/undoview/undo_view.h" |
43 #include "ui/base/animation/multi_animation.h" | |
44 #include "ui/base/dragdrop/drag_drop_types.h" | 43 #include "ui/base/dragdrop/drag_drop_types.h" |
45 #include "ui/base/dragdrop/gtk_dnd_util.h" | 44 #include "ui/base/dragdrop/gtk_dnd_util.h" |
46 #include "ui/base/gtk/gtk_compat.h" | 45 #include "ui/base/gtk/gtk_compat.h" |
47 #include "ui/base/gtk/gtk_hig_constants.h" | 46 #include "ui/base/gtk/gtk_hig_constants.h" |
48 #include "ui/base/gtk/menu_label_accelerator_util.h" | 47 #include "ui/base/gtk/menu_label_accelerator_util.h" |
49 #include "ui/base/l10n/l10n_util.h" | 48 #include "ui/base/l10n/l10n_util.h" |
50 #include "ui/base/resource/resource_bundle.h" | 49 #include "ui/base/resource/resource_bundle.h" |
51 #include "ui/gfx/color_utils.h" | 50 #include "ui/gfx/color_utils.h" |
52 #include "ui/gfx/font.h" | 51 #include "ui/gfx/font.h" |
53 #include "ui/gfx/skia_utils_gtk.h" | 52 #include "ui/gfx/skia_utils_gtk.h" |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 instant_mark_ = | 396 instant_mark_ = |
398 gtk_text_buffer_create_mark(text_buffer_, NULL, &start_iter, FALSE); | 397 gtk_text_buffer_create_mark(text_buffer_, NULL, &start_iter, FALSE); |
399 | 398 |
400 // Hooking up this handler after setting up above hacks for Instant view, so | 399 // Hooking up this handler after setting up above hacks for Instant view, so |
401 // that we won't filter out the special ZWP mark itself. | 400 // that we won't filter out the special ZWP mark itself. |
402 g_signal_connect(text_buffer_, "insert-text", | 401 g_signal_connect(text_buffer_, "insert-text", |
403 G_CALLBACK(&HandleInsertTextThunk), this); | 402 G_CALLBACK(&HandleInsertTextThunk), this); |
404 | 403 |
405 AdjustVerticalAlignmentOfInstantView(); | 404 AdjustVerticalAlignmentOfInstantView(); |
406 | 405 |
407 ui::MultiAnimation::Parts parts; | |
408 parts.push_back(ui::MultiAnimation::Part( | |
409 InstantController::kInlineAutocompletePauseTimeMS, ui::Tween::ZERO)); | |
410 parts.push_back(ui::MultiAnimation::Part( | |
411 InstantController::kInlineAutocompleteFadeInTimeMS, ui::Tween::EASE_IN)); | |
412 instant_animation_.reset(new ui::MultiAnimation(parts)); | |
413 instant_animation_->set_continuous(false); | |
414 | |
415 registrar_.Add(this, | 406 registrar_.Add(this, |
416 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | 407 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
417 content::Source<ThemeService>(theme_service_)); | 408 content::Source<ThemeService>(theme_service_)); |
418 theme_service_->InitThemesFor(this); | 409 theme_service_->InitThemesFor(this); |
419 | 410 |
420 ViewIDUtil::SetID(GetNativeView(), VIEW_ID_AUTOCOMPLETE); | 411 ViewIDUtil::SetID(GetNativeView(), VIEW_ID_AUTOCOMPLETE); |
421 } | 412 } |
422 | 413 |
423 void OmniboxViewGtk::HandleHierarchyChanged(GtkWidget* sender, | 414 void OmniboxViewGtk::HandleHierarchyChanged(GtkWidget* sender, |
424 GtkWidget* old_toplevel) { | 415 GtkWidget* old_toplevel) { |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 gfx::NativeView OmniboxViewGtk::GetNativeView() const { | 696 gfx::NativeView OmniboxViewGtk::GetNativeView() const { |
706 return alignment_.get(); | 697 return alignment_.get(); |
707 } | 698 } |
708 | 699 |
709 gfx::NativeView OmniboxViewGtk::GetRelativeWindowForPopup() const { | 700 gfx::NativeView OmniboxViewGtk::GetRelativeWindowForPopup() const { |
710 GtkWidget* toplevel = gtk_widget_get_toplevel(GetNativeView()); | 701 GtkWidget* toplevel = gtk_widget_get_toplevel(GetNativeView()); |
711 DCHECK(gtk_widget_is_toplevel(toplevel)); | 702 DCHECK(gtk_widget_is_toplevel(toplevel)); |
712 return toplevel; | 703 return toplevel; |
713 } | 704 } |
714 | 705 |
715 void OmniboxViewGtk::SetInstantSuggestion(const string16& suggestion, | 706 void OmniboxViewGtk::SetInstantSuggestion(const string16& suggestion) { |
716 bool animate_to_complete) { | |
717 std::string suggestion_utf8 = UTF16ToUTF8(suggestion); | 707 std::string suggestion_utf8 = UTF16ToUTF8(suggestion); |
718 | 708 |
719 gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str()); | 709 gtk_label_set_text(GTK_LABEL(instant_view_), suggestion_utf8.c_str()); |
720 | 710 |
721 StopAnimation(); | |
722 | |
723 if (suggestion.empty()) { | 711 if (suggestion.empty()) { |
724 gtk_widget_hide(instant_view_); | 712 gtk_widget_hide(instant_view_); |
725 return; | 713 return; |
726 } | 714 } |
727 bool animate = animate_to_complete; | |
728 if (supports_pre_edit_) | |
729 animate = animate && pre_edit_.empty(); | |
730 if (animate) { | |
731 instant_animation_->set_delegate(this); | |
732 instant_animation_->Start(); | |
733 } | |
734 | 715 |
735 gtk_widget_show(instant_view_); | 716 gtk_widget_show(instant_view_); |
736 AdjustVerticalAlignmentOfInstantView(); | 717 AdjustVerticalAlignmentOfInstantView(); |
737 UpdateInstantViewColors(); | 718 UpdateInstantViewColors(); |
738 } | 719 } |
739 | 720 |
740 string16 OmniboxViewGtk::GetInstantSuggestion() const { | 721 string16 OmniboxViewGtk::GetInstantSuggestion() const { |
741 const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); | 722 const gchar* suggestion = gtk_label_get_text(GTK_LABEL(instant_view_)); |
742 return suggestion ? UTF8ToUTF16(suggestion) : string16(); | 723 return suggestion ? UTF8ToUTF16(suggestion) : string16(); |
743 } | 724 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 } | 773 } |
793 | 774 |
794 void OmniboxViewGtk::Observe(int type, | 775 void OmniboxViewGtk::Observe(int type, |
795 const content::NotificationSource& source, | 776 const content::NotificationSource& source, |
796 const content::NotificationDetails& details) { | 777 const content::NotificationDetails& details) { |
797 DCHECK(type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED); | 778 DCHECK(type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED); |
798 | 779 |
799 SetBaseColor(); | 780 SetBaseColor(); |
800 } | 781 } |
801 | 782 |
802 void OmniboxViewGtk::AnimationEnded(const ui::Animation* animation) { | |
803 model()->CommitSuggestedText(false); | |
804 } | |
805 | |
806 void OmniboxViewGtk::AnimationProgressed(const ui::Animation* animation) { | |
807 UpdateInstantViewColors(); | |
808 } | |
809 | |
810 void OmniboxViewGtk::AnimationCanceled(const ui::Animation* animation) { | |
811 UpdateInstantViewColors(); | |
812 } | |
813 | |
814 void OmniboxViewGtk::SetBaseColor() { | 783 void OmniboxViewGtk::SetBaseColor() { |
815 DCHECK(text_view_); | 784 DCHECK(text_view_); |
816 | 785 |
817 bool use_gtk = theme_service_->UsingNativeTheme(); | 786 bool use_gtk = theme_service_->UsingNativeTheme(); |
818 if (use_gtk) { | 787 if (use_gtk) { |
819 gtk_widget_modify_cursor(text_view_, NULL, NULL); | 788 gtk_widget_modify_cursor(text_view_, NULL, NULL); |
820 gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL); | 789 gtk_widget_modify_base(text_view_, GTK_STATE_NORMAL, NULL); |
821 gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, NULL); | 790 gtk_widget_modify_base(text_view_, GTK_STATE_SELECTED, NULL); |
822 gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, NULL); | 791 gtk_widget_modify_text(text_view_, GTK_STATE_SELECTED, NULL); |
823 gtk_widget_modify_base(text_view_, GTK_STATE_ACTIVE, NULL); | 792 gtk_widget_modify_base(text_view_, GTK_STATE_ACTIVE, NULL); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 | 837 |
869 g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL); | 838 g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL); |
870 g_object_set(normal_text_tag_, "foreground", "#000000", NULL); | 839 g_object_set(normal_text_tag_, "foreground", "#000000", NULL); |
871 } | 840 } |
872 | 841 |
873 AdjustVerticalAlignmentOfInstantView(); | 842 AdjustVerticalAlignmentOfInstantView(); |
874 UpdateInstantViewColors(); | 843 UpdateInstantViewColors(); |
875 } | 844 } |
876 | 845 |
877 void OmniboxViewGtk::UpdateInstantViewColors() { | 846 void OmniboxViewGtk::UpdateInstantViewColors() { |
878 SkColor selection_text, selection_bg; | 847 GdkColor faded_text; |
879 GdkColor faded_text, normal_bg; | 848 if (theme_service_->UsingNativeTheme()) { |
880 | |
881 bool use_gtk = theme_service_->UsingNativeTheme(); | |
882 if (use_gtk) { | |
883 GtkStyle* style = gtk_rc_get_style(instant_view_); | 849 GtkStyle* style = gtk_rc_get_style(instant_view_); |
884 | |
885 faded_text = gtk_util::AverageColors( | 850 faded_text = gtk_util::AverageColors( |
886 style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]); | 851 style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]); |
887 normal_bg = style->base[GTK_STATE_NORMAL]; | |
888 | |
889 selection_text = gfx::GdkColorToSkColor(style->text[GTK_STATE_SELECTED]); | |
890 selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]); | |
891 } else { | 852 } else { |
892 gdk_color_parse(kTextBaseColor, &faded_text); | 853 gdk_color_parse(kTextBaseColor, &faded_text); |
893 | |
894 normal_bg = LocationBarViewGtk::kBackgroundColor; | |
895 selection_text = | |
896 theme_service_->get_active_selection_fg_color(); | |
897 selection_bg = | |
898 theme_service_->get_active_selection_bg_color(); | |
899 } | 854 } |
900 | 855 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &faded_text); |
901 double alpha = instant_animation_->is_animating() ? | |
902 instant_animation_->GetCurrentValue() : 0.0; | |
903 GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | |
904 selection_text, | |
905 gfx::GdkColorToSkColor(faded_text), | |
906 alpha * 0xff)); | |
907 GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | |
908 selection_bg, | |
909 gfx::GdkColorToSkColor(normal_bg), | |
910 alpha * 0xff)); | |
911 | |
912 if (alpha > 0.0) { | |
913 gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1); | |
914 // ACTIVE is the state for text that is selected, but not focused. | |
915 gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text); | |
916 gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg); | |
917 } else { | |
918 // When the text is unselected, fg is used for text color, the state | |
919 // is NORMAL, and the background is transparent. | |
920 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text); | |
921 } | |
922 } | 856 } |
923 | 857 |
924 void OmniboxViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { | 858 void OmniboxViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { |
925 OnBeforePossibleChange(); | 859 OnBeforePossibleChange(); |
926 } | 860 } |
927 | 861 |
928 void OmniboxViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { | 862 void OmniboxViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { |
929 OnAfterPossibleChange(); | 863 OnAfterPossibleChange(); |
930 } | 864 } |
931 | 865 |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 GtkTextIter* location, | 1281 GtkTextIter* location, |
1348 GtkTextMark* mark) { | 1282 GtkTextMark* mark) { |
1349 if (!text_buffer_ || buffer != text_buffer_) | 1283 if (!text_buffer_ || buffer != text_buffer_) |
1350 return; | 1284 return; |
1351 | 1285 |
1352 if (mark != gtk_text_buffer_get_insert(text_buffer_) && | 1286 if (mark != gtk_text_buffer_get_insert(text_buffer_) && |
1353 mark != gtk_text_buffer_get_selection_bound(text_buffer_)) { | 1287 mark != gtk_text_buffer_get_selection_bound(text_buffer_)) { |
1354 return; | 1288 return; |
1355 } | 1289 } |
1356 | 1290 |
1357 StopAnimation(); | |
1358 | |
1359 // If we are here, that means the user may be changing the selection | 1291 // If we are here, that means the user may be changing the selection |
1360 selection_suggested_ = false; | 1292 selection_suggested_ = false; |
1361 | 1293 |
1362 // Get the currently-selected text, if there is any. | 1294 // Get the currently-selected text, if there is any. |
1363 std::string new_selected_text = GetSelectedText(); | 1295 std::string new_selected_text = GetSelectedText(); |
1364 | 1296 |
1365 // If we had some text selected earlier but it's no longer highlighted, we | 1297 // If we had some text selected earlier but it's no longer highlighted, we |
1366 // might need to save it now... | 1298 // might need to save it now... |
1367 if (!selected_text_.empty() && new_selected_text.empty()) { | 1299 if (!selected_text_.empty() && new_selected_text.empty()) { |
1368 // ... but only if we currently own the selection. We want to manually | 1300 // ... but only if we currently own the selection. We want to manually |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1936 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min); | 1868 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_min, range.cp_min); |
1937 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max); | 1869 gtk_text_buffer_get_iter_at_offset(text_buffer_, iter_max, range.cp_max); |
1938 } | 1870 } |
1939 | 1871 |
1940 bool OmniboxViewGtk::IsCaretAtEnd() const { | 1872 bool OmniboxViewGtk::IsCaretAtEnd() const { |
1941 const CharRange selection = GetSelection(); | 1873 const CharRange selection = GetSelection(); |
1942 return selection.cp_min == selection.cp_max && | 1874 return selection.cp_min == selection.cp_max && |
1943 selection.cp_min == GetOmniboxTextLength(); | 1875 selection.cp_min == GetOmniboxTextLength(); |
1944 } | 1876 } |
1945 | 1877 |
1946 void OmniboxViewGtk::StopAnimation() { | |
1947 // Clear the animation delegate so we don't get an AnimationEnded() callback. | |
1948 instant_animation_->set_delegate(NULL); | |
1949 instant_animation_->Stop(); | |
1950 UpdateInstantViewColors(); | |
1951 } | |
1952 | |
1953 void OmniboxViewGtk::SavePrimarySelection(const std::string& selected_text) { | 1878 void OmniboxViewGtk::SavePrimarySelection(const std::string& selected_text) { |
1954 DCHECK(text_view_); | 1879 DCHECK(text_view_); |
1955 | 1880 |
1956 GtkClipboard* clipboard = | 1881 GtkClipboard* clipboard = |
1957 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); | 1882 gtk_widget_get_clipboard(text_view_, GDK_SELECTION_PRIMARY); |
1958 DCHECK(clipboard); | 1883 DCHECK(clipboard); |
1959 if (!clipboard) | 1884 if (!clipboard) |
1960 return; | 1885 return; |
1961 | 1886 |
1962 gtk_clipboard_set_text( | 1887 gtk_clipboard_set_text( |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 void OmniboxViewGtk::AdjustVerticalAlignmentOfInstantView() { | 2131 void OmniboxViewGtk::AdjustVerticalAlignmentOfInstantView() { |
2207 // By default, GtkTextView layouts an anchored child widget just above the | 2132 // By default, GtkTextView layouts an anchored child widget just above the |
2208 // baseline, so we need to move the |instant_view_| down to make sure it | 2133 // baseline, so we need to move the |instant_view_| down to make sure it |
2209 // has the same baseline as the |text_view_|. | 2134 // has the same baseline as the |text_view_|. |
2210 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2135 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
2211 int height; | 2136 int height; |
2212 pango_layout_get_size(layout, NULL, &height); | 2137 pango_layout_get_size(layout, NULL, &height); |
2213 int baseline = pango_layout_get_baseline(layout); | 2138 int baseline = pango_layout_get_baseline(layout); |
2214 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2139 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
2215 } | 2140 } |
OLD | NEW |