changeset 12498:a2de852981c1

[gaim-migrate @ 14810] SF Patch #1380806 from charkins "leave docklet loaded when notification area is not present" "From the summary, this sounds weird, but I think its better behavior. This really only effects some odd corner cases. The existing behavior is that the docklet plugin unloads itself after 10 seconds if the tray icon isn't created. The behavior with this patch is that there is a 3 second timeout (this is necessary to avoid race condition when restoring the gtkblist's visibility state on startup). After this timeout, the docklet plugin stays loaded waiting for a notification to appear, but is essentially non-functional. In the typical scenario, this patch doesn't effect the behavior. Here are some examples of where it does matter: 1) If gaim is closed with the buddy list hidden to the docklet, then gaim is started again without a notification area, the buddy list doesn't show up for 10 seconds (the time it takes for the docklet to timeout). This patch would reduce this to 3 seconds. 2) If the user removes the notification area from their panel, maybe to remove it from one panel and add it to a different panel, but doesn't add a new one back within 10 seconds, the current behavior would cause the docklet plugin to be unloaded. With this patch, the tray icon would automatically be added to the new notification area when it becomes available. 3) The gnome-panel dies and is not restarted within 10 seconds. Similar to #2. (There was a bug filed for this, but can't find it right now). My main concern was that it could be confusing to the user if they enable the docklet plugin, then 10 seconds later it gets disabled without any notification. This patch doesn't add any notification, but leaves the plugin running so it will automatically use a notification area when one becomes available. I also removed an unused parameter from docklet_remove() and changed the plugin description slightly to reflect the change in queuing/notification. Not sure how clear this is, so bug me on #gaim if you have any questions. --charkins" I made a few changes to this patch, but nothing terribly significant... committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Fri, 16 Dec 2005 09:16:14 +0000
parents 202ce52b77a9
children 3992105b8df5
files plugins/docklet/docklet-win32.c plugins/docklet/docklet-x11.c plugins/docklet/docklet.c plugins/docklet/docklet.h
diffstat 4 files changed, 41 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/docklet/docklet-win32.c	Fri Dec 16 09:02:17 2005 +0000
+++ b/plugins/docklet/docklet-win32.c	Fri Dec 16 09:16:14 2005 +0000
@@ -241,7 +241,7 @@
 	gaim_signals_disconnect_by_handle(&handle);
 	systray_remove_nid();
 	DestroyWindow(systray_hwnd);
-	docklet_remove(TRUE);
+	docklet_remove();
 }
 
 static struct docklet_ui_ops wgaim_tray_ops =
--- a/plugins/docklet/docklet-x11.c	Fri Dec 16 09:02:17 2005 +0000
+++ b/plugins/docklet/docklet-x11.c	Fri Dec 16 09:16:14 2005 +0000
@@ -33,7 +33,7 @@
 #include "eggtrayicon.h"
 #include "docklet.h"
 
-#define EMBED_TIMEOUT 10000
+#define EMBED_TIMEOUT 3000
 
 /* globals */
 static EggTrayIcon *docklet = NULL;
@@ -60,6 +60,7 @@
 	
 	g_source_remove(embed_timeout);
 	embed_timeout = 0;
+	docklet_embedded();
 }
 
 static void
@@ -67,7 +68,7 @@
 {
 	gaim_debug(GAIM_DEBUG_INFO, "tray icon", "destroyed\n");
 
-	docklet_remove(TRUE);
+	docklet_remove();
 
 	g_object_unref(G_OBJECT(docklet));
 	docklet = NULL;
@@ -206,7 +207,7 @@
 {
 	g_return_if_fail(docklet != NULL);
 
-	docklet_remove(GTK_WIDGET_VISIBLE(docklet));
+	docklet_remove();
 
 	g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_x11_destroyed_cb), NULL);
 	gtk_widget_destroy(GTK_WIDGET(docklet));
@@ -226,7 +227,13 @@
 static gboolean
 docklet_x11_embed_timeout_cb()
 {
-	docklet_unload();
+	/* 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.
+	 */
+	gaim_debug_info("tray icon", "failed to embed within timeout\n");
+	docklet_remove();
 
 	return FALSE;
 }
@@ -262,6 +269,14 @@
 
 	/* ref the docklet before we bandy it about the place */
 	g_object_ref(G_OBJECT(docklet));
+
+	/* 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.
+	 */
 	docklet_embedded();
 	embed_timeout = g_timeout_add(EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL);
 
--- a/plugins/docklet/docklet.c	Fri Dec 16 09:02:17 2005 +0000
+++ b/plugins/docklet/docklet.c	Fri Dec 16 09:16:14 2005 +0000
@@ -58,6 +58,7 @@
 static DockletStatus status = DOCKLET_STATUS_OFFLINE;
 static gboolean enable_join_chat = FALSE;
 static guint docklet_blinking_timer = 0;
+static gboolean visibility_manager = FALSE;
 
 /**************************************************************************
  * docklet status and utility functions
@@ -169,7 +170,7 @@
 
 		g_list_free(convs);
 
-	} else if(ui_ops->set_tooltip) {
+	} else if (ui_ops->set_tooltip) {
 		ui_ops->set_tooltip(NULL);
 	}
 
@@ -184,7 +185,7 @@
 	 *     5) AWAY_PENDING
 	 *     6) CONNECTING
 	 */
-	for(l = gaim_accounts_get_all(); l!=NULL; l=l->next) {
+	for(l = gaim_accounts_get_all(); l != NULL; l = l->next) {
 		DockletStatus tmpstatus = DOCKLET_STATUS_OFFLINE;
 
 		GaimAccount *account = (GaimAccount*)l->data;
@@ -243,7 +244,7 @@
 	GList *c = NULL;
 	c = gaim_connections_get_all();
 
-	while(c!=NULL) {
+	while(c != NULL) {
 		GaimConnection *gc = c->data;
 		if (GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info != NULL)
 			return TRUE;
@@ -447,7 +448,7 @@
 {
 	switch (button_type) {
 		case 1:
-			if (status==DOCKLET_STATUS_ONLINE_PENDING || status==DOCKLET_STATUS_AWAY_PENDING) {
+			if (status == DOCKLET_STATUS_ONLINE_PENDING || status == DOCKLET_STATUS_AWAY_PENDING) {
 				GList *l = get_pending_list(1);
 				if (l != NULL) {
 					gaim_gtkconv_present_conversation((GaimConversation *)l->data);
@@ -466,16 +467,22 @@
 void
 docklet_embedded()
 {
-	gaim_gtk_blist_visibility_manager_add();
+	if (!visibility_manager) {
+		gaim_gtk_blist_visibility_manager_add();
+		visibility_manager = TRUE;
+	}
 	docklet_update_status();
 	if (ui_ops && ui_ops->update_icon)
 		ui_ops->update_icon(status);
 }
 
 void
-docklet_remove(gboolean visible)
+docklet_remove()
 {
-	gaim_gtk_blist_visibility_manager_remove();
+	if (visibility_manager) {
+		gaim_gtk_blist_visibility_manager_remove();
+		visibility_manager = FALSE;
+	}
 }
 
 void
@@ -610,12 +617,13 @@
 	                                                  /**  summary        */
 	N_("Displays an icon for Gaim in the system tray."),
 	                                                  /**  description    */
-	N_("Displays a system tray icon (in GNOME, KDE or Windows for example) "
+	N_("Displays a system tray icon (in GNOME, KDE, or Windows for example) "
 	   "to show the current status of Gaim, allow fast access to commonly "
-	   "used functions, and to toggle display of the buddy list or login "
-	   "window. Also allows messages to be queued until the icon is "
-	   "clicked, similar to ICQ."),
-	"Robert McQueen <robot101@debian.org>",           /**< author         */
+	   "used functions, and to toggle display of the buddy list. "
+	   "Also provides options to blink for unread messages."),
+	                                                  /** author          */
+	"Robert McQueen <robot101@debian.org>"
+	"\n\t\t\tCasey Harkins <charkins@users.sf.net>",
 	GAIM_WEBSITE,                                     /**< homepage       */
 
 	plugin_load,                                      /**< load           */
--- a/plugins/docklet/docklet.h	Fri Dec 16 09:02:17 2005 +0000
+++ b/plugins/docklet/docklet.h	Fri Dec 16 09:16:14 2005 +0000
@@ -51,7 +51,7 @@
 /* functions in docklet.c */
 void docklet_clicked(int);
 void docklet_embedded(void);
-void docklet_remove(gboolean);
+void docklet_remove(void);
 void docklet_set_ui_ops(struct docklet_ui_ops *);
 void docklet_unload(void);