Chromium Code Reviews| 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 |