Index: chrome/browser/gtk/info_bubble_gtk.cc |
diff --git a/chrome/browser/gtk/info_bubble_gtk.cc b/chrome/browser/gtk/info_bubble_gtk.cc |
index 0fe2b7957b33ad8d8d17b8ecbbc1dac5d69b39d1..21834438b8a8ad2983dd865e697bcc1d0fc91753 100644 |
--- a/chrome/browser/gtk/info_bubble_gtk.cc |
+++ b/chrome/browser/gtk/info_bubble_gtk.cc |
@@ -116,17 +116,21 @@ gboolean HandleExpose(GtkWidget* widget, |
} // namespace |
// static |
-InfoBubbleGtk* InfoBubbleGtk::Show(const gfx::Rect& rect, GtkWidget* content) { |
+InfoBubbleGtk* InfoBubbleGtk::Show(const gfx::Rect& rect, |
+ GtkWidget* content, |
+ InfoBubbleGtkDelegate* delegate) { |
InfoBubbleGtk* bubble = new InfoBubbleGtk(); |
bubble->Init(rect, content); |
+ bubble->set_delegate(delegate); |
return bubble; |
} |
InfoBubbleGtk::InfoBubbleGtk() |
- : window_(NULL), |
+ : delegate_(NULL), |
+ window_(NULL), |
screen_x_(0), |
- screen_y_(0), |
- closed_(false) { |
+ screen_y_(0) { |
+ |
} |
InfoBubbleGtk::~InfoBubbleGtk() { |
@@ -173,18 +177,30 @@ void InfoBubbleGtk::Init(const gfx::Rect& rect, GtkWidget* content) { |
G_CALLBACK(&HandleConfigureThunk), this); |
g_signal_connect(window_, "button-press-event", |
G_CALLBACK(&HandleButtonPressThunk), this); |
+ g_signal_connect(window_, "destroy", |
+ G_CALLBACK(&HandleDestroyThunk), this); |
gtk_widget_show_all(window_); |
+ // Make sure our window has focus, is brought to the top, etc. |
gtk_window_present(GTK_WINDOW(window_)); |
+ // We add a GTK (application level) grab. This means we will get all |
+ // keyboard and mouse events for our application, even if they were delivered |
+ // on another window. This allows us to close when the user clicks outside |
+ // of the info bubble. We don't use an X grab since that would steal |
+ // keystrokes from your window manager, prevent you from interacting with |
+ // other applications, etc. |
gtk_grab_add(window_); |
} |
-void InfoBubbleGtk::Close() { |
- DCHECK(!closed_); |
+void InfoBubbleGtk::Close(bool closed_by_escape) { |
+ // Notify the delegate that we're about to close. This gives the chance |
+ // to save state / etc from the hosted widget before it's destroyed. |
+ if (delegate_) |
+ delegate_->InfoBubbleClosing(this, closed_by_escape); |
+ |
DCHECK(window_); |
gtk_widget_destroy(window_); |
- window_ = NULL; |
- closed_ = true; |
+ // |this| has been deleted, see HandleDestroy. |
} |
gboolean InfoBubbleGtk::HandleConfigure(GdkEventConfigure* event) { |
@@ -206,3 +222,11 @@ gboolean InfoBubbleGtk::HandleButtonPress(GdkEventButton* event) { |
Close(); |
return TRUE; |
} |
+ |
+gboolean InfoBubbleGtk::HandleDestroy() { |
+ // We are self deleting, we have a destroy signal setup to catch when we |
+ // destroy the widget manually, or the window was closed via X. This will |
+ // delete the InfoBubbleGtk object. |
+ delete this; |
+ return FALSE; // Propagate. |
+} |