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

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: Created 8 years, 11 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
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 recieves 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() { 76 void AutofillPopupViewGtk::Hide() {
65 gtk_widget_hide(window_); 77 gtk_widget_hide(window_);
66 } 78 }
67 79
68 void AutofillPopupViewGtk::ShowInternal() { 80 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. 81 // Find out the maximum bounds required by the popup.
78 // TODO(csharp): Once the icon is also displayed it will affect the required 82 // 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. 83 // size so it will need to be included in the calculation.
80 int popup_width = element_bounds().width(); 84 int popup_width = element_bounds().width();
81 DCHECK_EQ(autofill_values().size(), autofill_labels().size()); 85 DCHECK_EQ(autofill_values().size(), autofill_labels().size());
82 for (size_t i = 0; i < autofill_values().size(); ++i) { 86 for (size_t i = 0; i < autofill_values().size(); ++i) {
83 popup_width = std::max(popup_width, 87 popup_width = std::max(popup_width,
84 font_.GetStringWidth(autofill_values()[i]) + 88 font_.GetStringWidth(autofill_values()[i]) +
85 kMiddlePadding + 89 kMiddlePadding +
86 font_.GetStringWidth(autofill_labels()[i])); 90 font_.GetStringWidth(autofill_labels()[i]));
87 } 91 }
88 92
93 gint origin_x, origin_y;
94 gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y);
95
96 // Move the popup to appear right below the text field it is using.
97 bounds.SetRect(
98 origin_x + element_bounds().x(),
99 origin_y + element_bounds().y() + element_bounds().height(),
100 popup_width,
101 row_height_ * autofill_values().size());
102
103 gtk_window_move(GTK_WINDOW(window_), bounds.x(), bounds.y());
104
89 gtk_widget_set_size_request( 105 gtk_widget_set_size_request(
90 window_, 106 window_,
91 popup_width, 107 popup_width,
92 row_height_ * autofill_values().size()); 108 row_height_ * autofill_values().size());
93 109
94 gtk_widget_show(window_); 110 gtk_widget_show(window_);
95 111
96 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_); 112 GtkWidget* toplevel = gtk_widget_get_toplevel(parent_);
97 CHECK(gtk_widget_is_toplevel(toplevel)); 113 CHECK(gtk_widget_is_toplevel(toplevel));
98 ui::StackPopupWindow(window_, toplevel); 114 ui::StackPopupWindow(window_, toplevel);
99 } 115 }
100 116
117 void AutofillPopupViewGtk::InvalidateRow(size_t row) {
118 // TODO(deanm): Is it possible to use some constant for the width, instead
119 // of having to query the width of the window?
120 GdkRectangle row_rect = GetRectForRow(
121 row, GetWindowRect(window_->window).width(), row_height_).ToGdkRectangle() ;
122 gdk_window_invalidate_rect(window_->window, &row_rect, FALSE);
123 }
124
125 gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget,
126 GdkEventButton* event) {
127 size_t line = LineFromY(event->y);
128
129 if (event->button == 1) // Left click.
130 external_delegate()->didAcceptAutofillSuggestions(
131 autofill_values()[line],
132 autofill_unique_ids()[line],
133 line);
134
135 return TRUE;
136 }
137
101 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, 138 gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget,
102 GdkEventExpose* event) { 139 GdkEventExpose* event) {
103 gfx::Rect window_rect = GetWindowRect(event->window); 140 gfx::Rect window_rect = GetWindowRect(event->window);
104 gfx::Rect damage_rect = gfx::Rect(event->area); 141 gfx::Rect damage_rect = gfx::Rect(event->area);
105 142
106 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget))); 143 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(gtk_widget_get_window(widget)));
107 gdk_cairo_rectangle(cr, &event->area); 144 gdk_cairo_rectangle(cr, &event->area);
108 cairo_clip(cr); 145 cairo_clip(cr);
109 146
110 // This assert is kinda ugly, but it would be more currently unneeded work 147 // 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)) { 169 if (separator_index() == static_cast<int>(i)) {
133 int line_y = i * row_height_; 170 int line_y = i * row_height_;
134 171
135 cairo_save(cr); 172 cairo_save(cr);
136 cairo_move_to(cr, 0, line_y); 173 cairo_move_to(cr, 0, line_y);
137 cairo_line_to(cr, window_rect.width(), line_y); 174 cairo_line_to(cr, window_rect.width(), line_y);
138 cairo_stroke(cr); 175 cairo_stroke(cr);
139 cairo_restore(cr); 176 cairo_restore(cr);
140 } 177 }
141 178
179 if (selected_line() == i) {
180 gdk_cairo_set_source_color(cr, &kHoveredBackgroundColor);
181 cairo_rectangle(cr, line_rect.x(), line_rect.y(),
182 line_rect.width(), line_rect.height());
183 cairo_fill(cr);
184 }
185
142 // Center the text within the line. 186 // Center the text within the line.
143 int content_y = std::max( 187 int content_y = std::max(
144 line_rect.y(), 188 line_rect.y(),
145 line_rect.y() + ((row_height_ - actual_content_height) / 2)); 189 line_rect.y() + ((row_height_ - actual_content_height) / 2));
146 190
147 // Draw the value. 191 // Draw the value.
148 gtk_util::SetLayoutText(layout_, autofill_values()[i]); 192 gtk_util::SetLayoutText(layout_, autofill_values()[i]);
149 193
150 cairo_save(cr); 194 cairo_save(cr);
151 cairo_move_to(cr, 0, content_y); 195 cairo_move_to(cr, 0, content_y);
152 pango_cairo_show_layout(cr, layout_); 196 pango_cairo_show_layout(cr, layout_);
153 cairo_restore(cr); 197 cairo_restore(cr);
154 198
155 // Draw the label. 199 // Draw the label.
156 int x_align_left = window_rect.width() - 200 int x_align_left = window_rect.width() -
157 font_.GetStringWidth(autofill_labels()[i]); 201 font_.GetStringWidth(autofill_labels()[i]);
158 gtk_util::SetLayoutText(layout_, autofill_labels()[i]); 202 gtk_util::SetLayoutText(layout_, autofill_labels()[i]);
159 203
160 cairo_save(cr); 204 cairo_save(cr);
161 cairo_move_to(cr, x_align_left, line_rect.y()); 205 cairo_move_to(cr, x_align_left, line_rect.y());
162 pango_cairo_show_layout(cr, layout_); 206 pango_cairo_show_layout(cr, layout_);
163 cairo_restore(cr); 207 cairo_restore(cr);
164 } 208 }
165 209
166 cairo_destroy(cr); 210 cairo_destroy(cr);
167 211
168 return TRUE; 212 return TRUE;
169 } 213 }
170 214
215 gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget,
216 GdkEventMotion* event) {
217 size_t line = LineFromY(event->y);
218
219 SetSelectedLine(line);
220
221 return TRUE;
222 }
223
171 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect, 224 void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect,
172 const GdkColor& text_color) { 225 const GdkColor& text_color) {
173 int allocated_content_width = window_rect.width(); 226 int allocated_content_width = window_rect.width();
174 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE); 227 pango_layout_set_width(layout_, allocated_content_width * PANGO_SCALE);
175 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE); 228 pango_layout_set_height(layout_, row_height_ * PANGO_SCALE);
176 229
177 PangoAttrList* attrs = pango_attr_list_new(); 230 PangoAttrList* attrs = pango_attr_list_new();
178 231
179 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red, 232 PangoAttribute* fg_attr = pango_attr_foreground_new(text_color.red,
180 text_color.green, 233 text_color.green,
181 text_color.blue); 234 text_color.blue);
182 pango_attr_list_insert(attrs, fg_attr); // Ownership taken. 235 pango_attr_list_insert(attrs, fg_attr); // Ownership taken.
183 236
184 237
185 pango_layout_set_attributes(layout_, attrs); // Ref taken. 238 pango_layout_set_attributes(layout_, attrs); // Ref taken.
186 pango_attr_list_unref(attrs); 239 pango_attr_list_unref(attrs);
187 } 240 }
241
242 size_t AutofillPopupViewGtk::LineFromY(int y) {
243 return y / row_height_;
244 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698