Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc

Issue 9235072: Adding Mouse Support for new GTK Autofill (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixing problem with autofillAgent browser tests Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "autofill_popup_view_gtk.h" 5 #include "autofill_popup_view_gtk.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/autofill/autofill_external_delegate.h"
9 #include "chrome/browser/ui/gtk/gtk_util.h" 10 #include "chrome/browser/ui/gtk/gtk_util.h"
10 #include "ui/base/gtk/gtk_compat.h" 11 #include "ui/base/gtk/gtk_compat.h"
11 #include "ui/base/gtk/gtk_hig_constants.h" 12 #include "ui/base/gtk/gtk_hig_constants.h"
12 #include "ui/base/gtk/gtk_windowing.h" 13 #include "ui/base/gtk/gtk_windowing.h"
13 #include "ui/gfx/native_widget_types.h" 14 #include "ui/gfx/native_widget_types.h"
14 #include "ui/gfx/rect.h" 15 #include "ui/gfx/rect.h"
15 16
16 namespace { 17 namespace {
17 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce); 18 const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce);
19 const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0x0CD, 0xCD, 0xCD);
18 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00); 20 const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00);
19 21
20 // The amount of minimum padding between the Autofill value and label in pixels. 22 // The amount of minimum padding between the Autofill value and label in pixels.
21 const int kMiddlePadding = 10; 23 const int kMiddlePadding = 10;
22 24
23 // We have a 1 pixel border around the entire results popup. 25 // We have a 1 pixel border around the entire results popup.
24 const int kBorderThickness = 1; 26 const int kBorderThickness = 1;
25 27
26 gfx::Rect GetWindowRect(GdkWindow* window) { 28 gfx::Rect GetWindowRect(GdkWindow* window) {
27 return gfx::Rect(gdk_window_get_width(window), 29 return gfx::Rect(gdk_window_get_width(window),
28 gdk_window_get_height(window)); 30 gdk_window_get_height(window));
29 } 31 }
30 32
31 // Returns the rectangle containing the item at position |index| in the popup. 33 // Returns the rectangle containing the item at position |index| in the popup.
32 gfx::Rect GetRectForRow(size_t index, int width, int height) { 34 gfx::Rect GetRectForRow(size_t index, int width, int height) {
33 return gfx::Rect(0, (index * height), width, height); 35 return gfx::Rect(0, (index * height), width, height);
34 } 36 }
35 37
36 } // namespace 38 } // namespace
37 39
38 AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents, 40 AutofillPopupViewGtk::AutofillPopupViewGtk(
39 GtkWidget* parent) 41 content::WebContents* web_contents,
40 : AutofillPopupView(web_contents), 42 AutofillExternalDelegate* external_delegate,
43 GtkWidget* parent)
44 : AutofillPopupView(web_contents, external_delegate),
41 parent_(parent), 45 parent_(parent),
42 window_(gtk_window_new(GTK_WINDOW_POPUP)) { 46 window_(gtk_window_new(GTK_WINDOW_POPUP)) {
43 CHECK(parent != NULL); 47 CHECK(parent != NULL);
44 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE); 48 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
45 gtk_widget_set_app_paintable(window_, TRUE); 49 gtk_widget_set_app_paintable(window_, TRUE);
46 gtk_widget_set_double_buffered(window_, TRUE); 50 gtk_widget_set_double_buffered(window_, TRUE);
47 51
48 // Setup the window to ensure it recieves the expose event. 52 // Setup the window to ensure it receives the expose event.
49 gtk_widget_add_events(window_, GDK_EXPOSURE_MASK); 53 gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK |
54 GDK_BUTTON_RELEASE_MASK |
55 GDK_EXPOSURE_MASK |
56 GDK_POINTER_MOTION_MASK);
50 g_signal_connect(window_, "expose-event", 57 g_signal_connect(window_, "expose-event",
51 G_CALLBACK(HandleExposeThunk), this); 58 G_CALLBACK(HandleExposeThunk), this);
52 59
60 g_signal_connect(window_, "motion-notify-event",
61 G_CALLBACK(HandleMotionThunk), this);
62 g_signal_connect(window_, "button-release-event",
63 G_CALLBACK(HandleButtonReleaseThunk), this);
64
53 // Cache the layout so we don't have to create it for every expose. 65 // Cache the layout so we don't have to create it for every expose.
54 layout_ = gtk_widget_create_pango_layout(window_, NULL); 66 layout_ = gtk_widget_create_pango_layout(window_, NULL);
55 67
56 row_height_ = font_.GetHeight(); 68 row_height_ = font_.GetHeight();
57 } 69 }
58 70
59 AutofillPopupViewGtk::~AutofillPopupViewGtk() { 71 AutofillPopupViewGtk::~AutofillPopupViewGtk() {
60 g_object_unref(layout_); 72 g_object_unref(layout_);
61 gtk_widget_destroy(window_); 73 gtk_widget_destroy(window_);
62 } 74 }
63 75
64 void AutofillPopupViewGtk::Hide() {
65 gtk_widget_hide(window_);
66 }
67
68 void AutofillPopupViewGtk::ShowInternal() { 76 void AutofillPopupViewGtk::ShowInternal() {
69 gint origin_x, origin_y;
70 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
71
72 // Move the popup to appear right below the text field it is using.
73 gtk_window_move(GTK_WINDOW(window_),
74 origin_x + element_bounds().x(),
75 origin_y + element_bounds().y() + element_bounds().height());
76
77 // Find out the maximum bounds required by the popup. 77 // Find out the maximum bounds required by the popup.
78 // TODO(csharp): Once the icon is also displayed it will affect the required 78 // TODO(csharp): Once the icon is also displayed it will affect the required
79 // size so it will need to be included in the calculation. 79 // size so it will need to be included in the calculation.
80 int popup_width = element_bounds().width(); 80 int popup_width = element_bounds().width();
81 DCHECK_EQ(autofill_values().size(), autofill_labels().size()); 81 DCHECK_EQ(autofill_values().size(), autofill_labels().size());
82 for (size_t i = 0; i < autofill_values().size(); ++i) { 82 for (size_t i = 0; i < autofill_values().size(); ++i) {
83 popup_width = std::max(popup_width, 83 popup_width = std::max(popup_width,
84 font_.GetStringWidth(autofill_values()[i]) + 84 font_.GetStringWidth(autofill_values()[i]) +
85 kMiddlePadding + 85 kMiddlePadding +
86 font_.GetStringWidth(autofill_labels()[i])); 86 font_.GetStringWidth(autofill_labels()[i]));
87 } 87 }
88 88
89 gint origin_x, origin_y;
90 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
91
92 // Move the popup to appear right below the text field it is using.
93 bounds_.SetRect(
94 origin_x + element_bounds().x(),
95 origin_y + element_bounds().y() + element_bounds().height(),
96 popup_width,
97 row_height_ * autofill_values().size());
98
99 gtk_window_move(GTK_WINDOW(window_), bounds_.x(), bounds_.y());
100
89 gtk_widget_set_size_request( 101 gtk_widget_set_size_request(
90 window_, 102 window_,
91 popup_width, 103 popup_width,
92 row_height_ * autofill_values().size()); 104 row_height_ * autofill_values().size());
93 105
94 gtk_widget_show(window_); 106 gtk_widget_show(window_);
95 107
96 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_); 108 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
97 CHECK(gtk_widget_is_toplevel(toplevel)); 109 CHECK(gtk_widget_is_toplevel(toplevel));
98 ui::StackPopupWindow(window_, toplevel); 110 ui::StackPopupWindow(window_, toplevel);
99 } 111 }
100 112
113 void AutofillPopupViewGtk::HideInternal() {
114 gtk_widget_hide(window_);
115 }
116
117 void AutofillPopupViewGtk::InvalidateRow(size_t row) {
118 GdkRectangle row_rect = GetRectForRow(
119 row, bounds_.width(), row_height_).ToGdkRectangle();
120 gdk_window_invalidate_rect(window_->window, &row_rect, FALSE);
121 }
122
123 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget,
124 GdkEventButton* event) {
125 // We only care about the left click.
126 if (event->button != 1)
127 return FALSE;
128
129 size_t line = LineFromY(event->y);
130 DCHECK_LT(line, autofill_values().size());
131
132 external_delegate()->DidAcceptAutofillSuggestions(
133 autofill_values()[line],
134 autofill_unique_ids()[line],
135 line);
136
137 return TRUE;
138 }
139
101 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, 140 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
102 GdkEventExpose* event) { 141 GdkEventExpose* event) {
103 gfx::Rect window_rect = GetWindowRect(event->window); 142 gfx::Rect window_rect = GetWindowRect(event->window);
104 gfx::Rect damage_rect = gfx::Rect(event->area); 143 gfx::Rect damage_rect = gfx::Rect(event->area);
105 144
106 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget))); 145 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
107 gdk_cairo_rectangle(cr, &event->area); 146 gdk_cairo_rectangle(cr, &event->area);
108 cairo_clip(cr); 147 cairo_clip(cr);
109 148
110 // This assert is kinda ugly, but it would be more currently unneeded work 149 // This assert is kinda ugly, but it would be more currently unneeded work
(...skipping 21 matching lines...) Expand all
132 if (separator_index() == static_cast<int>(i)) { 171 if (separator_index() == static_cast<int>(i)) {
133 int line_y = i * row_height_; 172 int line_y = i * row_height_;
134 173
135 cairo_save(cr); 174 cairo_save(cr);
136 cairo_move_to(cr, 0, line_y); 175 cairo_move_to(cr, 0, line_y);
137 cairo_line_to(cr, window_rect.width(), line_y); 176 cairo_line_to(cr, window_rect.width(), line_y);
138 cairo_stroke(cr); 177 cairo_stroke(cr);
139 cairo_restore(cr); 178 cairo_restore(cr);
140 } 179 }
141 180
181 if (selected_line() == static_cast<int>(i)) {
182 gdk_cairo_set_source_color(cr, &kHoveredBackgroundColor);
183 cairo_rectangle(cr, line_rect.x(), line_rect.y(),
184 line_rect.width(), line_rect.height());
185 cairo_fill(cr);
186 }
187
142 // Center the text within the line. 188 // Center the text within the line.
143 int content_y = std::max( 189 int content_y = std::max(
144 line_rect.y(), 190 line_rect.y(),
145 line_rect.y() + ((row_height_ - actual_content_height) / 2)); 191 line_rect.y() + ((row_height_ - actual_content_height) / 2));
146 192
147 // Draw the value. 193 // Draw the value.
148 gtk_util::SetLayoutText(layout_, autofill_values()[i]); 194 gtk_util::SetLayoutText(layout_, autofill_values()[i]);
149 195
150 cairo_save(cr); 196 cairo_save(cr);
151 cairo_move_to(cr, 0, content_y); 197 cairo_move_to(cr, 0, content_y);
152 pango_cairo_show_layout(cr, layout_); 198 pango_cairo_show_layout(cr, layout_);
153 cairo_restore(cr); 199 cairo_restore(cr);
154 200
155 // Draw the label. 201 // Draw the label.
156 int x_align_left = window_rect.width() - 202 int x_align_left = window_rect.width() -
157 font_.GetStringWidth(autofill_labels()[i]); 203 font_.GetStringWidth(autofill_labels()[i]);
158 gtk_util::SetLayoutText(layout_, autofill_labels()[i]); 204 gtk_util::SetLayoutText(layout_, autofill_labels()[i]);
159 205
160 cairo_save(cr); 206 cairo_save(cr);
161 cairo_move_to(cr, x_align_left, line_rect.y()); 207 cairo_move_to(cr, x_align_left, line_rect.y());
162 pango_cairo_show_layout(cr, layout_); 208 pango_cairo_show_layout(cr, layout_);
163 cairo_restore(cr); 209 cairo_restore(cr);
164 } 210 }
165 211
166 cairo_destroy(cr); 212 cairo_destroy(cr);
167 213
168 return TRUE; 214 return TRUE;
169 } 215 }
170 216
217 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget,
218 GdkEventMotion* event) {
219 int line = LineFromY(event->y);
220
221 SetSelectedLine(line);
222
223 return TRUE;
224 }
225
171 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect, 226 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect,
172 const GdkColor& text_color) { 227 const GdkColor& text_color) {
173 int allocated_content_width = window_rect.width(); 228 int allocated_content_width = window_rect.width();
174 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE); 229 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE);
175 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE); 230 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE);
176 231
177 PangoAttrList* attrs = pango_attr_list_new(); 232 PangoAttrList* attrs = pango_attr_list_new();
178 233
179 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red, 234 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
180 text_color.green, 235 text_color.green,
181 text_color.blue); 236 text_color.blue);
182 pango_attr_list_insert(attrs, fg_attr); // Ownership taken. 237 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
183 238
184 239
185 pango_layout_set_attributes(layout_, attrs); // Ref taken. 240 pango_layout_set_attributes(layout_, attrs); // Ref taken.
186 pango_attr_list_unref(attrs); 241 pango_attr_list_unref(attrs);
187 } 242 }
243
244 int AutofillPopupViewGtk::LineFromY(int y) {
245 return y / row_height_;
246 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.h ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698