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 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 return ((first_char_start < last_char_start) ? | |
449 (last_char_end - first_char_start) : | |
450 (first_char_end - last_char_start)) + | |
439 horizontal_border_size; | 451 horizontal_border_size; |
Evan Stade
2010/12/11 00:13:25
indentation is weird here
| |
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 // TODO(suzhe): fix me. | |
Evan Stade
2010/12/11 00:13:25
?
James Su
2010/12/11 00:32:32
Done.
| |
892 GtkStyle* style = gtk_rc_get_style(instant_view_); | |
893 selection_bg = gfx::GdkColorToSkColor(style->base[GTK_STATE_SELECTED]); | |
894 #else | |
866 normal_bg = LocationBarViewGtk::kBackgroundColor; | 895 normal_bg = LocationBarViewGtk::kBackgroundColor; |
867 | |
868 selection_text = | 896 selection_text = |
869 theme_provider_->get_active_selection_fg_color(); | 897 theme_provider_->get_active_selection_fg_color(); |
870 selection_bg = | 898 selection_bg = |
871 theme_provider_->get_active_selection_bg_color(); | 899 theme_provider_->get_active_selection_bg_color(); |
900 #endif | |
872 } | 901 } |
873 | 902 |
874 double alpha = instant_animation_->is_animating() ? | 903 double alpha = instant_animation_->is_animating() ? |
875 instant_animation_->GetCurrentValue() : 0.0; | 904 instant_animation_->GetCurrentValue() : 0.0; |
876 GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | 905 GdkColor text = gfx::SkColorToGdkColor(color_utils::AlphaBlend( |
877 selection_text, | 906 selection_text, |
878 gfx::GdkColorToSkColor(faded_text), | 907 gfx::GdkColorToSkColor(faded_text), |
879 alpha * 0xff)); | 908 alpha * 0xff)); |
880 GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend( | 909 GdkColor bg = gfx::SkColorToGdkColor(color_utils::AlphaBlend( |
881 selection_bg, | 910 selection_bg, |
882 gfx::GdkColorToSkColor(normal_bg), | 911 gfx::GdkColorToSkColor(normal_bg), |
883 alpha * 0xff)); | 912 alpha * 0xff)); |
884 | 913 |
885 if (alpha > 0.0) { | 914 if (alpha > 0.0) { |
886 gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1); | 915 gtk_label_select_region(GTK_LABEL(instant_view_), 0, -1); |
887 // ACTIVE is the state for text that is selected, but not focused. | 916 // ACTIVE is the state for text that is selected, but not focused. |
888 gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text); | 917 gtk_widget_modify_text(instant_view_, GTK_STATE_ACTIVE, &text); |
889 gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg); | 918 gtk_widget_modify_base(instant_view_, GTK_STATE_ACTIVE, &bg); |
890 } else { | 919 } else { |
891 // When the text is unselected, fg is used for text color, the state | 920 // When the text is unselected, fg is used for text color, the state |
892 // is NORMAL, and the background is transparent. | 921 // is NORMAL, and the background is transparent. |
893 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text); | 922 gtk_widget_modify_fg(instant_view_, GTK_STATE_NORMAL, &text); |
894 } | 923 } |
895 #else // defined(TOOLKIT_VIEWS) | |
896 // We don't worry about views because it doesn't use the instant view. | |
897 #endif | |
898 } | 924 } |
899 | 925 |
900 void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { | 926 void AutocompleteEditViewGtk::HandleBeginUserAction(GtkTextBuffer* sender) { |
901 OnBeforePossibleChange(); | 927 OnBeforePossibleChange(); |
902 } | 928 } |
903 | 929 |
904 void AutocompleteEditViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { | 930 void AutocompleteEditViewGtk::HandleEndUserAction(GtkTextBuffer* sender) { |
905 OnAfterPossibleChange(); | 931 OnAfterPossibleChange(); |
906 } | 932 } |
907 | 933 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1165 } | 1191 } |
1166 | 1192 |
1167 void AutocompleteEditViewGtk::HandleViewMoveCursor( | 1193 void AutocompleteEditViewGtk::HandleViewMoveCursor( |
1168 GtkWidget* sender, | 1194 GtkWidget* sender, |
1169 GtkMovementStep step, | 1195 GtkMovementStep step, |
1170 gint count, | 1196 gint count, |
1171 gboolean extend_selection) { | 1197 gboolean extend_selection) { |
1172 GtkTextIter sel_start, sel_end; | 1198 GtkTextIter sel_start, sel_end; |
1173 gboolean has_selection = | 1199 gboolean has_selection = |
1174 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); | 1200 gtk_text_buffer_get_selection_bounds(text_buffer_, &sel_start, &sel_end); |
1201 bool handled = false; | |
1175 | 1202 |
1176 bool handled = true; | 1203 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection && |
1204 (count == 1 || count == -1)) { | |
1205 gint cursor_pos; | |
1206 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, NULL); | |
1177 | 1207 |
1178 // We want the GtkEntry behavior when you move the cursor while you have a | 1208 // We need to take the content direction into account when handling cursor |
1179 // selection. GtkTextView just drops the selection and moves the cursor, but | 1209 // 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. | 1210 // the direction is RTL. Although we should check the direction around the |
1181 if (step == GTK_MOVEMENT_VISUAL_POSITIONS && !extend_selection) { | 1211 // input caret, it's much simpler and good enough to check whole content's |
1182 if ((count == 1 || count == -1) && has_selection) { | 1212 // direction. |
1213 PangoDirection content_dir = GetContentDirection(); | |
1214 gint count_towards_end = (content_dir == PANGO_DIRECTION_RTL ? -1 : 1); | |
Evan Stade
2010/12/11 00:13:25
no ()
James Su
2010/12/11 00:32:32
Done.
| |
1215 | |
1216 // We want the GtkEntry behavior when you move the cursor while you have a | |
1217 // selection. GtkTextView just drops the selection and moves the cursor, | |
1218 // but instead we want to move the cursor to the appropiate end of the | |
1219 // selection. | |
1220 if (has_selection) { | |
1183 // We have a selection and start / end are in ascending order. | 1221 // We have a selection and start / end are in ascending order. |
1184 // Cursor placement will remove the selection, so we need inform |model_| | 1222 // Cursor placement will remove the selection, so we need inform |
1185 // about this change by calling On{Before|After}PossibleChange() methods. | 1223 // |model_| about this change by |
1224 // calling On{Before|After}PossibleChange() methods. | |
1186 OnBeforePossibleChange(); | 1225 OnBeforePossibleChange(); |
1187 gtk_text_buffer_place_cursor(text_buffer_, | 1226 gtk_text_buffer_place_cursor( |
1188 count == 1 ? &sel_end : &sel_start); | 1227 text_buffer_, count == count_towards_end ? &sel_end : &sel_start); |
1189 OnAfterPossibleChange(); | 1228 OnAfterPossibleChange(); |
1190 } else if (count == 1 && !has_selection) { | 1229 handled = true; |
1191 gint cursor_pos; | 1230 } else if (count == count_towards_end && cursor_pos == GetTextLength()) { |
1192 g_object_get(G_OBJECT(text_buffer_), "cursor-position", &cursor_pos, | 1231 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 } | 1232 } |
1201 } else if (step == GTK_MOVEMENT_PAGES) { // Page up and down. | 1233 } 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). | 1234 // Multiply by count for the direction (if we move too much that's ok). |
1203 model_->OnUpOrDownKeyPressed(model_->result().size() * count); | 1235 model_->OnUpOrDownKeyPressed(model_->result().size() * count); |
1236 handled = true; | |
1204 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. | 1237 } else if (step == GTK_MOVEMENT_DISPLAY_LINES) { // Arrow up and down. |
1205 model_->OnUpOrDownKeyPressed(count); | 1238 model_->OnUpOrDownKeyPressed(count); |
1206 } else { | 1239 handled = true; |
1207 handled = false; | |
1208 } | 1240 } |
1209 | 1241 |
1210 if (!handled) { | 1242 if (!handled) { |
1211 // Cursor movement may change the selection, we need to record the change | 1243 // Cursor movement may change the selection, we need to record the change |
1212 // and report it to |model_|. | 1244 // and report it to |model_|. |
1213 if (has_selection || extend_selection) | 1245 if (has_selection || extend_selection) |
1214 OnBeforePossibleChange(); | 1246 OnBeforePossibleChange(); |
1215 | 1247 |
1216 // Propagate into GtkTextView | 1248 // Propagate into GtkTextView |
1217 GtkTextViewClass* klass = GTK_TEXT_VIEW_GET_CLASS(text_view_); | 1249 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. | 1495 // prevent the focus from being moved. |
1464 bool handled = false; | 1496 bool handled = false; |
1465 | 1497 |
1466 // Trigger Tab to search behavior only when Tab key is pressed. | 1498 // Trigger Tab to search behavior only when Tab key is pressed. |
1467 if (model_->is_keyword_hint() && !model_->keyword().empty()) { | 1499 if (model_->is_keyword_hint() && !model_->keyword().empty()) { |
1468 if (enable_tab_to_search_) { | 1500 if (enable_tab_to_search_) { |
1469 model_->AcceptKeyword(); | 1501 model_->AcceptKeyword(); |
1470 handled = true; | 1502 handled = true; |
1471 } | 1503 } |
1472 } else { | 1504 } 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_)) { | 1505 if (GTK_WIDGET_VISIBLE(instant_view_)) { |
1477 controller_->OnCommitSuggestedText(GetText()); | 1506 controller_->OnCommitSuggestedText(GetText()); |
1478 handled = true; | 1507 handled = true; |
1479 } else { | 1508 } else { |
1480 handled = controller_->AcceptCurrentInstantPreview(); | 1509 handled = controller_->AcceptCurrentInstantPreview(); |
1481 } | 1510 } |
1482 } | 1511 } |
1483 | 1512 |
1484 if (handled) { | 1513 if (handled) { |
1485 static guint signal_id = g_signal_lookup("move-focus", GTK_TYPE_WIDGET); | 1514 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 | 2093 // baseline, so we need to move the |instant_view_| down to make sure it |
2065 // has the same baseline as the |text_view_|. | 2094 // has the same baseline as the |text_view_|. |
2066 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); | 2095 PangoLayout* layout = gtk_label_get_layout(GTK_LABEL(instant_view_)); |
2067 int height; | 2096 int height; |
2068 pango_layout_get_size(layout, NULL, &height); | 2097 pango_layout_get_size(layout, NULL, &height); |
2069 PangoLayoutIter* iter = pango_layout_get_iter(layout); | 2098 PangoLayoutIter* iter = pango_layout_get_iter(layout); |
2070 int baseline = pango_layout_iter_get_baseline(iter); | 2099 int baseline = pango_layout_iter_get_baseline(iter); |
2071 pango_layout_iter_free(iter); | 2100 pango_layout_iter_free(iter); |
2072 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); | 2101 g_object_set(instant_anchor_tag_, "rise", baseline - height, NULL); |
2073 } | 2102 } |
OLD | NEW |