Chromium Code Reviews| Index: chrome/browser/gtk/browser_window_gtk.cc |
| diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc |
| index 484b5ff48fd0a7038805fcd19fb9a3d63f449ede..a6b278bb2158f4fb6fbfd3f95531b1c7f223383e 100644 |
| --- a/chrome/browser/gtk/browser_window_gtk.cc |
| +++ b/chrome/browser/gtk/browser_window_gtk.cc |
| @@ -4,8 +4,9 @@ |
| #include "chrome/browser/gtk/browser_window_gtk.h" |
| -#include "base/logging.h" |
| #include "base/base_paths_linux.h" |
| +#include "base/logging.h" |
| +#include "base/message_loop.h" |
| #include "base/path_service.h" |
| #include "chrome/browser/browser.h" |
| #include "chrome/browser/gtk/browser_toolbar_gtk.h" |
| @@ -50,11 +51,6 @@ static GdkPixbuf* LoadThemeImage(int resource_id) { |
| return pixbuf; |
| } |
| -gboolean MainWindowDestroyed(GtkWindow* window, BrowserWindowGtk* browser_win) { |
| - delete browser_win; |
| - return FALSE; // Don't stop this message. |
| -} |
| - |
| gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event, |
| BrowserWindowGtk* browser_win) { |
| gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height); |
| @@ -134,7 +130,7 @@ void BrowserWindowGtk::Init() { |
| window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
| gtk_window_set_default_size(window_, 640, 480); |
| g_signal_connect(G_OBJECT(window_), "destroy", |
| - G_CALLBACK(MainWindowDestroyed), this); |
| + G_CALLBACK(OnWindowDestroyed), this); |
| g_signal_connect(G_OBJECT(window_), "configure-event", |
| G_CALLBACK(MainWindowConfigured), this); |
| g_signal_connect(G_OBJECT(window_), "window-state-event", |
| @@ -205,8 +201,11 @@ void BrowserWindowGtk::Close() { |
| if (!window_) |
| return; |
| - gtk_widget_destroy(GTK_WIDGET(window_)); |
| + GtkWidget* window = GTK_WIDGET(window_); |
| + // To help catch bugs in any event handlers that might get fired during the |
| + // destruction, set window_ to NULL before any handlers will run. |
| window_ = NULL; |
| + gtk_widget_destroy(window); |
| } |
| void BrowserWindowGtk::Activate() { |
| @@ -418,3 +417,21 @@ void BrowserWindowGtk::SetCustomFrame(bool custom_frame) { |
| gtk_container_set_border_width(GTK_CONTAINER(vbox_), 0); |
| } |
| } |
| + |
| +// static |
| +gboolean BrowserWindowGtk::OnWindowDestroyed(GtkWidget* window, |
| + BrowserWindowGtk* browser_win) { |
| + // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the |
| + // signal right away, and we will be here (while Close() is still in the |
| + // call stack). In order to not reenter Close(), and to also follow the |
| + // expectations of BrowserList, we should run the BrowserWindowGtk destructor |
| + // not now, but after the run loop goes back to process messages. Otherwise |
| + // we will remove ourself from BrowserList while it's being iterated. |
| + // Additionally, now that we know the window is gone, we need to make sure to |
| + // set window_ to NULL, otherwise we will try to close the window again when |
| + // we call Close() in the destructor. |
| + browser_win->window_ = NULL; |
| + MessageLoop::current()->DeleteSoon(FROM_HERE, browser_win); |
|
darin (slow to review)
2009/03/12 22:26:25
i love problems like this :-P
this LGTM. DeleteS
|
| + return FALSE; // Don't stop this message. |
| +} |
| + |