# HG changeset patch # User Christian Hammond # Date 1042076884 0 # Node ID e252238f99dfa27445ebced6687211501c8fb245 # Parent 43864b6a28a2a8dbda713db335c61ab420e79d14 [gaim-migrate @ 4512] commit message: wait don't apply that bloody gedit there we go fixed it patch to fix docklet crash on unload, thanks to Nicol?s Lichtmaier for identifying the problem and fix, and Kristian Rietveld for implementing it also implements a blinking icon when messages are pending & credits people correctly in ChangeLog and for the record, it was Nicol?s Lichtmaier who did the icon factory stuff last night * Robot101 hops up and down patchy merge merge! < ChipX86> fine. yay =) committer: Tailor Script diff -r 43864b6a28a2 -r e252238f99df ChangeLog --- 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) diff -r 43864b6a28a2 -r e252238f99df plugins/docklet/docklet.c --- 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 @@ -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)); diff -r 43864b6a28a2 -r e252238f99df plugins/docklet/eggtrayicon.c --- 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