Index: chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc |
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc |
index 93a347e551124cc2ecce1637279d72ac71a0fe0d..866d3ce548532eee7d4f90d1876d6c3ee06f9079 100644 |
--- a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc |
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc |
@@ -6,6 +6,7 @@ |
#include "base/logging.h" |
#include "base/utf_string_conversions.h" |
+#include "chrome/browser/autofill/autofill_external_delegate.h" |
#include "chrome/browser/ui/gtk/gtk_util.h" |
#include "ui/base/gtk/gtk_compat.h" |
#include "ui/base/gtk/gtk_hig_constants.h" |
@@ -15,6 +16,7 @@ |
namespace { |
const GdkColor kBorderColor = GDK_COLOR_RGB(0xc7, 0xca, 0xce); |
+const GdkColor kHoveredBackgroundColor = GDK_COLOR_RGB(0x0CD, 0xCD, 0xCD); |
const GdkColor kTextColor = GDK_COLOR_RGB(0x00, 0x00, 0x00); |
// The amount of minimum padding between the Autofill value and label in pixels. |
@@ -35,9 +37,11 @@ gfx::Rect GetRectForRow(size_t index, int width, int height) { |
} // namespace |
-AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents, |
- GtkWidget* parent) |
- : AutofillPopupView(web_contents), |
+AutofillPopupViewGtk::AutofillPopupViewGtk( |
+ content::WebContents* web_contents, |
+ AutofillExternalDelegate* external_delegate, |
+ GtkWidget* parent) |
+ : AutofillPopupView(web_contents, external_delegate), |
parent_(parent), |
window_(gtk_window_new(GTK_WINDOW_POPUP)) { |
CHECK(parent != NULL); |
@@ -46,10 +50,18 @@ AutofillPopupViewGtk::AutofillPopupViewGtk(content::WebContents* web_contents, |
gtk_widget_set_double_buffered(window_, TRUE); |
// Setup the window to ensure it recieves the expose event. |
- gtk_widget_add_events(window_, GDK_EXPOSURE_MASK); |
+ gtk_widget_add_events(window_, GDK_BUTTON_MOTION_MASK | |
+ GDK_BUTTON_RELEASE_MASK | |
+ GDK_EXPOSURE_MASK | |
+ GDK_POINTER_MOTION_MASK); |
g_signal_connect(window_, "expose-event", |
G_CALLBACK(HandleExposeThunk), this); |
+ g_signal_connect(window_, "motion-notify-event", |
+ G_CALLBACK(HandleMotionThunk), this); |
+ g_signal_connect(window_, "button-release-event", |
+ G_CALLBACK(HandleButtonReleaseThunk), this); |
+ |
// Cache the layout so we don't have to create it for every expose. |
layout_ = gtk_widget_create_pango_layout(window_, NULL); |
@@ -66,14 +78,6 @@ void AutofillPopupViewGtk::Hide() { |
} |
void AutofillPopupViewGtk::ShowInternal() { |
- gint origin_x, origin_y; |
- gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y); |
- |
- // Move the popup to appear right below the text field it is using. |
- gtk_window_move(GTK_WINDOW(window_), |
- origin_x + element_bounds().x(), |
- origin_y + element_bounds().y() + element_bounds().height()); |
- |
// Find out the maximum bounds required by the popup. |
// TODO(csharp): Once the icon is also displayed it will affect the required |
// size so it will need to be included in the calculation. |
@@ -86,6 +90,18 @@ void AutofillPopupViewGtk::ShowInternal() { |
font_.GetStringWidth(autofill_labels()[i])); |
} |
+ gint origin_x, origin_y; |
+ gdk_window_get_origin(gtk_widget_get_window(parent_), &origin_x, &origin_y); |
+ |
+ // Move the popup to appear right below the text field it is using. |
+ bounds.SetRect( |
+ origin_x + element_bounds().x(), |
+ origin_y + element_bounds().y() + element_bounds().height(), |
+ popup_width, |
+ row_height_ * autofill_values().size()); |
+ |
+ gtk_window_move(GTK_WINDOW(window_), bounds.x(), bounds.y()); |
+ |
gtk_widget_set_size_request( |
window_, |
popup_width, |
@@ -98,6 +114,27 @@ void AutofillPopupViewGtk::ShowInternal() { |
ui::StackPopupWindow(window_, toplevel); |
} |
+void AutofillPopupViewGtk::InvalidateRow(size_t row) { |
+ // TODO(deanm): Is it possible to use some constant for the width, instead |
+ // of having to query the width of the window? |
+ GdkRectangle row_rect = GetRectForRow( |
+ row, GetWindowRect(window_->window).width(), row_height_).ToGdkRectangle(); |
+ gdk_window_invalidate_rect(window_->window, &row_rect, FALSE); |
+} |
+ |
+gboolean AutofillPopupViewGtk::HandleButtonRelease(GtkWidget* widget, |
+ GdkEventButton* event) { |
+ size_t line = LineFromY(event->y); |
+ |
+ if (event->button == 1) // Left click. |
+ external_delegate()->didAcceptAutofillSuggestions( |
+ autofill_values()[line], |
+ autofill_unique_ids()[line], |
+ line); |
+ |
+ return TRUE; |
+} |
+ |
gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, |
GdkEventExpose* event) { |
gfx::Rect window_rect = GetWindowRect(event->window); |
@@ -139,6 +176,13 @@ gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, |
cairo_restore(cr); |
} |
+ if (selected_line() == i) { |
+ gdk_cairo_set_source_color(cr, &kHoveredBackgroundColor); |
+ cairo_rectangle(cr, line_rect.x(), line_rect.y(), |
+ line_rect.width(), line_rect.height()); |
+ cairo_fill(cr); |
+ } |
+ |
// Center the text within the line. |
int content_y = std::max( |
line_rect.y(), |
@@ -168,6 +212,15 @@ gboolean AutofillPopupViewGtk::HandleExpose(GtkWidget* widget, |
return TRUE; |
} |
+gboolean AutofillPopupViewGtk::HandleMotion(GtkWidget* widget, |
+ GdkEventMotion* event) { |
+ size_t line = LineFromY(event->y); |
+ |
+ SetSelectedLine(line); |
+ |
+ return TRUE; |
+} |
+ |
void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect, |
const GdkColor& text_color) { |
int allocated_content_width = window_rect.width(); |
@@ -185,3 +238,7 @@ void AutofillPopupViewGtk::SetupLayout(const gfx::Rect& window_rect, |
pango_layout_set_attributes(layout_, attrs); // Ref taken. |
pango_attr_list_unref(attrs); |
} |
+ |
+size_t AutofillPopupViewGtk::LineFromY(int y) { |
+ return y / row_height_; |
+} |