From 232e79a6d79b90d99deb11e126373d493f3045f6 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 19 Jun 2007 10:29:55 +0000 Subject: [PATCH] Use a static variable to hold the singleton and remove the code that binds 2007-06-19 Emmanuele Bassi * gtk/gtkrecentmanager.c: Use a static variable to hold the singleton and remove the code that binds a recent manager to a GdkScreen. (gtk_recent_manager_set_screen): Make it a NOOP. (gtk_recent_manager_get_for_screen): Proxy for gtk_recent_manager_get_default(). * gtk/gtk.symbols: * gtk/gtkrecentmanager.h: Deprecate gtk_recent_manager_set_screen() and gtk_recent_manager_get_for_screen(). * gtk/gtkmain.c: Force a synchronisation of the GtkRecentManager singleton (if any) when reaching main loop depth of 0. * gtk/gtkrecentchooserdefault.c: (gtk_recent_chooser_default_dispose): Disconnect the changed signal only if we have a manager and we are connected to it. (set_recent_manager): Ditto. * README.in: Document the deprecations. svn path=/trunk/; revision=18184 --- ChangeLog | 25 +++++++ README.in | 6 ++ gtk/gtk.symbols | 2 + gtk/gtkmain.c | 10 ++- gtk/gtkrecentchooserdefault.c | 17 +++-- gtk/gtkrecentmanager.c | 130 ++++++++++------------------------ gtk/gtkrecentmanager.h | 7 +- 7 files changed, 95 insertions(+), 102 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ff70be2c7..67eab857a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2007-06-19 Emmanuele Bassi + + * gtk/gtkrecentmanager.c: Use a static variable to hold the + singleton and remove the code that binds a recent manager to + a GdkScreen. + + (gtk_recent_manager_set_screen): Make it a NOOP. + (gtk_recent_manager_get_for_screen): Proxy for + gtk_recent_manager_get_default(). + + * gtk/gtk.symbols: + * gtk/gtkrecentmanager.h: Deprecate gtk_recent_manager_set_screen() + and gtk_recent_manager_get_for_screen(). + + * gtk/gtkmain.c: Force a synchronisation of the GtkRecentManager + singleton (if any) when reaching main loop depth of 0. + + * gtk/gtkrecentchooserdefault.c: + (gtk_recent_chooser_default_dispose): Disconnect the changed + signal only if we have a manager and we are connected to it. + + (set_recent_manager): Ditto. + + * README.in: Document the deprecations. + 2007-06-18 Matthias Clasen * gtk/gtkcellrendererspin.c: Fix some issues with refcounting diff --git a/README.in b/README.in index 800d066ce5..74efdfe2ae 100644 --- a/README.in +++ b/README.in @@ -86,6 +86,12 @@ Release notes for 2.12 documented as an abstract class, and there is little reason to instantiate it. +* The memory management of the GtkRecentManager object has been changed, + as using the screen didn't guarantee that the singleton instance was + correctly destroyed. The screen-related functions have been deprecated, + and should not be used anymore; the GtkRecentManager instance returned by + the gtk_recent_manager_get_default() function is guaranteed to be valid + for the entire lifetime of an application. Release notes for 2.10 ====================== diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 22a9267b77..b06f781efb 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3203,8 +3203,10 @@ gtk_recent_manager_get_type G_GNUC_CONST gtk_recent_manager_new gtk_recent_manager_get_items gtk_recent_manager_get_default +#ifndef GTK_DISABLE_DEPRECATED gtk_recent_manager_get_for_screen gtk_recent_manager_set_screen +#endif gtk_recent_manager_add_item gtk_recent_manager_add_full gtk_recent_manager_remove_item diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index ca9e874bc2..3da053bcee 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -61,6 +61,7 @@ #include "gtkmain.h" #include "gtkmodules.h" #include "gtkrc.h" +#include "gtkrecentmanager.h" #include "gtkselection.h" #include "gtksettings.h" #include "gtkwidget.h" @@ -1188,9 +1189,14 @@ gtk_main (void) gtk_main_loop_level--; - /* Try storing all clipboard data we have */ if (gtk_main_loop_level == 0) - _gtk_clipboard_store_all (); + { + /* Try storing all clipboard data we have */ + _gtk_clipboard_store_all (); + + /* Synchronize the recent manager singleton */ + _gtk_recent_manager_sync (); + } } guint diff --git a/gtk/gtkrecentchooserdefault.c b/gtk/gtkrecentchooserdefault.c index cf7254b87d..26a44a0234 100644 --- a/gtk/gtkrecentchooserdefault.c +++ b/gtk/gtkrecentchooserdefault.c @@ -601,7 +601,7 @@ gtk_recent_chooser_default_dispose (GObject *object) impl->recent_items = NULL; } - if (impl->manager_changed_id) + if (impl->manager && impl->manager_changed_id) { g_signal_handler_disconnect (impl->manager, impl->manager_changed_id); impl->manager_changed_id = 0; @@ -1838,8 +1838,11 @@ set_recent_manager (GtkRecentChooserDefault *impl, { if (impl->manager) { - g_signal_handler_disconnect (impl, impl->manager_changed_id); - impl->manager_changed_id = 0; + if (impl->manager_changed_id) + { + g_signal_handler_disconnect (impl, impl->manager_changed_id); + impl->manager_changed_id = 0; + } impl->manager = NULL; } @@ -1850,9 +1853,11 @@ set_recent_manager (GtkRecentChooserDefault *impl, impl->manager = gtk_recent_manager_get_default (); if (impl->manager) - impl->manager_changed_id = g_signal_connect (impl->manager, "changed", - G_CALLBACK (recent_manager_changed_cb), - impl); + { + impl->manager_changed_id = g_signal_connect (impl->manager, "changed", + G_CALLBACK (recent_manager_changed_cb), + impl); + } } GtkWidget * diff --git a/gtk/gtkrecentmanager.c b/gtk/gtkrecentmanager.c index 663e5fb4b0..8c0269947a 100644 --- a/gtk/gtkrecentmanager.c +++ b/gtk/gtkrecentmanager.c @@ -96,7 +96,6 @@ struct _GtkRecentManagerPrivate { gchar *filename; - guint is_screen_singleton : 1; guint is_dirty : 1; guint write_in_progress : 1; guint read_in_progress : 1; @@ -104,8 +103,6 @@ struct _GtkRecentManagerPrivate gint limit; gint size; - GdkScreen *screen; - GBookmarkFile *recent_items; time_t last_mtime; @@ -150,6 +147,8 @@ static void gtk_recent_info_free (GtkRecentInfo *re static guint signal_changed = 0; +static GtkRecentManager *recent_manager_singleton = NULL; + G_DEFINE_TYPE (GtkRecentManager, gtk_recent_manager, G_TYPE_OBJECT) static void @@ -286,13 +285,10 @@ gtk_recent_manager_init (GtkRecentManager *manager) priv->limit = DEFAULT_LIMIT; priv->size = 0; - priv->is_screen_singleton = FALSE; priv->is_dirty = FALSE; priv->write_in_progress = FALSE; priv->read_in_progress = FALSE; - priv->screen = NULL; - priv->filename = g_build_filename (g_get_home_dir (), GTK_RECENTLY_USED_FILE, NULL); @@ -364,7 +360,7 @@ gtk_recent_manager_finalize (GObject *object) if (priv->recent_items) g_bookmark_file_free (priv->recent_items); - + /* chain up parent's finalize method */ G_OBJECT_CLASS (gtk_recent_manager_parent_class)->finalize (object); } @@ -614,8 +610,7 @@ build_recent_items_list (GtkRecentManager *manager) * each time something inside the list changes. * * #GtkRecentManager objects are expensive: be sure to create them only when - * needed. You should use the gtk_recent_manager_new_for_screen() or the - * gtk_recent_manager_get_default() functions instead. + * needed. You should use gtk_recent_manager_get_default() instead. * * Return value: A newly created #GtkRecentManager object. * @@ -630,20 +625,21 @@ gtk_recent_manager_new (void) /** * gtk_recent_manager_get_default: * - * Gets the recent manager for the default screen. See - * gtk_recent_manager_get_for_screen(). + * Gets a unique instance of #GtkRecentManager, that you can share + * in your application without caring about memory management. The + * returned instance will be freed when you application terminates. * - * Return value: A unique #GtkRecentManager associated with the - * default screen. This recent manager is associated with the - * screen and can be used as long as the screen is open. - * Do not ref or unref it. + * Return value: A unique #GtkRecentManager. Do not ref or unref it. * * Since: 2.10 */ GtkRecentManager * gtk_recent_manager_get_default (void) { - return gtk_recent_manager_get_for_screen (gdk_screen_get_default ()); + if (G_UNLIKELY (!recent_manager_singleton)) + recent_manager_singleton = gtk_recent_manager_new (); + + return recent_manager_singleton; } /** @@ -664,70 +660,16 @@ gtk_recent_manager_get_default (void) * and can be used as long as the screen is open. Do not ref or * unref it. * + * @Deprecated: 2.12: This function has been deprecated and should + * not be used in newly written code. Calling this function is + * equivalent to calling gtk_recent_manager_get_default(). + * * Since: 2.10 */ GtkRecentManager * gtk_recent_manager_get_for_screen (GdkScreen *screen) { - GtkRecentManager *manager; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - g_return_val_if_fail (!screen->closed, NULL); - - manager = g_object_get_data (G_OBJECT (screen), "gtk-recent-manager-default"); - if (!manager) - { - GtkRecentManagerPrivate *priv; - - manager = gtk_recent_manager_new (); - gtk_recent_manager_set_screen (manager, screen); - - priv = manager->priv; - priv->is_screen_singleton = TRUE; - - g_object_set_data (G_OBJECT (screen), I_("gtk-recent-manager-default"), manager); - } - - return manager; -} - -static void -display_closed (GdkDisplay *display, - gboolean is_error, - GtkRecentManager *manager) -{ - GtkRecentManagerPrivate *priv = manager->priv; - GdkScreen *screen = priv->screen; - gboolean was_screen_singleton = priv->is_screen_singleton; - - if (was_screen_singleton) - { - g_object_set_data (G_OBJECT (screen), I_("gtk-recent-manager-default"), NULL); - priv->is_screen_singleton = FALSE; - } - - gtk_recent_manager_set_screen (manager, NULL); - - if (was_screen_singleton) - g_object_unref (manager); -} - -static void -unset_screen (GtkRecentManager *manager) -{ - GtkRecentManagerPrivate *priv = manager->priv; - GdkDisplay *display; - - if (priv->screen) - { - display = gdk_screen_get_display (priv->screen); - - g_signal_handlers_disconnect_by_func (display, - (gpointer) display_closed, - manager); - - priv->screen = NULL; - } + return gtk_recent_manager_get_default (); } /** @@ -740,30 +682,16 @@ unset_screen (GtkRecentManager *manager) * storage. * * Since: 2.10 + * + * @Deprecated: 2.12: This function has been deprecated and should + * not be used in newly written code. Calling this function has + * no effect. */ void gtk_recent_manager_set_screen (GtkRecentManager *manager, GdkScreen *screen) { - GtkRecentManagerPrivate *priv; - GdkDisplay *display; - g_return_if_fail (GTK_IS_RECENT_MANAGER (manager)); - g_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen)); - - priv = manager->priv; - - unset_screen (manager); - - if (screen) - { - display = gdk_screen_get_display (screen); - - priv->screen = screen; - - g_signal_connect (display, "closed", - G_CALLBACK (display_closed), manager); - } } /** @@ -2448,5 +2376,21 @@ gtk_recent_info_has_group (GtkRecentInfo *info, return FALSE; } +/* + * _gtk_recent_manager_sync: + * + * Private function for synchronising the recent manager singleton. + */ +void +_gtk_recent_manager_sync (void) +{ + if (recent_manager_singleton) + { + /* force a dump of the contents of the recent manager singleton */ + recent_manager_singleton->priv->is_dirty = TRUE; + gtk_recent_manager_real_changed (recent_manager_singleton); + } +} + #define __GTK_RECENT_MANAGER_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkrecentmanager.h b/gtk/gtkrecentmanager.h index 37e7121a62..b184b3fa81 100644 --- a/gtk/gtkrecentmanager.h +++ b/gtk/gtkrecentmanager.h @@ -136,10 +136,12 @@ GType gtk_recent_manager_get_type (void) G_GNUC_CONST; GtkRecentManager *gtk_recent_manager_new (void); GtkRecentManager *gtk_recent_manager_get_default (void); -GtkRecentManager *gtk_recent_manager_get_for_screen (GdkScreen *screen); +#ifndef GTK_DISABLE_DEPRECATED +GtkRecentManager *gtk_recent_manager_get_for_screen (GdkScreen *screen); void gtk_recent_manager_set_screen (GtkRecentManager *manager, GdkScreen *screen); +#endif gboolean gtk_recent_manager_add_item (GtkRecentManager *manager, const gchar *uri); @@ -203,6 +205,9 @@ gboolean gtk_recent_info_exists (GtkRecentInfo *info gboolean gtk_recent_info_match (GtkRecentInfo *info_a, GtkRecentInfo *info_b); +/* private */ +void _gtk_recent_manager_sync (void); + G_END_DECLS #endif /* __GTK_RECENT_MANAGER_H__ */