| 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 |