OLD | NEW |
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_gtk.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 #include <gdk/gdkkeysyms.h> | 8 #include <gdk/gdkkeysyms.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 GdkRectangle first_char_bounds, last_char_bounds; | 426 GdkRectangle first_char_bounds, last_char_bounds; |
427 gtk_text_buffer_get_start_iter(text_buffer_, &start); | 427 gtk_text_buffer_get_start_iter(text_buffer_, &start); |
428 | 428 |
429 // Use the real end iterator here to take the width of instant suggestion | 429 // Use the real end iterator here to take the width of instant suggestion |
430 // text into account, so that location bar can layout its children correctly. | 430 // text into account, so that location bar can layout its children correctly. |
431 gtk_text_buffer_get_end_iter(text_buffer_, &end); | 431 gtk_text_buffer_get_end_iter(text_buffer_, &end); |
432 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), | 432 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), |
433 &start, &first_char_bounds); | 433 &start, &first_char_bounds); |
434 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), | 434 gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), |
435 &end, &last_char_bounds); | 435 &end, &last_char_bounds); |
436 return ((last_char_bounds.x > first_char_bounds.x) ? | 436 |
437 (last_char_bounds.x + last_char_bounds.width - first_char_bounds.x) : | 437 gint first_char_start = first_char_bounds.x; |
438 (first_char_bounds.x - last_char_bounds.x + last_char_bounds.width)) + | 438 gint first_char_end = first_char_start + first_char_bounds.width; |
439 horizontal_border_size; | 439 gint last_char_start = last_char_bounds.x; |
| 440 gint last_char_end = last_char_start + last_char_bounds.width; |
| 441 |
| 442 // bounds width could be negative for RTL text. |
| 443 if (first_char_start > first_char_end) |
| 444 std::swap(first_char_start, first_char_end); |
| 445 if (last_char_start > last_char_end) |
| 446 std::swap(last_char_start, last_char_end); |
| 447 |
| 448 gint text_width = first_char_start < last_char_start ? |
| 449 last_char_end - first_char_start : first_char_end - last_char_start; |
| 450 |
| 451 return text_width + horizontal_border_size; |
440 } | 452 } |
441 | 453 |
442 int AutocompleteEditViewGtk::WidthOfTextAfterCursor() { | 454 int AutocompleteEditViewGtk::WidthOfTextAfterCursor() { |
443 // Not used. | 455 // Not used. |
444 return -1; | 456 return -1; |
445 } | 457 } |
446 | 458 |
447 gfx::Font AutocompleteEditViewGtk::GetFont() { | 459 gfx::Font AutocompleteEditViewGtk::GetFont() { |
448 GtkRcStyle* rc_style = gtk_widget_get_modifier_style(text_view_); | 460 GtkRcStyle* rc_style = gtk_widget_get_modifier_style(text_view_); |
449 return gfx::Font((rc_style && rc_style->font_desc) ? | 461 return gfx::Font((rc_style && rc_style->font_desc) ? |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 | 853 |
842 g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL); | 854 g_object_set(faded_text_tag_, "foreground", kTextBaseColor, NULL); |
843 g_object_set(normal_text_tag_, "foreground", "#000000", NULL); | 855 g_object_set(normal_text_tag_, "foreground", "#000000", NULL); |
844 } | 856 } |
845 | 857 |
846 AdjustVerticalAlignmentOfInstantView(); | 858 AdjustVerticalAlignmentOfInstantView(); |
847 UpdateInstantViewColors(); | 859 UpdateInstantViewColors(); |
848 } | 860 } |
849 | 861 |
850 void AutocompleteEditViewGtk::UpdateInstantViewColors() { | 862 void AutocompleteEditViewGtk::UpdateInstantViewColors() { |
851 #if !defined(TOOLKIT_VIEWS) | |
852 SkColor selection_text, selection_bg; | 863 SkColor selection_text, selection_bg; |
853 GdkColor faded_text, normal_bg; | 864 GdkColor faded_text, normal_bg; |
854 | 865 |
855 if (theme_provider_->UseGtkTheme()) { | 866 #if defined(TOOLKIT_VIEWS) |
856 GtkStyle* style = gtk_rc_get_style(text_view_); | 867 bool use_gtk = false; |
| 868 #else |
| 869 bool use_gtk = theme_provider_->UseGtkTheme(); |
| 870 #endif |
| 871 |
| 872 if (use_gtk) { |
| 873 GtkStyle* style = gtk_rc_get_style(instant_view_); |
857 | 874 |
858 faded_text = gtk_util::AverageColors( | 875 faded_text = gtk_util::AverageColors( |
859 style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]); | 876 style->text[GTK_STATE_NORMAL], style->base[GTK_STATE_NORMAL]); |
860 normal_bg = style->base[GTK_STATE_NORMAL]; | 877 normal_bg = style->base[GTK_STATE_NORMAL]; |
861 | 878 |
862 selection_text = gfx::GdkColorToSkColor(style->text[GTK_STATE_SELECTED]); | 879 selection_text = gfx::GdkColorToSkColor(style->text[GTK_STATE_SELECTED]); |
863 selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]); | 880 selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]); |
864 } else { | 881 } else { |
865 gdk_color_parse(kTextBaseColor, &faded_text); | 882 gdk_color_parse(kTextBaseColor, &faded_text); |
| 883 |
| 884 #if defined(TOOLKIT_VIEWS) |
| 885 normal_bg = gfx::SkColorToGdkColor( |
| 886 LocationBarView::GetColor(ToolbarModel::NONE, |
| 887 LocationBarView::BACKGROUND)); |
| 888 selection_text = LocationBarView::GetColor( |
| 889 ToolbarModel::NONE, LocationBarView::SELECTED_TEXT); |
| 890 |
| 891 GtkStyle* style = gtk_rc_get_style(instant_view_); |
| 892 selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]); |
| 893 #else |
866 normal_bg = LocationBarViewGtk::kBackgroundColor; | 894 normal_bg = LocationBarViewGtk::kBackgroundColor; |
867 | |
868 selection_text = | 895 selection_text = |
869 theme_provider_->get_active_selection_fg_color(); | 896 theme_provider_->get_active_selection_fg_color(); |
870 selection_bg = | 897 selection_bg = |
871 theme_provider_->get_active_selection_bg_color(); | 898 theme_provider_->get_active_selection_bg_color(); |
| 899 #endif |
872 } | 900 } |
873 | 901 |
874 double alpha = instant_animation_->is_animating() ? | 902 double alpha = instant_animation_->is_animating() ? |
875 instant_animation_->GetCurrentValue() : 0.0; | 903 instant_animation_->GetCurrentValue() : 0.0; |
876 GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | 904 GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend( |
877 selection_text, | 905 selection_text, |
878 gfx::GdkColorToSkColor(faded_text), | 906 gfx::GdkColorToSkColor(faded_text), |
879 alpha * 0xff)); | 907 alpha * 0xff)); |
880 GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | 908 GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend( |
881 selection_bg, | 909 selection_bg, |
882 gfx::GdkColorToSkColor(normal_bg), | 910 gfx::GdkColorToSkColor(normal_bg), |
883 alpha * 0xff)); | 911 alpha * 0xff)); |
884 | 912 |
885 if (alpha > 0.0) { | 913 if (alpha > 0.0) { |
886 gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1); | 914 gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1); |
887 // ACTIVE is the state for text that is selected, but not focused. | 915 // ACTIVE is the state for text that is selected, but not focused. |
888 gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text); | 916 gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text); |
889 gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg); | 917 gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg); |
890 } else { | 918 } else { |
891 // When the text is unselected, fg is used for text color, the state | 919 // When the text is unselected, fg is used for text color, the state |
892 // is NORMAL, and the background is transparent. | 920 // is NORMAL, and the background is transparent. |
893 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text); | 921 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text); |
894 } | 922 } |
895 #else // defined(TOOLKIT_VIEWS) | |
896 // We don't worry about views because it doesn't use the instant view. | |
897 #endif | |
898 } | 923 } |
899 | 924 |
900 void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { | 925 void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { |
901 OnBeforePossibleChange(); | 926 OnBeforePossibleChange(); |
902 } | 927 } |
903 | 928 |
904 void AutocompleteEditViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { | 929 void AutocompleteEditViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { |
905 OnAfterPossibleChange(); | 930 OnAfterPossibleChange(); |
906 } | 931 } |
907 | 932 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 } | 1190 } |
1166 | 1191 |
1167 void AutocompleteEditViewGtk::HandleViewMoveCursor( | 1192 void AutocompleteEditViewGtk::HandleViewMoveCursor( |
1168 GtkWidget* sender, | 1193 GtkWidget* sender, |
1169 GtkMovementStep step, | 1194 GtkMovementStep step, |
1170 gint count, | 1195 gint count, |
1171 gboolean extend_selection) { | 1196 gboolean extend_selection) { |
1172 GtkTextIter sel_start, sel_end; | 1197 GtkTextIter sel_start, sel_end; |
1173 gboolean has_selection = | 1198 gboolean has_selection = |
1174 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); | 1199 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); |
| 1200 bool handled = false; |
1175 | 1201 |
1176 bool handled = true; | 1202 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && |
| 1203 (count == 1 || count == -1)) { |
| 1204 gint cursor_pos; |
| 1205 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL); |
1177 | 1206 |
1178 // We want the GtkEntry behavior when you move the cursor while you have a | 1207 // We need to take the content direction into account when handling cursor |
1179 // selection. GtkTextView just drops the selection and moves the cursor, but | 1208 // movement, because the behavior of Left and Right key will be inverted if |
1180 // instead we want to move the cursor to the appropiate end of the selection. | 1209 // the direction is RTL. Although we should check the direction around the |
1181 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection) { | 1210 // input caret, it's much simpler and good enough to check whole content's |
1182 if ((count == 1 || count == -1) && has_selection) { | 1211 // direction. |
| 1212 PangoDirection content_dir = GetContentDirection(); |
| 1213 gint count_towards_end = content_dir == PANGO_DIRECTION_RTL ? -1 : 1; |
| 1214 |
| 1215 // We want the GtkEntry behavior when you move the cursor while you have a |
| 1216 // selection. GtkTextView just drops the selection and moves the cursor, |
| 1217 // but instead we want to move the cursor to the appropiate end of the |
| 1218 // selection. |
| 1219 if (has_selection) { |
1183 // We have a selection and start / end are in ascending order. | 1220 // We have a selection and start / end are in ascending order. |
1184 // Cursor placement will remove the selection, so we need inform |model_| | 1221 // Cursor placement will remove the selection, so we need inform |
1185 // about this change by calling On{Before|After}PossibleChange() methods. | 1222 // |model_| about this change by |
| 1223 // calling On{Before|After}PossibleChange() methods. |
1186 OnBeforePossibleChange(); | 1224 OnBeforePossibleChange(); |
1187 gtk_text_buffer_place_cursor(text_buffer_, | 1225 gtk_text_buffer_place_cursor( |
1188 count == 1 ? &sel_end : &sel_start); | 1226 text_buffer_, count == count_towards_end ? &sel_end : &sel_start); |
1189 OnAfterPossibleChange(); | 1227 OnAfterPossibleChange(); |
1190 } else if (count == 1 && !has_selection) { | 1228 handled = true; |
1191 gint cursor_pos; | 1229 } else if (count == count_towards_end && cursor_pos == GetTextLength()) { |
1192 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, | 1230 handled = controller_->OnCommitSuggestedText(GetText()); |
1193 NULL); | |
1194 if (cursor_pos == GetTextLength()) | |
1195 controller_->OnCommitSuggestedText(GetText()); | |
1196 else | |
1197 handled = false; | |
1198 } else { | |
1199 handled = false; | |
1200 } | 1231 } |
1201 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. | 1232 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. |
1202 // Multiply by count for the direction (if we move too much that's ok). | 1233 // Multiply by count for the direction (if we move too much that's ok). |
1203 model_->OnUpOrDownKeyPressed(model_->result().size() * count); | 1234 model_->OnUpOrDownKeyPressed(model_->result().size() * count); |
| 1235 handled = true; |
1204 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. | 1236 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. |
1205 model_->OnUpOrDownKeyPressed(count); | 1237 model_->OnUpOrDownKeyPressed(count); |
1206 } else { | 1238 handled = true; |
1207 handled = false; | |
1208 } | 1239 } |
1209 | 1240 |
1210 if (!handled) { | 1241 if (!handled) { |
1211 // Cursor movement may change the selection, we need to record the change | 1242 // Cursor movement may change the selection, we need to record the change |
1212 // and report it to |model_|. | 1243 // and report it to |model_|. |
1213 if (has_selection || extend_selection) | 1244 if (has_selection || extend_selection) |
1214 OnBeforePossibleChange(); | 1245 OnBeforePossibleChange(); |
1215 | 1246 |
1216 // Propagate into GtkTextView | 1247 // Propagate into GtkTextView |
1217 GtkTextViewClass* klass = GTK_TEXT_VIEW_GET_CLASS(text_view_); | 1248 GtkTextViewClass* klass = GTK_TEXT_VIEW_GET_CLASS(text_view_); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 // prevent the focus from being moved. | 1494 // prevent the focus from being moved. |
1464 bool handled = false; | 1495 bool handled = false; |
1465 | 1496 |
1466 // Trigger Tab to search behavior only when Tab key is pressed. | 1497 // Trigger Tab to search behavior only when Tab key is pressed. |
1467 if (model_->is_keyword_hint() && !model_->keyword().empty()) { | 1498 if (model_->is_keyword_hint() && !model_->keyword().empty()) { |
1468 if (enable_tab_to_search_) { | 1499 if (enable_tab_to_search_) { |
1469 model_->AcceptKeyword(); | 1500 model_->AcceptKeyword(); |
1470 handled = true; | 1501 handled = true; |
1471 } | 1502 } |
1472 } else { | 1503 } else { |
1473 // TODO(estade): this only works for linux/gtk; linux/views doesn't use | |
1474 // |instant_view_| so its visibility is not an indicator of whether we | |
1475 // have a suggestion. | |
1476 if (GTK_WIDGET_VISIBLE(instant_view_)) { | 1504 if (GTK_WIDGET_VISIBLE(instant_view_)) { |
1477 controller_->OnCommitSuggestedText(GetText()); | 1505 controller_->OnCommitSuggestedText(GetText()); |
1478 handled = true; | 1506 handled = true; |
1479 } else { | 1507 } else { |
1480 handled = controller_->AcceptCurrentInstantPreview(); | 1508 handled = controller_->AcceptCurrentInstantPreview(); |
1481 } | 1509 } |
1482 } | 1510 } |
1483 | 1511 |
1484 if (handled) { | 1512 if (handled) { |
1485 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); | 1513 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2064 // baseline, so we need to move the |instant_view_| down to make sure it | 2092 // baseline, so we need to move the |instant_view_| down to make sure it |
2065 // has the same baseline as the |text_view_|. | 2093 // has the same baseline as the |text_view_|. |
2066 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2094 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
2067 int height; | 2095 int height; |
2068 pango_layout_get_size(layout, NULL, &height); | 2096 pango_layout_get_size(layout, NULL, &height); |
2069 PangoLayoutIter* iter = pango_layout_get_iter(layout); | 2097 PangoLayoutIter* iter = pango_layout_get_iter(layout); |
2070 int baseline = pango_layout_iter_get_baseline(iter); | 2098 int baseline = pango_layout_iter_get_baseline(iter); |
2071 pango_layout_iter_free(iter); | 2099 pango_layout_iter_free(iter); |
2072 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2100 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
2073 } | 2101 } |
OLD | NEW |