| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 24 matching lines...) Expand all Loading... |
| 35 #include "chrome/browser/gtk/gtk_theme_provider.h" | 35 #include "chrome/browser/gtk/gtk_theme_provider.h" |
| 36 #include "chrome/browser/gtk/location_bar_view_gtk.h" | 36 #include "chrome/browser/gtk/location_bar_view_gtk.h" |
| 37 #endif | 37 #endif |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| 41 const char kTextBaseColor[] = "#808080"; | 41 const char kTextBaseColor[] = "#808080"; |
| 42 const char kSecureSchemeColor[] = "#009614"; | 42 const char kSecureSchemeColor[] = "#009614"; |
| 43 const char kInsecureSchemeColor[] = "#c80000"; | 43 const char kInsecureSchemeColor[] = "#c80000"; |
| 44 | 44 |
| 45 const double kStrikethroughStrokeRed = 210.0 / 256.0; |
| 46 const double kStrikethroughStrokeWidth = 2.0; |
| 47 |
| 45 size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) { | 48 size_t GetUTF8Offset(const std::wstring& wide_text, size_t wide_text_offset) { |
| 46 return WideToUTF8(wide_text.substr(0, wide_text_offset)).size(); | 49 return WideToUTF8(wide_text.substr(0, wide_text_offset)).size(); |
| 47 } | 50 } |
| 48 | 51 |
| 49 // Stores GTK+-specific state so it can be restored after switching tabs. | 52 // Stores GTK+-specific state so it can be restored after switching tabs. |
| 50 struct ViewState { | 53 struct ViewState { |
| 51 explicit ViewState(const AutocompleteEditViewGtk::CharRange& selection_range) | 54 explicit ViewState(const AutocompleteEditViewGtk::CharRange& selection_range) |
| 52 : selection_range(selection_range) { | 55 : selection_range(selection_range) { |
| 53 } | 56 } |
| 54 | 57 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 mark_set_handler_id_ = g_signal_connect( | 216 mark_set_handler_id_ = g_signal_connect( |
| 214 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this); | 217 text_buffer_, "mark-set", G_CALLBACK(&HandleMarkSetThunk), this); |
| 215 g_signal_connect(text_view_, "drag-data-received", | 218 g_signal_connect(text_view_, "drag-data-received", |
| 216 G_CALLBACK(&HandleDragDataReceivedThunk), this); | 219 G_CALLBACK(&HandleDragDataReceivedThunk), this); |
| 217 g_signal_connect(text_view_, "backspace", | 220 g_signal_connect(text_view_, "backspace", |
| 218 G_CALLBACK(&HandleBackSpaceThunk), this); | 221 G_CALLBACK(&HandleBackSpaceThunk), this); |
| 219 g_signal_connect(text_view_, "copy-clipboard", | 222 g_signal_connect(text_view_, "copy-clipboard", |
| 220 G_CALLBACK(&HandleCopyClipboardThunk), this); | 223 G_CALLBACK(&HandleCopyClipboardThunk), this); |
| 221 g_signal_connect(text_view_, "paste-clipboard", | 224 g_signal_connect(text_view_, "paste-clipboard", |
| 222 G_CALLBACK(&HandlePasteClipboardThunk), this); | 225 G_CALLBACK(&HandlePasteClipboardThunk), this); |
| 226 g_signal_connect_after(text_view_, "expose-event", |
| 227 G_CALLBACK(&HandleExposeEventThunk), this); |
| 223 | 228 |
| 224 #if !defined(TOOLKIT_VIEWS) | 229 #if !defined(TOOLKIT_VIEWS) |
| 225 registrar_.Add(this, | 230 registrar_.Add(this, |
| 226 NotificationType::BROWSER_THEME_CHANGED, | 231 NotificationType::BROWSER_THEME_CHANGED, |
| 227 NotificationService::AllSources()); | 232 NotificationService::AllSources()); |
| 228 theme_provider_->InitThemesFor(this); | 233 theme_provider_->InitThemesFor(this); |
| 229 #else | 234 #else |
| 230 // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe | 235 // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe |
| 231 // themes. | 236 // themes. |
| 232 SetBaseColor(); | 237 SetBaseColor(); |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 // the selection and unhighlight its text. | 1034 // the selection and unhighlight its text. |
| 1030 gtk_text_buffer_copy_clipboard(text_buffer_, clipboard); | 1035 gtk_text_buffer_copy_clipboard(text_buffer_, clipboard); |
| 1031 } | 1036 } |
| 1032 | 1037 |
| 1033 void AutocompleteEditViewGtk::HandlePasteClipboard() { | 1038 void AutocompleteEditViewGtk::HandlePasteClipboard() { |
| 1034 // We can't call model_->on_paste_replacing_all() here, because the actual | 1039 // We can't call model_->on_paste_replacing_all() here, because the actual |
| 1035 // paste clipboard action may not be performed if the clipboard is empty. | 1040 // paste clipboard action may not be performed if the clipboard is empty. |
| 1036 paste_clipboard_requested_ = true; | 1041 paste_clipboard_requested_ = true; |
| 1037 } | 1042 } |
| 1038 | 1043 |
| 1044 gfx::Rect AutocompleteEditViewGtk::WindowBoundsFromIters( |
| 1045 GtkTextIter* iter1, GtkTextIter* iter2) { |
| 1046 GdkRectangle start_location, end_location; |
| 1047 GtkTextView* text_view = GTK_TEXT_VIEW(text_view_); |
| 1048 gtk_text_view_get_iter_location(text_view, iter1, &start_location); |
| 1049 gtk_text_view_get_iter_location(text_view, iter2, &end_location); |
| 1050 |
| 1051 gint x1, x2, y1, y2; |
| 1052 gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_WIDGET, |
| 1053 start_location.x, start_location.y, |
| 1054 &x1, &y1); |
| 1055 gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_WIDGET, |
| 1056 end_location.x + end_location.width, |
| 1057 end_location.y + end_location.height, |
| 1058 &x2, &y2); |
| 1059 |
| 1060 return gfx::Rect(x1, y1, x2 - x1, y2 - y1); |
| 1061 } |
| 1062 |
| 1063 gboolean AutocompleteEditViewGtk::HandleExposeEvent(GdkEventExpose* expose) { |
| 1064 if (strikethrough_.cp_min >= strikethrough_.cp_max) |
| 1065 return FALSE; |
| 1066 |
| 1067 gfx::Rect expose_rect(expose->area); |
| 1068 |
| 1069 GtkTextIter iter_min, iter_max; |
| 1070 ItersFromCharRange(strikethrough_, &iter_min, &iter_max); |
| 1071 gfx::Rect strikethrough_rect = WindowBoundsFromIters(&iter_min, &iter_max); |
| 1072 |
| 1073 if (!expose_rect.Intersects(strikethrough_rect)) |
| 1074 return FALSE; |
| 1075 |
| 1076 // Finally, draw. |
| 1077 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(expose->window)); |
| 1078 cairo_rectangle(cr, expose_rect.x(), expose_rect.y(), |
| 1079 expose_rect.width(), expose_rect.height()); |
| 1080 cairo_clip(cr); |
| 1081 |
| 1082 // TODO(estade): we probably shouldn't draw the strikethrough on selected |
| 1083 // text. I started to do this, but it was way more effort than it seemed |
| 1084 // worth. |
| 1085 strikethrough_rect.Inset(kStrikethroughStrokeWidth, |
| 1086 kStrikethroughStrokeWidth); |
| 1087 cairo_set_source_rgb(cr, kStrikethroughStrokeRed, 0.0, 0.0); |
| 1088 cairo_set_line_width(cr, kStrikethroughStrokeWidth); |
| 1089 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); |
| 1090 cairo_move_to(cr, strikethrough_rect.x(), strikethrough_rect.bottom()); |
| 1091 cairo_line_to(cr, strikethrough_rect.right(), strikethrough_rect.y()); |
| 1092 cairo_stroke(cr); |
| 1093 cairo_destroy(cr); |
| 1094 |
| 1095 return FALSE; |
| 1096 } |
| 1097 |
| 1039 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed, | 1098 void AutocompleteEditViewGtk::SelectAllInternal(bool reversed, |
| 1040 bool update_primary_selection) { | 1099 bool update_primary_selection) { |
| 1041 GtkTextIter start, end; | 1100 GtkTextIter start, end; |
| 1042 if (reversed) { | 1101 if (reversed) { |
| 1043 gtk_text_buffer_get_bounds(text_buffer_, &end, &start); | 1102 gtk_text_buffer_get_bounds(text_buffer_, &end, &start); |
| 1044 } else { | 1103 } else { |
| 1045 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); | 1104 gtk_text_buffer_get_bounds(text_buffer_, &start, &end); |
| 1046 } | 1105 } |
| 1047 if (!update_primary_selection) | 1106 if (!update_primary_selection) |
| 1048 StartUpdatingHighlightedText(); | 1107 StartUpdatingHighlightedText(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 parts.host.begin)); | 1188 parts.host.begin)); |
| 1130 gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0, | 1189 gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0, |
| 1131 GetUTF8Offset(text, | 1190 GetUTF8Offset(text, |
| 1132 parts.host.end())); | 1191 parts.host.end())); |
| 1133 | 1192 |
| 1134 gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end); | 1193 gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end); |
| 1135 } else { | 1194 } else { |
| 1136 gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end); | 1195 gtk_text_buffer_apply_tag(text_buffer_, normal_text_tag_, &start, &end); |
| 1137 } | 1196 } |
| 1138 | 1197 |
| 1198 strikethrough_ = CharRange(); |
| 1139 // Emphasize the scheme for security UI display purposes (if necessary). | 1199 // Emphasize the scheme for security UI display purposes (if necessary). |
| 1140 if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() && | 1200 if (!model_->user_input_in_progress() && parts.scheme.is_nonempty() && |
| 1141 (scheme_security_level_ != ToolbarModel::NORMAL)) { | 1201 (scheme_security_level_ != ToolbarModel::NORMAL)) { |
| 1142 gtk_text_buffer_get_iter_at_line_index(text_buffer_, &start, 0, | 1202 strikethrough_ = CharRange(GetUTF8Offset(text, parts.scheme.begin), |
| 1143 GetUTF8Offset(text, | 1203 GetUTF8Offset(text, parts.scheme.end())); |
| 1144 parts.scheme.begin)); | 1204 ItersFromCharRange(strikethrough_, &start, &end); |
| 1145 gtk_text_buffer_get_iter_at_line_index(text_buffer_, &end, 0, | 1205 // When we draw the strikethrough, we don't want to include the ':' at the |
| 1146 GetUTF8Offset(text, | 1206 // end of the scheme. |
| 1147 parts.scheme.end())); | 1207 strikethrough_.cp_max--; |
| 1208 |
| 1148 if (scheme_security_level_ == ToolbarModel::SECURE) { | 1209 if (scheme_security_level_ == ToolbarModel::SECURE) { |
| 1149 gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, | 1210 gtk_text_buffer_apply_tag(text_buffer_, secure_scheme_tag_, |
| 1150 &start, &end); | 1211 &start, &end); |
| 1151 } else { | 1212 } else { |
| 1152 gtk_text_buffer_apply_tag(text_buffer_, insecure_scheme_tag_, | 1213 gtk_text_buffer_apply_tag(text_buffer_, insecure_scheme_tag_, |
| 1153 &start, &end); | 1214 &start, &end); |
| 1154 } | 1215 } |
| 1155 } | 1216 } |
| 1156 } | 1217 } |
| 1157 | 1218 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1177 std::string utf8 = WideToUTF8(text); | 1238 std::string utf8 = WideToUTF8(text); |
| 1178 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); | 1239 gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); |
| 1179 SetSelectedRange(range); | 1240 SetSelectedRange(range); |
| 1180 } | 1241 } |
| 1181 | 1242 |
| 1182 void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { | 1243 void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { |
| 1183 GtkTextIter insert, bound; | 1244 GtkTextIter insert, bound; |
| 1184 ItersFromCharRange(range, &bound, &insert); | 1245 ItersFromCharRange(range, &bound, &insert); |
| 1185 gtk_text_buffer_select_range(text_buffer_, &insert, &bound); | 1246 gtk_text_buffer_select_range(text_buffer_, &insert, &bound); |
| 1186 } | 1247 } |
| OLD | NEW |