changeset 4261:e252238f99df

[gaim-migrate @ 4512] <Robot101> commit message: <Robot101> wait <Robot101> don't apply that <Robot101> bloody gedit <Robot101> there we go <Robot101> fixed it <Robot101> patch to fix docklet crash on unload, thanks to Nicol?s Lichtmaier for identifying the problem and fix, and Kristian Rietveld for implementing it <Robot101> also implements a blinking icon when messages are pending & credits people correctly in ChangeLog <Robot101> and for the record, it was Nicol?s Lichtmaier who did the icon factory stuff last night * Robot101 hops up and down <Robot101> patchy merge merge! < ChipX86> fine. <Robot101> yay =) committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Thu, 09 Jan 2003 01:48:04 +0000
parents 43864b6a28a2
children 7103653dd34e
files ChangeLog plugins/docklet/docklet.c plugins/docklet/eggtrayicon.c
diffstat 3 files changed, 112 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jan 09 01:32:54 2003 +0000
+++ b/ChangeLog	Thu Jan 09 01:48:04 2003 +0000
@@ -16,9 +16,11 @@
 	  Robert McQueen)
 
 	Plugins:
-	* Docklet plugin--replaces the old GNOME applet.  You'll need the
-	  Panel Notification Area applet for GNOME 2, or the kicker for
-	  KDE 3.1. (Thanks, Robert McQueen, Ari Pollak, Patrick Aussems)
+	* Tray icon plugin--replaces the old GNOME applet. You'll need 
+	  the panel Notification Area applet (aka system-tray-applet) 
+	  for GNOME 2, or the Kicker for KDE 3.1. (Thanks, Robert 
+	  McQueen, Nicolás Lichtmaier, Kristian Rietveld, Ari Pollak &
+	  Patrick Aussems)
 	* Added GAIM::remove_event_handler and made set_info short
 	  circuitable in perl. (Thanks, Ryan McCabe)
 	* event_del_conversation for plugins. (Thanks, Bill Tompkins)
--- a/plugins/docklet/docklet.c	Thu Jan 09 01:32:54 2003 +0000
+++ b/plugins/docklet/docklet.c	Thu Jan 09 01:48:04 2003 +0000
@@ -20,13 +20,12 @@
  */
 
 /* todo (in order of importance):
-    - don't crash when the plugin gets unloaded (may be a libegg bug,
-       see #101467 in gnome bugzilla)
-    - handle and update tooltips to show your current accounts ?
+    - check removing the icon factory actually frees the icons
+    - unify the queue so we can have a global away without the dialog
+    - handle and update tooltips to show your current accounts/queued messages?
+    - show a count of queued messages in the unified queue
     - dernyi's account status menu in the right click
-    - store icons in gtk2 stock icon thing (needs doing for the whole prog)
-    - optional pop up notices when GNOME2's system-tray-applet supports it
-    - support blinking the icon when messages are pending */
+    - optional pop up notices when GNOME2's system-tray-applet supports it */
 
 /* includes */
 #include <gtk/gtk.h>
@@ -55,10 +54,11 @@
 
 /* globals */
 static EggTrayIcon *docklet = NULL;
-static GtkWidget *icon;
+static GtkWidget *image = NULL;
+static GtkIconFactory *icon_factory = NULL;
 static enum docklet_status status;
-static GtkIconFactory *icon_factory = NULL;
-static GtkIconSize icon_size;
+static enum docklet_status icon;
+static guint blinker = 0;
 
 static void docklet_toggle_mute(GtkWidget *toggle, void *data) {
 	mute_sounds = GTK_CHECK_MENU_ITEM(toggle)->active;
@@ -188,11 +188,10 @@
 	}
 }
 
-static void docklet_update_icon()
-{
+static void docklet_update_icon() {
 	const gchar *icon_name = NULL;
 
-	switch (status) {
+	switch (icon) {
 		case offline:
 			icon_name = "gaim-docklet-offline";
 			break;
@@ -214,9 +213,36 @@
 			break;
 	}
 
-	gtk_image_set_from_stock(GTK_IMAGE(icon), icon_name, icon_size);
+	gtk_image_set_from_stock(GTK_IMAGE(image), icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+
+	debug_printf("Tray Icon: updated icon to '%s'\n", icon_name);
+}
 
-	debug_printf("Tray Icon: updated icon to '%s'\n",icon_name);
+static gboolean docklet_blink_icon() {
+	if (status == online_pending) {
+		if (status == icon) {
+			/* last icon was the right one... let's change it */
+			icon = online;
+		} else {
+			/* last icon was the wrong one, change it back */
+			icon = online_pending;
+		}
+	} else if (status == away_pending) {
+		if (status == icon) {
+			/* last icon was the right one... let's change it */
+			icon = away;
+		} else {
+			/* last icon was the wrong one, change it back */
+			icon = away_pending;
+		}
+	} else {
+		/* no messages, stop blinking */
+		return FALSE;
+	}
+
+	docklet_update_icon();
+
+	return TRUE; /* keep blinking */
 }
 
 static gboolean docklet_update_status() {
@@ -246,8 +272,15 @@
 		}
 	}
 
+	/* update the icon if we changed status */
 	if (status != oldstatus) {
+		icon = status;
 		docklet_update_icon();
+
+		/* and schedule the blinker function if messages are pending */
+		if (status == online_pending || status == away_pending) {
+			blinker = g_timeout_add(500, docklet_blink_icon, NULL);
+		}
 	}
 
 	return FALSE; /* for when we're called by the glib idle handler */
@@ -265,6 +298,11 @@
 
 	docklet_flush_queue();
 
+	if (blinker) {
+		g_source_remove(blinker);
+		blinker = 0;
+	}
+
 	g_object_unref(G_OBJECT(docklet));
 	docklet = NULL;
 
@@ -284,13 +322,13 @@
 
 	docklet = egg_tray_icon_new("Gaim");
 	box = gtk_event_box_new();
-	icon = gtk_image_new();
+	image = gtk_image_new();
 
 	g_signal_connect(G_OBJECT(docklet), "embedded", G_CALLBACK(docklet_embedded), NULL);
 	g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_destroyed), NULL);
 	g_signal_connect(G_OBJECT(box), "button-press-event", G_CALLBACK(docklet_clicked), NULL);
 
-	gtk_container_add(GTK_CONTAINER(box), icon);
+	gtk_container_add(GTK_CONTAINER(box), image);
 	gtk_container_add(GTK_CONTAINER(docklet), box);
 	gtk_widget_show_all(GTK_WIDGET(docklet));
 
@@ -365,13 +403,9 @@
 	docklet_register_icon("gaim-docklet-msgpend", "msgpend.png");
 
 	gtk_icon_factory_add_default(icon_factory);
-	
-	icon_size = gtk_icon_size_register("gaim-docklet-size", 24, 24);
 }
 
 static void docklet_unregister_icon_factory() {
-	/* does this actually free anything? it's a moot point seeing as
-	   unloading the docklet crashes gaim, but it needs to be checked */
 	gtk_icon_factory_remove_default(icon_factory);
 }
 
@@ -401,6 +435,11 @@
 
 	docklet_flush_queue();
 
+	if (blinker) {
+		g_source_remove(blinker);
+		blinker = 0;
+	}
+
 	g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_destroyed), NULL);
 	gtk_widget_destroy(GTK_WIDGET(docklet));
 
--- a/plugins/docklet/eggtrayicon.c	Thu Jan 09 01:32:54 2003 +0000
+++ b/plugins/docklet/eggtrayicon.c	Thu Jan 09 01:48:04 2003 +0000
@@ -31,6 +31,8 @@
 static void egg_tray_icon_init (EggTrayIcon *icon);
 static void egg_tray_icon_class_init (EggTrayIconClass *klass);
 
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
 static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
 
 GType
@@ -57,6 +59,10 @@
 
       our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0);
     }
+  else if (parent_class == NULL) {
+    /* we're reheating the old class from a previous instance -  engage ugly hack =( */
+    egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type));
+  }
 
   return our_type;
 }
@@ -72,7 +78,11 @@
 static void
 egg_tray_icon_class_init (EggTrayIconClass *klass)
 {
+  GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
   parent_class = g_type_class_peek_parent (klass);
+
+  widget_class->unrealize = egg_tray_icon_unrealize;
 }
 
 static GdkFilterReturn
@@ -99,6 +109,38 @@
 }
 
 static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+  EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+  GdkWindow *root_window;
+
+  if (icon->manager_window != None)
+    {
+      GdkWindow *gdkwin;
+
+#if HAVE_GTK_MULTIHEAD
+      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+                                              icon->manager_window);
+#else
+      gdkwin = gdk_window_lookup (icon->manager_window);
+#endif
+
+      gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+    }
+
+#if HAVE_GTK_MULTIHEAD
+  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+#else
+  root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
+#endif
+
+  gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
 egg_tray_icon_send_manager_message (EggTrayIcon *icon,
 				    long         message,
 				    Window       window,
@@ -158,7 +200,7 @@
       GdkWindow *gdkwin;
 
 #if HAVE_GTK_MULTIHEAD
-      gdkwin = gdk_window_lookup_for_display (display,
+      gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
 					      icon->manager_window);
 #else
       gdkwin = gdk_window_lookup (icon->manager_window);
@@ -210,6 +252,10 @@
   gtk_window_set_title (GTK_WINDOW (icon), name);
 
 #if HAVE_GTK_MULTIHEAD
+  /* FIXME: this code does not compile, screen is undefined. Now try
+   * getting the GdkScreen from xscreen (:. Dunno how to solve this
+   * (there is prolly some easy way I cant think of right now)
+   */
   gtk_plug_construct_for_display (GTK_PLUG (icon),
 				  gdk_screen_get_display (screen), 0);
 #else
@@ -235,7 +281,7 @@
   egg_tray_icon_update_manager_window (icon);
 
 #if HAVE_GTK_MULTIHEAD
-  root_window = gdk_screen_get_root_window (screen);
+  root_window = gdk_screen_get_root_window (gtk_widget_get_screen (screen));
 #else
   root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ());
 #endif