diff options
author | Xan Lopez <xan@gnome.org> | 2009-10-23 07:51:17 +0800 |
---|---|---|
committer | Xan Lopez <xan@gnome.org> | 2009-10-24 02:56:24 +0800 |
commit | 46845bbcf412994f0bb3e949178c6f72f676f70b (patch) | |
tree | 998ead5ff6fd8a86269e45313a2baa3d2afd182b | |
parent | dc14e5bcab1759813aeed64af213ba067535e7e8 (diff) | |
download | gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar.gz gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar.bz2 gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar.lz gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar.xz gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.tar.zst gsoc2013-epiphany-46845bbcf412994f0bb3e949178c6f72f676f70b.zip |
Refactor EphyShell lifetime tracking
Stop having each EphyWindow ref the shell, and instead have the shell
track all the newly created EphyWindows. When the last one is gone,
quit the GTK+ mainloop. This is simpler and avoids potential reference
cycles (see bug #573551).
Bug #599348
-rw-r--r-- | embed/downloader-view.c | 17 | ||||
-rw-r--r-- | embed/ephy-embed-shell.c | 40 | ||||
-rw-r--r-- | embed/ephy-embed-shell.h | 4 | ||||
-rw-r--r-- | src/ephy-main.c | 23 | ||||
-rw-r--r-- | src/ephy-window.c | 12 |
5 files changed, 55 insertions, 41 deletions
diff --git a/embed/downloader-view.c b/embed/downloader-view.c index da28caf23..a2f655807 100644 --- a/embed/downloader-view.c +++ b/embed/downloader-view.c @@ -74,7 +74,6 @@ struct _DownloaderViewPrivate NotifyNotification *notification; #endif - guint idle_unref : 1; guint source_id; guint notification_timeout; }; @@ -222,8 +221,6 @@ prepare_close_cb (EphyEmbedShell *shell, /* hide window already */ gtk_widget_hide (priv->window); - priv->idle_unref = FALSE; - /* cancel pending downloads */ g_hash_table_foreach_remove (priv->downloads_hash, (GHRFunc) remove_download, view); @@ -237,14 +234,12 @@ prepare_close_cb (EphyEmbedShell *shell, static void downloader_view_init (DownloaderView *dv) { - g_object_ref (embed_shell); - + _ephy_embed_shell_track_object (embed_shell, G_OBJECT (dv)); dv->priv = EPHY_DOWNLOADER_VIEW_GET_PRIVATE (dv); dv->priv->downloads_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)gtk_tree_row_reference_free); - dv->priv->idle_unref = TRUE; downloader_view_build_ui (dv); @@ -259,7 +254,6 @@ downloader_view_finalize (GObject *object) { DownloaderView *dv = EPHY_DOWNLOADER_VIEW (object); DownloaderViewPrivate *priv = dv->priv; - gboolean idle_unref = dv->priv->idle_unref; if (priv->status_icon != NULL) { @@ -286,15 +280,6 @@ downloader_view_finalize (GObject *object) g_hash_table_destroy (dv->priv->downloads_hash); G_OBJECT_CLASS (downloader_view_parent_class)->finalize (object); - - if (idle_unref) - { - ephy_object_idle_unref (embed_shell); - } - else - { - g_object_unref (embed_shell); - } } DownloaderView * diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c index 85eb7fa2e..17f4b98e2 100644 --- a/embed/ephy-embed-shell.c +++ b/embed/ephy-embed-shell.c @@ -57,12 +57,14 @@ struct _EphyEmbedShellPrivate EphyAdBlockManager *adblock_manager; GtkPageSetup *page_setup; GtkPrintSettings *print_settings; + guint object_count; guint single_initialised : 1; }; enum { PREPARE_CLOSE, + QUIT, LAST_SIGNAL }; @@ -315,6 +317,25 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + +/** + * EphyEmbedShell::quit: + * @shell: an #EphyEmbedShell + * + * The ::quit is emitted when all windows (browser windows, popups, + * download windows, etc) are closed and the @shell is ready to be + * closed. + * + * Since: 2.30 + **/ + signals[QUIT] = + g_signal_new ("quit", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); g_type_class_add_private (object_class, sizeof (EphyEmbedShellPrivate)); } @@ -490,3 +511,22 @@ ephy_embed_shell_get_print_settings (EphyEmbedShell *shell) return priv->print_settings; } + + +static void +object_notify_cb (EphyEmbedShell *shell, GObject *object) +{ + shell->priv->object_count--; + if (shell->priv->object_count == 0) + g_signal_emit (shell, signals[QUIT], 0); +} + +void +_ephy_embed_shell_track_object (EphyEmbedShell *shell, GObject *object) +{ + g_return_if_fail (EPHY_IS_EMBED_SHELL (shell)); + g_return_if_fail (G_IS_OBJECT (object)); + + g_object_weak_ref (object, (GWeakNotify)object_notify_cb, shell); + shell->priv->object_count++; +} diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h index 9772293b3..ef10c2acc 100644 --- a/embed/ephy-embed-shell.h +++ b/embed/ephy-embed-shell.h @@ -91,6 +91,10 @@ void ephy_embed_shell_set_print_settings (EphyEmbedShell *shell, GtkPrintSettings *ephy_embed_shell_get_print_settings (EphyEmbedShell *shell); +/* Private API */ +void _ephy_embed_shell_track_object (EphyEmbedShell *shell, + GObject *object); + G_END_DECLS #endif /* !EPHY_EMBED_SHELL_H */ diff --git a/src/ephy-main.c b/src/ephy-main.c index 5daca6fc6..493eb91dc 100644 --- a/src/ephy-main.c +++ b/src/ephy-main.c @@ -238,16 +238,6 @@ handle_email (GtkAboutDialog *about, } static void -shell_weak_notify (gpointer data, - GObject *zombie) -{ - if (gtk_main_level ()) - { - gtk_main_quit (); - } -} - -static void unref_proxy_reply_cb (DBusGProxy *proxy, GError *error, gpointer user_data) @@ -468,6 +458,12 @@ save_accels (void) g_free (filename); } +static void +shell_quit_cb (EphyShell *shell, gpointer data) +{ + gtk_main_quit (); +} + int main (int argc, char *argv[]) @@ -767,13 +763,10 @@ main (int argc, /* Now create the shell */ _ephy_shell_create_instance (); + g_signal_connect (ephy_shell, "quit", G_CALLBACK (shell_quit_cb), NULL); queue_commands (user_time); - /* We'll release the initial reference on idle */ - g_object_weak_ref (G_OBJECT (ephy_shell), shell_weak_notify, NULL); - ephy_object_idle_unref (ephy_shell); - #ifdef HAVE_LIBNOTIFY /* Init notifications for the download manager */ notify_init (PACKAGE); @@ -782,6 +775,8 @@ main (int argc, gtk_main (); /* Shutdown */ + g_object_unref (ephy_shell); + #ifdef HAVE_LIBNOTIFY if (notify_is_initted ()) notify_uninit (); diff --git a/src/ephy-window.c b/src/ephy-window.c index 3f53fa39d..df0c7dfb1 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -458,7 +458,6 @@ struct _EphyWindowPrivate guint is_popup : 1; guint present_on_insert : 1; guint key_theme_is_emacs : 1; - guint shell_unref : 1; }; enum @@ -3315,15 +3314,6 @@ ephy_window_dispose (GObject *object) destroy_fullscreen_popup (window); G_OBJECT_CLASS (ephy_window_parent_class)->dispose (object); - - /* We need to unref the shell after chaining up to the parent - * class, since our children widgets might need the shell to - * be around for some cleanup operations */ - if (window->priv->shell_unref == FALSE) - { - g_object_unref (ephy_shell); - window->priv->shell_unref = TRUE; - } } static void @@ -3642,7 +3632,7 @@ ephy_window_init (EphyWindow *window) { LOG ("EphyWindow initialising %p", window); - g_object_ref (ephy_shell); + _ephy_embed_shell_track_object (EPHY_EMBED_SHELL (ephy_shell), G_OBJECT (window)); window->priv = EPHY_WINDOW_GET_PRIVATE (window); } |