# HG changeset patch # User Elliott Sales de Andrade # Date 1292307275 0 # Node ID 7fb5e60fd919f6f5e5a8fdb123d762cd7c147ad3 # Parent fd43277108be1383adef1df2f68d853ba89db750 Re-implement the embedding timeout, so that the buddy list doesn't seem to disappear on startup entirely if you don't have a notification area. Fixes #12129. diff -r fd43277108be -r 7fb5e60fd919 pidgin/gtkdocklet-gtk.c --- a/pidgin/gtkdocklet-gtk.c Sun Dec 12 11:32:07 2010 +0000 +++ b/pidgin/gtkdocklet-gtk.c Tue Dec 14 06:14:35 2010 +0000 @@ -26,8 +26,74 @@ #include "pidginstock.h" #include "gtkdocklet.h" +#define SHORT_EMBED_TIMEOUT 5 +#define LONG_EMBED_TIMEOUT 15 + /* globals */ -GtkStatusIcon *docklet = NULL; +static GtkStatusIcon *docklet = NULL; +static guint embed_timeout = 0; + +/* protos */ +static void docklet_gtk_status_create(gboolean); + +static gboolean +docklet_gtk_recreate_cb(gpointer data) +{ + docklet_gtk_status_create(TRUE); + + return FALSE; +} + +static gboolean +docklet_gtk_embed_timeout_cb(gpointer data) +{ + /* The docklet was not embedded within the timeout. + * Remove it as a visibility manager, but leave the plugin + * loaded so that it can embed automatically if/when a notification + * area becomes available. + */ + purple_debug_info("docklet", "failed to embed within timeout\n"); + pidgin_docklet_remove(); + + embed_timeout = 0; + return FALSE; +} + +static gboolean +docklet_gtk_embedded_cb(GtkWidget *widget, gpointer data) +{ + if (embed_timeout) { + purple_timeout_remove(embed_timeout); + embed_timeout = 0; + } + + if (gtk_status_icon_is_embedded(docklet)) { + purple_debug_info("docklet", "embedded\n"); + + pidgin_docklet_embedded(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", TRUE); + } else { + purple_debug_info("docklet", "detached\n"); + + pidgin_docklet_remove(); + purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded", FALSE); + } + + return TRUE; +} + +static void +docklet_gtk_destroyed_cb(GtkWidget *widget, gpointer data) +{ + purple_debug_info("docklet", "destroyed\n"); + + pidgin_docklet_remove(); + + g_object_unref(G_OBJECT(docklet)); + docklet = NULL; + + g_idle_add(docklet_gtk_recreate_cb, NULL); +} static void docklet_gtk_status_activated_cb(GtkStatusIcon *status_icon, gpointer user_data) @@ -114,7 +180,13 @@ pidgin_docklet_remove(); + if (embed_timeout) { + purple_timeout_remove(embed_timeout); + embed_timeout = 0; + } + gtk_status_icon_set_visible(docklet, FALSE); + g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_gtk_destroyed_cb), NULL); g_object_unref(G_OBJECT(docklet)); docklet = NULL; @@ -137,9 +209,33 @@ g_signal_connect(G_OBJECT(docklet), "activate", G_CALLBACK(docklet_gtk_status_activated_cb), NULL); g_signal_connect(G_OBJECT(docklet), "popup-menu", G_CALLBACK(docklet_gtk_status_clicked_cb), NULL); + g_signal_connect(G_OBJECT(docklet), "notify::embedded", G_CALLBACK(docklet_gtk_embedded_cb), NULL); + g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_gtk_destroyed_cb), NULL); - pidgin_docklet_embedded(); gtk_status_icon_set_visible(docklet, TRUE); + + /* This is a hack to avoid a race condition between the docklet getting + * embedded in the notification area and the gtkblist restoring its + * previous visibility state. If the docklet does not get embedded within + * the timeout, it will be removed as a visibility manager until it does + * get embedded. Ideally, we would only call docklet_embedded() when the + * icon was actually embedded. This only happens when the docklet is first + * created, not when being recreated. + * + * The gtk docklet tracks whether it successfully embedded in a pref and + * allows for a longer timeout period if it successfully embedded the last + * time it was run. This should hopefully solve problems with the buddy + * list not properly starting hidden when Pidgin is started on login. + */ + if (!recreate) { + pidgin_docklet_embedded(); + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/gtk/embedded")) { + embed_timeout = purple_timeout_add_seconds(LONG_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); + } else { + embed_timeout = purple_timeout_add_seconds(SHORT_EMBED_TIMEOUT, docklet_gtk_embed_timeout_cb, NULL); + } + } + purple_debug_info("docklet", "GTK+ created\n"); }