diff -Nru pidgin-libnotify-0.14/debian/changelog pidgin-libnotify-0.14/debian/changelog --- pidgin-libnotify-0.14/debian/changelog 2012-08-31 08:37:33.000000000 -0400 +++ pidgin-libnotify-0.14/debian/changelog 2012-11-12 13:54:48.000000000 -0500 @@ -1,3 +1,18 @@ +pidgin-libnotify (0.14-4ubuntu12) quantal; urgency=low + + * libmessaging-menu support (LP: #1040259) + * debian/control: + - drop indicate build-dep + - add libmessaging-menu-dev + * debian/patches/ubuntu_notify_support.patch: + - Split out notify changes from messaging-menu changes (was combined + in indicate.patch) + - Merged libnotify-0.7.patch + * debian/patches/messaging_menu.patch: + - messaging-menu support. + + -- Jason Conti Sun, 21 Oct 2012 15:17:58 -0400 + pidgin-libnotify (0.14-4ubuntu11) quantal; urgency=low * debian/control: Drop indicator-status-provider-pidgin, since this is diff -Nru pidgin-libnotify-0.14/debian/control pidgin-libnotify-0.14/debian/control --- pidgin-libnotify-0.14/debian/control 2012-08-31 08:36:38.000000000 -0400 +++ pidgin-libnotify-0.14/debian/control 2012-10-21 15:43:47.000000000 -0400 @@ -5,7 +5,7 @@ XSBC-Original-Maintainer: Varun Hiremath Uploaders: Torsten Werner Build-Depends: debhelper (>= 5), cdbs, intltool, pkg-config, libnotify-dev (>= 0.7), - libglib2.0-dev, libgtk2.0-dev, libtool, pidgin-dev, libindicate-dev (>= 0.6.90), libindicate-gtk-dev (>= 0.6.90), + libglib2.0-dev, libgtk2.0-dev, libtool, pidgin-dev, libmessaging-menu-dev (>= 12.10.4), dh-autoreconf Standards-Version: 3.8.0 Homepage: http://gaim-libnotify.sourceforge.net diff -Nru pidgin-libnotify-0.14/debian/patches/force-load.patch pidgin-libnotify-0.14/debian/patches/force-load.patch --- pidgin-libnotify-0.14/debian/patches/force-load.patch 2012-02-10 14:04:30.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/force-load.patch 2012-10-21 15:37:15.000000000 -0400 @@ -1,11 +1,9 @@ === modified file 'src/pidgin-libnotify.c' -Index: pidgin-libnotify/src/pidgin-libnotify.c -=================================================================== ---- pidgin-libnotify.orig/src/pidgin-libnotify.c 2011-08-10 22:52:51.793663042 -0400 -+++ pidgin-libnotify/src/pidgin-libnotify.c 2011-08-10 22:53:21.483706587 -0400 -@@ -1151,6 +1151,20 @@ - return FALSE; - } +--- a/src/pidgin-libnotify.c ++++ b/src/pidgin-libnotify.c +@@ -568,6 +568,20 @@ + &prefs_info /* prefs info */ + }; +static gboolean +force_load_once (gpointer data) @@ -22,9 +20,9 @@ +} + static void - notify_check_caps_helper (gpointer data, gpointer user_data) + init_plugin (PurplePlugin *plugin) { -@@ -1371,6 +1385,9 @@ +@@ -585,6 +599,9 @@ purple_prefs_add_bool ("/plugins/gtk/libnotify/signon", TRUE); purple_prefs_add_bool ("/plugins/gtk/libnotify/signoff", FALSE); purple_prefs_add_bool ("/plugins/gtk/libnotify/only_available", FALSE); diff -Nru pidgin-libnotify-0.14/debian/patches/indicate.patch pidgin-libnotify-0.14/debian/patches/indicate.patch --- pidgin-libnotify-0.14/debian/patches/indicate.patch 2012-02-10 14:08:34.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/indicate.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,1205 +0,0 @@ -=== modified file 'configure.ac' -Index: pidgin-libnotify/configure.ac -=================================================================== ---- pidgin-libnotify.orig/configure.ac 2012-02-10 14:04:30.138001000 -0500 -+++ pidgin-libnotify/configure.ac 2012-02-10 14:08:27.593219142 -0500 -@@ -74,6 +74,15 @@ - AC_SUBST(LIBNOTIFY_LIBS) - - # -+# Check for libindicate -+# -+ -+PKG_CHECK_MODULES(LIBINDICATE, indicate-0.7 >= 0.6.90 indicate-gtk-0.7 >= 0.6.90) -+ -+AC_SUBST(LIBINDICATE_CFLAGS) -+AC_SUBST(LIBINDICATE_LIBS) -+ -+# - # Check for GTK+ - # - PKG_CHECK_MODULES(GTK, gtk+-2.0) -Index: pidgin-libnotify/src/Makefile.am -=================================================================== ---- pidgin-libnotify.orig/src/Makefile.am 2012-02-10 14:04:30.138001000 -0500 -+++ pidgin-libnotify/src/Makefile.am 2012-02-10 14:04:30.138001000 -0500 -@@ -10,7 +10,7 @@ - pidgin-libnotify.c \ - gln_intl.h - --pidgin_libnotify_la_LIBADD = $(LIBNOTIFY_LIBS) $(DBUS_LIBS) $(GTK_LIBS) -+pidgin_libnotify_la_LIBADD = $(LIBINDICATE_LIBS) $(LIBNOTIFY_LIBS) $(DBUS_LIBS) $(GTK_LIBS) - - endif - -@@ -24,6 +24,7 @@ - $(PIDGIN_CFLAGS) \ - $(LIBPURPLE_CFLAGS) \ - $(LIBNOTIFY_CFLAGS) \ -+ $(LIBINDICATE_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GTK_CFLAGS) - -Index: pidgin-libnotify/src/pidgin-libnotify.c -=================================================================== ---- pidgin-libnotify.orig/src/pidgin-libnotify.c 2012-02-10 14:04:30.138001000 -0500 -+++ pidgin-libnotify/src/pidgin-libnotify.c 2012-02-10 14:07:50.273217913 -0500 -@@ -35,15 +35,53 @@ - - /* for pidgin_create_prpl_icon */ - #include -+#include - - #include -+#include -+#include -+#include -+#include - - #include - - #define PLUGIN_ID "pidgin-libnotify" - -+#ifdef G_LOG_DOMAIN -+#undef G_LOG_DOMAIN -+#endif -+#define G_LOG_DOMAIN "pidgin-libnotify-plugin" -+ -+#define PIDGIN_DESKTOP_FILE "/usr/share/applications/pidgin.desktop" -+#define BLACKLIST_FILENAME "pidgin-libnotify" -+#define BLACKLIST_DIR "indicators/messages/applications-blacklist" -+ -+/* Prototypes */ -+static void indicate_chat_nick (PurpleAccount *account, const gchar *sender, const gchar *message, PurpleConversation *conv, gpointer data); -+static void notify_new_message_cb (PurpleAccount *account, const gchar *sender, const gchar *message, int flags, gpointer data); -+ -+/* Structs */ -+typedef struct _indicate_chat_nick_idle_t indicate_chat_nick_idle_t; -+struct _indicate_chat_nick_idle_t { -+ PurpleAccount * account; -+ gchar * sender; -+ gchar * message; -+}; -+ -+/* Globals */ - static GHashTable *buddy_hash; - -+static gboolean notify_supports_actions = FALSE; -+static gboolean notify_supports_append = FALSE; -+static gboolean notify_supports_truncation = FALSE; -+ -+static gboolean visibility_managed = FALSE; -+ -+static IndicateServer * indicate_server = NULL; -+static guint never_loaded = 0; -+ -+static void conv_delete_cb (PurpleConversation * conv, void * data); -+ - static PurplePluginPrefFrame * - get_plugin_pref_frame (PurplePlugin *plugin) - { -@@ -82,6 +120,11 @@ - _("Only when available")); - purple_plugin_pref_frame_add (frame, ppref); - -+ ppref = purple_plugin_pref_new_with_name_and_label ( -+ "/plugins/gtk/libnotify/blocked_nicks", -+ _("Names to remove notifications for")); -+ purple_plugin_pref_frame_add (frame, ppref); -+ - return frame; - } - -@@ -127,7 +170,9 @@ - return; - - just_signed_on_accounts = g_list_prepend (just_signed_on_accounts, account); -- g_timeout_add (5000, event_connection_throttle_cb, (gpointer)account); -+ g_timeout_add_seconds (15, event_connection_throttle_cb, (gpointer)account); -+ -+ return; - } - - /* do NOT g_free() the string returned by this function */ -@@ -154,7 +199,6 @@ - data = purple_buddy_icon_get_data (buddy_icon, &len); - - loader = gdk_pixbuf_loader_new (); -- gdk_pixbuf_loader_set_size (loader, 48, 48); - gdk_pixbuf_loader_write (loader, data, len, NULL); - gdk_pixbuf_loader_close (loader, NULL); - -@@ -169,6 +213,97 @@ - return icon; - } - -+/* -+ * This takes a pixbuf that we want to send to the notify server, and -+ * transforms it to the desired dimensions suitable for a notification. -+ * We scale the pixbuf down to size * size (square), but preserve the -+ * original aspect ratio and fill in the edges with transparent pixels -+ * if the original pixbuf was not square. -+ */ -+static GdkPixbuf * -+normalize_icon (GdkPixbuf *icon, gint size) -+{ -+ gint w, h; -+ int dest_x, dest_y; -+ gdouble max_edge; -+ gint new_width, new_height; -+ GdkPixbuf *scaled_icon; -+ GdkPixbuf *new_icon; -+ -+ w = gdk_pixbuf_get_width (icon); -+ h = gdk_pixbuf_get_height (icon); -+ -+ dest_x = dest_y = 0; -+ -+ max_edge = MAX (w, h); -+ -+ new_width = size * (w / max_edge); -+ new_height = size * (h / max_edge); -+ -+ /* Scale the image down, preserving the aspect ratio */ -+ scaled_icon = gdk_pixbuf_scale_simple (icon, -+ new_width, -+ new_height, -+ GDK_INTERP_HYPER); -+ -+ g_object_unref (icon); -+ -+ /* Create a square pixbuf with an alpha channel, dimensions size * size */ -+ new_icon = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (scaled_icon), -+ TRUE, -+ gdk_pixbuf_get_bits_per_sample (scaled_icon), -+ size, size); -+ -+ /* Clear the pixbuf so it is transparent */ -+ gdk_pixbuf_fill (new_icon, 0x00000000); -+ -+ /* Center the aspect ratio preseved pixbuf in the square pixbuf */ -+ if (new_width > new_height) { -+ dest_y = (new_width - new_height) / 2; -+ } else if (new_height > new_width) { -+ dest_x = (new_height - new_width) / 2; -+ } -+ -+ /* Copy from the aspect ratio-preserved scaled pixbuf into the -+ * new pixbuf, at a centered position. */ -+ gdk_pixbuf_copy_area (scaled_icon, -+ 0, 0, -+ gdk_pixbuf_get_width (scaled_icon), -+ gdk_pixbuf_get_height (scaled_icon), -+ new_icon, -+ dest_x, dest_y); -+ -+ g_object_unref (scaled_icon); -+ -+ return new_icon; -+} -+ -+/* Check the name against the static list of black listed -+ names that we're looking out for. These shouldn't result -+ in either notifications or indicators. */ -+static gboolean -+name_blacklisted (PurpleAccount * account, const gchar * name) -+{ -+ if (account != NULL) { -+ const gchar * username = purple_account_get_username(account); -+ gchar ** userparts = g_strsplit(username, "@", 2); -+ if (g_strcmp0(name, userparts[1]) == 0) { -+ g_strfreev(userparts); -+ return TRUE; -+ } -+ g_strfreev(userparts); -+ } -+ -+ GList * blacklist = purple_prefs_get_string_list("/plugins/gtk/libnotify/blocked_nicks"); -+ GList * pnt; -+ for (pnt = blacklist; pnt != NULL; pnt = g_list_next(pnt)) { -+ if (g_strcmp0(name, (gchar *)pnt->data) == 0) { -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ - static void - action_cb (NotifyNotification *notification, - gchar *action, gpointer user_data) -@@ -177,9 +312,9 @@ - PurpleConversation *conv = NULL; - - purple_debug_info (PLUGIN_ID, "action_cb(), " -- "notification: 0x%x, action: '%s'", notification, action); -+ "notification: 0x%x, action: '%s'", GPOINTER_TO_UINT(notification), action); - -- buddy = (PurpleBuddy *)g_object_get_data (G_OBJECT(notification), "buddy"); -+ buddy = (PurpleBuddy *)user_data; - - if (!buddy) { - purple_debug_warning (PLUGIN_ID, "Got no buddy!"); -@@ -199,13 +334,25 @@ - } - - static gboolean --closed_cb (NotifyNotification *notification) -+notification_list_closed_cb (NotifyNotification *notification, PurpleConversation * conv) - { -- PurpleContact *contact; -+ purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", GPOINTER_TO_UINT(notification)); - -- purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", notification); -+ if (conv != NULL) { -+ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); -+ notifylist = g_list_remove(notifylist, notification); -+ purple_conversation_set_data(conv, "notification-list", notifylist); -+ } -+ g_object_unref(notification); -+ -+ return FALSE; -+} -+ -+static gboolean -+closed_cb (NotifyNotification *notification, PurpleContact * contact) -+{ -+ purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", GPOINTER_TO_UINT(notification)); - -- contact = (PurpleContact *)g_object_get_data (G_OBJECT(notification), "contact"); - if (contact) - g_hash_table_remove (buddy_hash, contact); - -@@ -218,11 +365,12 @@ - * num_chars is utf-8 characters */ - static gchar * - truncate_escape_string (const gchar *str, -- int num_chars) -+ int num_chars, -+ gboolean escape) - { - gchar *escaped_str; - -- if (g_utf8_strlen (str, num_chars*2+1) > num_chars) { -+ if (!notify_supports_truncation && g_utf8_strlen (str, num_chars*2+1) > num_chars) { - gchar *truncated_str; - gchar *str2; - -@@ -231,11 +379,11 @@ - - g_utf8_strncpy (str2, str, num_chars-2); - truncated_str = g_strdup_printf ("%s..", str2); -- escaped_str = g_markup_escape_text (truncated_str, strlen (truncated_str)); -+ escaped_str = escape ? g_markup_escape_text (truncated_str, strlen (truncated_str)) : g_strdup (truncated_str); - g_free (str2); - g_free (truncated_str); - } else { -- escaped_str = g_markup_escape_text (str, strlen (str)); -+ escaped_str = escape ? g_markup_escape_text (str, strlen (str)) : g_strdup (str); - } - - return escaped_str; -@@ -257,67 +405,105 @@ - static void - notify (const gchar *title, - const gchar *body, -- PurpleBuddy *buddy) -+ PurpleBuddy *buddy, -+ PurpleConversation *conv) - { - NotifyNotification *notification = NULL; -- GdkPixbuf *icon; -- PurpleBuddyIcon *buddy_icon; -- gchar *tr_body; -- PurpleContact *contact; -+ GdkPixbuf *icon = NULL; -+ PurpleBuddyIcon *buddy_icon = NULL; -+ gchar *tr_body = NULL; -+ PurpleContact *contact = NULL; - -- contact = purple_buddy_get_contact (buddy); -+ if (buddy != NULL) { -+ contact = purple_buddy_get_contact (buddy); -+ } - - if (body) -- tr_body = truncate_escape_string (body, 60); -+ tr_body = truncate_escape_string (body, 60, TRUE); - else - tr_body = NULL; - -- notification = g_hash_table_lookup (buddy_hash, contact); -+ /* If we're appending we shouldn't update an already -+ existing notification */ -+ if (conv == NULL && contact != NULL) { -+ notification = g_hash_table_lookup (buddy_hash, contact); -+ } - -+ /* This will only happen if we're a login message */ - if (notification != NULL) { - notify_notification_update (notification, title, tr_body, NULL); -+ - /* this shouldn't be necessary, file a bug */ - notify_notification_show (notification, NULL); - - purple_debug_info (PLUGIN_ID, "notify(), update: " - "title: '%s', body: '%s', buddy: '%s'\n", -- title, tr_body, best_name (buddy)); -+ title, tr_body, buddy != NULL ? best_name (buddy) : "(null)"); - - g_free (tr_body); - return; - } -- notification = notify_notification_new (title, tr_body, NULL, NULL); -+ -+ notification = notify_notification_new (title, tr_body, "notification-message-im", NULL); - purple_debug_info (PLUGIN_ID, "notify(), new: " - "title: '%s', body: '%s', buddy: '%s'\n", -- title, tr_body, best_name (buddy)); -+ title, tr_body, buddy != NULL ? best_name (buddy) : "(null)"); - - g_free (tr_body); - -- buddy_icon = purple_buddy_get_icon (buddy); -- if (buddy_icon) { -+ if (notify_supports_append) { -+ if (conv != NULL) { -+ notify_notification_set_hint_string(notification, "x-canonical-append", "allow"); -+ } -+ } -+ -+ if (buddy != NULL) { -+ buddy_icon = purple_buddy_get_icon (buddy); -+ } -+ -+ if (buddy_icon != NULL) { - icon = pixbuf_from_buddy_icon (buddy_icon); - purple_debug_info (PLUGIN_ID, "notify(), has a buddy icon.\n"); - } else { -- icon = pidgin_create_prpl_icon (buddy->account, 1); -- purple_debug_info (PLUGIN_ID, "notify(), has a prpl icon.\n"); -+ if (buddy != NULL) { -+ icon = pidgin_create_prpl_icon (buddy->account, PIDGIN_PRPL_ICON_LARGE); -+ purple_debug_info (PLUGIN_ID, "notify(), has a prpl icon.\n"); -+ } - } - -- if (icon) { -+ icon = normalize_icon (icon, 48); -+ -+ if (icon != NULL) { - notify_notification_set_icon_from_pixbuf (notification, icon); - g_object_unref (icon); -- } else { -- purple_debug_warning (PLUGIN_ID, "notify(), couldn't find any icon!\n"); -- } - -- g_hash_table_insert (buddy_hash, contact, notification); -+ GValue iconname = {0}; -+ g_value_init(&iconname, G_TYPE_STRING); -+ g_value_set_static_string(&iconname, ""); -+ g_object_set_property(G_OBJECT(notification), "icon-name", &iconname); -+ } - -- g_object_set_data (G_OBJECT(notification), "contact", contact); -+ if (contact != NULL && conv == NULL) { -+ g_hash_table_insert (buddy_hash, contact, notification); - -- g_signal_connect (notification, "closed", G_CALLBACK(closed_cb), NULL); -+ g_signal_connect (notification, "closed", G_CALLBACK(closed_cb), contact); -+ } -+ if (conv != NULL) { -+ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); -+ notifylist = g_list_append(notifylist, notification); -+ purple_conversation_set_data(conv, "notification-list", notifylist); -+ g_signal_connect(notification, "closed", G_CALLBACK(notification_list_closed_cb), conv); -+ } -+ if (contact == NULL && conv == NULL) { -+ /* Should never happen, but just in case, let's not have a memory leak */ -+ g_signal_connect(notification, "closed", G_CALLBACK(g_object_unref), NULL); -+ } - - notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); - -- notify_notification_add_action (notification, "show", _("Show"), action_cb, NULL, NULL); -+ if (notify_supports_actions) { -+ notify_notification_add_action (notification, "show", _("Show"), action_cb, buddy, NULL); -+ } - - if (!notify_notification_show (notification, NULL)) { - purple_debug_error (PLUGIN_ID, "notify(), failed to send notification\n"); -@@ -329,7 +515,7 @@ - notify_buddy_signon_cb (PurpleBuddy *buddy, - gpointer data) - { -- gchar *tr_name, *title; -+ gchar *tr_name; - gboolean blocked; - - g_return_if_fail (buddy); -@@ -347,21 +533,18 @@ - if (!should_notify_unavailable (purple_buddy_get_account (buddy))) - return; - -- tr_name = truncate_escape_string (best_name (buddy), 25); -+ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); - -- title = g_strdup_printf (_("%s signed on"), tr_name); -- -- notify (title, NULL, buddy); -+ notify (tr_name, _("is online"), buddy, NULL); - - g_free (tr_name); -- g_free (title); - } - - static void - notify_buddy_signoff_cb (PurpleBuddy *buddy, - gpointer data) - { -- gchar *tr_name, *title; -+ gchar *tr_name; - gboolean blocked; - - g_return_if_fail (buddy); -@@ -379,45 +562,78 @@ - if (!should_notify_unavailable (purple_buddy_get_account (buddy))) - return; - -- tr_name = truncate_escape_string (best_name (buddy), 25); -- -- title = g_strdup_printf (_("%s signed off"), tr_name); -+ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); - -- notify (title, NULL, buddy); -+ notify (tr_name, _("is offline"), buddy, NULL); - - g_free (tr_name); -- g_free (title); - } - - static void - notify_msg_sent (PurpleAccount *account, - const gchar *sender, -- const gchar *message) -+ const gchar *message, -+ PurpleConversation * conv) - { -- PurpleBuddy *buddy; -- gchar *title, *body, *tr_name; -+ PurpleBuddy *buddy = NULL; -+ gchar *body = NULL, *tr_name = NULL; - gboolean blocked; - -- buddy = purple_find_buddy (account, sender); -- if (!buddy) -- return; -- - blocked = purple_prefs_get_bool ("/plugins/gtk/libnotify/blocked"); - if (!purple_privacy_check(account, sender) && blocked) - return; - -- tr_name = truncate_escape_string (best_name (buddy), 25); -+ if (g_list_find (just_signed_on_accounts, account)) -+ return; -+ -+ buddy = purple_find_buddy (account, sender); -+ -+ if (buddy != NULL) { -+ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); -+ } else { -+ if (conv != NULL) { -+ const gchar * temp = purple_conversation_get_title(conv); -+ if (temp != NULL) { -+ if (sender == NULL || !g_strcmp0(sender, temp)) { -+ tr_name = g_strdup(temp); -+ } else { -+ tr_name = g_strdup_printf("%s (%s)", sender, temp); -+ } -+ } else { -+ if (sender != NULL) { -+ tr_name = g_strdup(sender); -+ } -+ } -+ } -+ } -+ -+ if (tr_name == NULL) { -+ purple_debug_warning(PLUGIN_ID, "Unable to find a title for the notification"); -+ return; -+ } - -- title = g_strdup_printf (_("%s says:"), tr_name); - body = purple_markup_strip_html (message); - -- notify (title, body, buddy); -+ notify (tr_name, body, buddy, conv); - - g_free (tr_name); -- g_free (title); - g_free (body); - } - -+static gboolean -+notify_new_message_idle (gpointer data) -+{ -+ indicate_chat_nick_idle_t * idle_data = (indicate_chat_nick_idle_t *)data; -+ -+ notify_new_message_cb(idle_data->account, idle_data->sender, idle_data->message, 0, NULL); -+ -+ g_free(idle_data->sender); -+ g_free(idle_data->message); -+ g_free(idle_data); -+ -+ return FALSE; -+} -+ - static void - notify_new_message_cb (PurpleAccount *account, - const gchar *sender, -@@ -430,24 +646,44 @@ - if (!purple_prefs_get_bool ("/plugins/gtk/libnotify/newmsg")) - return; - -+ if (name_blacklisted(account, sender)) return; -+ - conv = purple_find_conversation_with_account (PURPLE_CONV_TYPE_IM, sender, account); - - #ifndef DEBUG /* in debug mode, always show notifications */ - if (conv && purple_conversation_has_focus (conv)) { -- purple_debug_info (PLUGIN_ID, "Conversation has focus 0x%x\n", conv); -+ purple_debug_info (PLUGIN_ID, "Conversation has focus 0x%x\n", GPOINTER_TO_UINT(conv)); - return; - } - #endif - - if (conv && purple_prefs_get_bool ("/plugins/gtk/libnotify/newconvonly")) { -- purple_debug_info (PLUGIN_ID, "Conversation is not new 0x%x\n", conv); -+ purple_debug_info (PLUGIN_ID, "Conversation is not new 0x%x\n", GPOINTER_TO_UINT(conv)); -+ return; -+ } -+ -+ if (conv == NULL) { -+ purple_debug_warning(PLUGIN_ID, "Notify Message send has NULL Conversation, going idle"); -+ indicate_chat_nick_idle_t * idle_data = g_new0(indicate_chat_nick_idle_t, 1); -+ idle_data->account = account; -+ idle_data->sender = g_strdup(sender); -+ idle_data->message = g_strdup(message); -+ g_idle_add(notify_new_message_idle, idle_data); - return; - } - - if (!should_notify_unavailable (account)) - return; - -- notify_msg_sent (account, sender, message); -+ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); -+ if (pconv != NULL) { -+ if (pconv->entry != NULL && pconv->imhtml != NULL) { -+ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { -+ purple_debug_warning(PLUGIN_ID, "Pidgin conversation's widgets are in focus"); -+ return; -+ }}} -+ -+ notify_msg_sent (account, sender, message, conv); - } - - static void -@@ -463,10 +699,490 @@ - if (nick && !strcmp (sender, nick)) - return; - -- if (!g_strstr_len (message, strlen(message), nick)) -+ if (!purple_utf8_has_word (message, nick)) -+ return; -+ -+ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); -+ if (pconv != NULL) { -+ if (pconv->entry != NULL && pconv->imhtml != NULL) { -+ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { -+ purple_debug_warning(PLUGIN_ID, "Pidgin conversation's widgets are in focus"); - return; -+ }}} -+ -+ if (name_blacklisted(account, sender)) return; -+ -+ notify_msg_sent (account, sender, message, conv); -+} -+ -+static gboolean -+indicate_focus_cb (GtkWidget * widget, GdkEventFocus * event, gpointer data) -+{ -+ conv_delete_cb((PurpleConversation *)data, NULL); -+ -+ /* Don't swallow event */ -+ return FALSE; -+} -+ -+static void -+indicate_show_cb (IndicateIndicator * indicator, guint timestamp, PurpleConversation * conv) -+{ -+ /* g_debug ("indicate_show_cb()"); */ -+ -+ if (conv == NULL) { -+ purple_debug_warning(PLUGIN_ID, "\tNULL conversation"); -+ } -+ -+ PidginConversation * gtkconv = PIDGIN_CONVERSATION(conv); -+ if (gtkconv == NULL) { -+ purple_debug_warning(PLUGIN_ID, "\tNULL Pidgin Conversation"); -+ } - -- notify_msg_sent (account, sender, message); -+ pidgin_conv_switch_active_conversation(conv); -+ pidgin_conv_window_switch_gtkconv(gtkconv->win, gtkconv); -+ gtk_window_present_with_time(GTK_WINDOW(gtkconv->win->window), timestamp); -+ -+ return; -+} -+ -+static void -+conv_delete_cb (PurpleConversation * conv, void * data) -+{ -+ /* g_debug("Pidgin conv delete: %s", purple_conversation_get_name(conv)); */ -+ IndicateIndicator * indicator = INDICATE_INDICATOR(purple_conversation_get_data(conv, "indicate-indicator")); -+ if (indicator != NULL) { -+ indicate_indicator_hide(indicator); -+ g_object_unref(G_OBJECT(indicator)); -+ purple_conversation_set_data(conv, "indicate-indicator", NULL); -+ } -+ -+ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); -+ if (notifylist != NULL) { -+ GList * i; -+ for (i = notifylist; i != NULL; i = i->next) { -+ NotifyNotification * notification = NOTIFY_NOTIFICATION(i->data); -+ if (notification == NULL) break; -+ -+ g_signal_handlers_disconnect_by_func(G_OBJECT(notification), notification_list_closed_cb, conv); -+ notify_notification_close(notification, NULL); /* Don't care if it fails, it's going to die. */ -+ g_object_unref(G_OBJECT(notification)); -+ } -+ g_list_free(notifylist); -+ -+ purple_conversation_set_data(conv, "notification-list", NULL); -+ } -+ -+ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); -+ if (pconv != NULL) { -+ g_signal_handlers_disconnect_by_func(G_OBJECT(pconv->entry), G_CALLBACK(indicate_focus_cb), conv); -+ g_signal_handlers_disconnect_by_func(G_OBJECT(pconv->imhtml), G_CALLBACK(indicate_focus_cb), conv); -+ } -+ -+ return; -+} -+ -+static gboolean -+indicate_chat_nick_idle (gpointer data) -+{ -+ indicate_chat_nick_idle_t * idle_data = (indicate_chat_nick_idle_t *)data; -+ -+ PurpleConversation * conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, idle_data->sender, idle_data->account); -+ if (conv != NULL) { -+ indicate_chat_nick(idle_data->account, idle_data->sender, idle_data->message, conv, NULL); -+ } -+ -+ g_free(idle_data->sender); -+ g_free(idle_data->message); -+ g_free(idle_data); -+ -+ return FALSE; -+} -+ -+static void -+indicate_chat_nick (PurpleAccount *account, -+ const gchar *sender, -+ const gchar *message, -+ PurpleConversation *conv, -+ gpointer data) -+{ -+ PurpleBuddy *buddy = NULL; -+ GdkPixbuf *icon = NULL; -+ gchar *tr_name = NULL; -+ PurpleBuddyIcon * buddy_icon = NULL; -+ -+ /* g_debug("Entering indicate_chat_nick"); */ -+ if (name_blacklisted(account, sender)) return; -+ -+ if (conv == NULL) { -+ purple_debug_warning(PLUGIN_ID, "Conversation is NULL, setting up to check in idle"); -+ indicate_chat_nick_idle_t * idle_data = g_new0(indicate_chat_nick_idle_t, 1); -+ idle_data->account = account; -+ idle_data->sender = g_strdup(sender); -+ idle_data->message = g_strdup(message); -+ g_idle_add(indicate_chat_nick_idle, idle_data); -+ return; -+ } -+ -+ if (g_list_find (just_signed_on_accounts, account)) -+ return; -+ -+ if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { -+ gchar * nick = (gchar *)purple_conv_chat_get_nick (PURPLE_CONV_CHAT(conv)); -+ if (nick && !strcmp (sender, nick)) -+ return; -+ -+ if (!purple_utf8_has_word (message, nick)) -+ return; -+ } -+ -+ IndicateIndicator * indicator = purple_conversation_get_data(conv, "indicate-indicator"); -+ if (indicator != NULL) { -+ /* We've already indicated this one, let's set the time */ -+ /* g_debug("Updating indicator time"); */ -+ GTimeVal time; g_get_current_time(&time); -+ indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), "time", &time); -+ return; -+ } -+ -+ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); -+ if (pconv != NULL) { -+ if (pconv->entry != NULL && pconv->imhtml != NULL) { -+ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { -+ purple_debug_warning(PLUGIN_ID, "Pidgin conversation's widgets are in focus"); -+ return; -+ }}} -+ -+ if (account != NULL && sender != NULL) { -+ buddy = purple_find_buddy (account, sender); -+ } else { -+ purple_debug_warning(PLUGIN_ID, "We can't create an indicator for an account or a sender that don't exist!"); -+ } -+ -+ if (buddy == NULL) { -+ purple_debug_warning(PLUGIN_ID, "Unable to find buddy."); -+ } else { -+ buddy_icon = purple_buddy_get_icon(buddy); -+ } -+ -+ if (buddy_icon != NULL) { -+ icon = pixbuf_from_buddy_icon(buddy_icon); -+ } else { -+ if (buddy != NULL) { -+ icon = pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_LARGE); -+ } -+ } -+ -+ if (buddy != NULL) { -+ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); -+ } else { -+ const gchar * temp = purple_conversation_get_title(conv); -+ if (temp != NULL) { -+ if (sender == NULL || !g_strcmp0(sender, temp)) { -+ tr_name = g_strdup(temp); -+ } else { -+ tr_name = g_strdup_printf("%s (%s)", sender, temp); -+ } -+ } else { -+ if (sender != NULL) { -+ tr_name = g_strdup(sender); -+ } -+ } -+ } -+ -+ if (tr_name == NULL) { -+ purple_debug_warning(PLUGIN_ID, "Unable to determine a sender"); -+ return; -+ } -+ -+ indicator = indicate_indicator_new(); -+ -+ indicate_indicator_set_property(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_NAME, tr_name); -+ indicate_indicator_set_property(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_ATTENTION, "true"); -+ if (icon) { -+ indicate_gtk_indicator_set_property_icon(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon); -+ g_object_unref(G_OBJECT(icon)); -+ } -+ GTimeVal time; g_get_current_time(&time); -+ indicate_indicator_set_property_time(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_TIME, &time); -+ indicate_indicator_show(INDICATE_INDICATOR(indicator)); -+ -+ purple_conversation_set_data(conv, "indicate-indicator", indicator); -+ -+ g_signal_connect(G_OBJECT(pconv->entry), "focus-in-event", G_CALLBACK(indicate_focus_cb), conv); -+ g_signal_connect(G_OBJECT(pconv->imhtml), "focus-in-event", G_CALLBACK(indicate_focus_cb), conv); -+ -+ g_signal_connect(G_OBJECT(indicator), INDICATE_INDICATOR_SIGNAL_DISPLAY, G_CALLBACK(indicate_show_cb), conv); -+ -+ return; -+} -+ -+static void -+indicate_new_message_cb (PurpleAccount *account, -+ const gchar *sender, -+ const gchar *message, -+ int flags, -+ gpointer data) -+{ -+ PurpleConversation * conv = purple_find_conversation_with_account (PURPLE_CONV_TYPE_IM, sender, account); -+ -+ return indicate_chat_nick(account, sender, message, conv, data); -+} -+ -+static void -+indicate_server_show_interest (IndicateServer * server, IndicateInterests interest, gpointer data) -+{ -+ if (interest == INDICATE_INTEREST_SERVER_SIGNAL) { -+ if (visibility_managed == FALSE) { -+ pidgin_blist_visibility_manager_add(); -+ visibility_managed = TRUE; -+ } -+ } -+ -+ return; -+} -+ -+static void -+indicate_server_remove_interest (IndicateServer * server, IndicateInterests interest, gpointer data) -+{ -+ if (interest == INDICATE_INTEREST_SERVER_SIGNAL) { -+ if (visibility_managed == TRUE) { -+ pidgin_blist_visibility_manager_remove(); -+ visibility_managed = FALSE; -+ } -+ } -+ -+ return; -+} -+ -+static void -+indicate_server_display (IndicateServer * server, guint timestamp, gpointer data) -+{ -+ if (visibility_managed == FALSE) { -+ /* If we haven't been told that someone is interested in -+ sending signals, but we get one. How rude is that! */ -+ g_warning("Got a signal on our server, but no one has told us that they were interested in doing that. Hmph."); -+ return; -+ } -+ -+ purple_blist_set_visible(TRUE); -+ -+ PidginBuddyList * gtkblist = pidgin_blist_get_default_gtk_blist(); -+ if (gtkblist == NULL) return; -+ -+ if (gtkblist->window == NULL) return; -+ gtk_window_present_with_time(GTK_WINDOW(gtkblist->window), timestamp); -+ -+ return; -+} -+ -+static gboolean -+indicate_login_timeout (gpointer data) -+{ -+ IndicateIndicator * indicator = INDICATE_INDICATOR(data); -+ -+ indicate_indicator_hide(indicator); -+ g_object_unref(G_OBJECT(indicator)); -+ -+ return FALSE; -+} -+ -+static void -+indicate_login_cb (IndicateIndicator * indicator, guint timestamp, gpointer data) -+{ -+ PurpleBuddy * buddy = (PurpleBuddy *)data; -+ -+ if (buddy == NULL) -+ return; -+ -+ PurpleAccount * account = purple_buddy_get_account(buddy); -+ const char * name = purple_buddy_get_name(buddy); -+ -+ PurpleConversation * conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account); -+ if (conv == NULL) { -+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name); -+ } -+ -+ indicate_show_cb(NULL, timestamp, conv); -+ -+ return; -+} -+ -+static void -+indicate_buddy_signon_cb (PurpleBuddy *buddy, -+ gpointer data) -+{ -+ GdkPixbuf *icon = NULL; -+ PurpleBuddyIcon * buddy_icon = NULL; -+ gchar *tr_name = NULL; -+ IndicateIndicator * indicator = NULL; -+ gboolean blocked; -+ -+ g_return_if_fail (buddy); -+ -+ if (!purple_prefs_get_bool ("/plugins/gtk/libnotify/signon")) -+ return; -+ -+ if (g_list_find (just_signed_on_accounts, buddy->account)) -+ return; -+ -+ blocked = purple_prefs_get_bool ("/plugins/gtk/libnotify/blocked"); -+ if (!purple_privacy_check (buddy->account, buddy->name) && blocked) -+ return; -+ -+ if (!should_notify_unavailable (purple_buddy_get_account (buddy))) -+ return; -+ -+ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); -+ -+ buddy_icon = purple_buddy_get_icon(buddy); -+ -+ if (buddy_icon != NULL) { -+ icon = pixbuf_from_buddy_icon(buddy_icon); -+ } else { -+ if (buddy != NULL) { -+ icon = pidgin_create_prpl_icon(buddy->account, PIDGIN_PRPL_ICON_LARGE); -+ } -+ } -+ -+ indicator = INDICATE_INDICATOR(indicate_indicator_new()); -+ -+ indicate_indicator_set_property(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_NAME, tr_name); -+ if (icon) { -+ indicate_gtk_indicator_set_property_icon(INDICATE_INDICATOR(indicator), INDICATE_INDICATOR_MESSAGES_PROP_ICON, icon); -+ g_object_unref(G_OBJECT(icon)); -+ } -+ indicate_indicator_show(INDICATE_INDICATOR(indicator)); -+ -+ g_timeout_add_seconds(60, indicate_login_timeout, indicator); -+ g_signal_connect(G_OBJECT(indicator), INDICATE_INDICATOR_SIGNAL_DISPLAY, G_CALLBACK(indicate_login_cb), buddy); -+ -+ g_free (tr_name); -+} -+ -+static void -+remove_from_blacklist (void) -+{ -+ gchar *bpath; -+ -+ bpath = g_build_filename (g_get_user_config_dir(), -+ BLACKLIST_DIR, -+ BLACKLIST_FILENAME, -+ NULL); -+ -+ if (g_file_test (bpath, G_FILE_TEST_EXISTS)) { -+ GFile *bfile; -+ bfile = g_file_new_for_path (bpath); -+ -+ if (bfile) { -+ GError *error = NULL; -+ g_file_delete (bfile, NULL, &error); -+ -+ if (error) { -+ g_warning ("Unable to remove blacklist file: %s", error->message); -+ g_error_free (error); -+ } -+ -+ g_object_unref (bfile); -+ } -+ } -+ -+ g_free (bpath); -+ -+ return; -+} -+ -+static gboolean -+plugin_never_loaded (gpointer data) -+{ -+ gchar *bdir; -+ gchar *bpath; -+ GError *error = NULL; -+ -+ bdir = g_build_filename (g_get_user_config_dir (), -+ BLACKLIST_DIR, -+ NULL); -+ if (!g_file_test (bdir, G_FILE_TEST_IS_DIR)) { -+ GFile *dirfile; -+ -+ dirfile = g_file_new_for_path (bdir); -+ if (dirfile) { -+ g_file_make_directory_with_parents (dirfile, -+ NULL, -+ &error); -+ if (error) { -+ g_warning ("Unable to create blacklist directory: %s", -+ error->message); -+ g_error_free (error); -+ g_object_unref (dirfile); -+ g_free (bdir); -+ return FALSE; -+ } -+ } else { -+ g_warning ("Unable to create blacklist directory: Unable to create " -+ "GFile for path %s", bdir); -+ g_free (bdir); -+ return FALSE; -+ } -+ -+ g_object_unref (dirfile); -+ } -+ g_free (bdir); -+ -+ bpath = g_build_filename (g_get_user_config_dir (), -+ BLACKLIST_DIR, -+ BLACKLIST_FILENAME, -+ NULL); -+ -+ if (g_file_set_contents (bpath, -+ PIDGIN_DESKTOP_FILE, -+ -1, -+ &error)) { -+ g_debug ("Successfully wrote blacklist file to %s", bpath); -+ } else { -+ g_debug ("Unable to write blacklist file to %s: %s", -+ bpath, -+ error ? error->message : "Unknown"); -+ if (error) -+ g_error_free (error); -+ } -+ -+ g_free (bpath); -+ -+ return FALSE; -+} -+ -+static void -+notify_check_caps_helper (gpointer data, gpointer user_data) -+{ -+ gchar * cap = (gchar *)data; -+ -+ if (cap == NULL) return; -+ -+ if (!strcmp(cap, "actions")) { -+ notify_supports_actions = TRUE; -+ } else if (!strcmp(cap, "append")) { -+ notify_supports_append = TRUE; -+ } else if (!strcmp(cap, "x-canonical-append")) { -+ notify_supports_append = TRUE; -+ } else if (!strcmp(cap, "truncation")) { -+ notify_supports_truncation = TRUE; -+ } else if (!strcmp(cap, "x-canonical-truncation")) { -+ notify_supports_truncation = TRUE; -+ } -+ -+ return; -+} -+ -+static void -+notify_check_caps(void) -+{ -+ GList * caps = notify_get_server_caps(); -+ -+ g_list_foreach(caps, notify_check_caps_helper, NULL); -+ g_list_foreach(caps, (GFunc)g_free, NULL); -+ g_list_free(caps); -+ -+ return; - } - - static gboolean -@@ -479,6 +1195,22 @@ - return FALSE; - } - -+ /* They really do love me! */ -+ if (never_loaded != 0) { -+ g_source_remove(never_loaded); -+ } -+ remove_from_blacklist(); -+ -+ notify_check_caps(); -+ -+ indicate_server = indicate_server_ref_default(); -+ indicate_server_set_type(indicate_server, "message.instant"); -+ indicate_server_set_desktop_file(indicate_server, PIDGIN_DESKTOP_FILE); -+ g_signal_connect(G_OBJECT(indicate_server), INDICATE_SERVER_SIGNAL_SERVER_DISPLAY, G_CALLBACK(indicate_server_display), NULL); -+ g_signal_connect(G_OBJECT(indicate_server), INDICATE_SERVER_SIGNAL_INTEREST_ADDED, G_CALLBACK(indicate_server_show_interest), NULL); -+ g_signal_connect(G_OBJECT(indicate_server), INDICATE_SERVER_SIGNAL_INTEREST_REMOVED, G_CALLBACK(indicate_server_remove_interest), NULL); -+ indicate_server_show(indicate_server); -+ - conv_handle = purple_conversations_get_handle (); - blist_handle = purple_blist_get_handle (); - conn_handle = purple_connections_get_handle(); -@@ -497,6 +1229,18 @@ - purple_signal_connect (conv_handle, "received-chat-msg", plugin, - PURPLE_CALLBACK(notify_chat_nick), NULL); - -+ purple_signal_connect (conv_handle, "received-im-msg", plugin, -+ PURPLE_CALLBACK(indicate_new_message_cb), NULL); -+ -+ purple_signal_connect (conv_handle, "received-chat-msg", plugin, -+ PURPLE_CALLBACK(indicate_chat_nick), NULL); -+ -+ purple_signal_connect (blist_handle, "buddy-signed-on", plugin, -+ PURPLE_CALLBACK(indicate_buddy_signon_cb), NULL); -+ -+ purple_signal_connect (conv_handle, "deleting-conversation", plugin, -+ PURPLE_CALLBACK(conv_delete_cb), NULL); -+ - /* used just to not display the flood of guifications we'd get */ - purple_signal_connect (conn_handle, "signed-on", plugin, - PURPLE_CALLBACK(event_connection_throttle), NULL); -@@ -525,6 +1269,18 @@ - purple_signal_disconnect (conv_handle, "received-chat-msg", plugin, - PURPLE_CALLBACK(notify_chat_nick)); - -+ purple_signal_disconnect (conv_handle, "received-im-msg", plugin, -+ PURPLE_CALLBACK(indicate_new_message_cb)); -+ -+ purple_signal_disconnect (conv_handle, "received-chat-msg", plugin, -+ PURPLE_CALLBACK(indicate_chat_nick)); -+ -+ purple_signal_disconnect (blist_handle, "buddy-signed-on", plugin, -+ PURPLE_CALLBACK(indicate_buddy_signon_cb)); -+ -+ purple_signal_disconnect (conv_handle, "deleting-conversation", plugin, -+ PURPLE_CALLBACK(conv_delete_cb)); -+ - purple_signal_disconnect (conn_handle, "signed-on", plugin, - PURPLE_CALLBACK(event_connection_throttle)); - -@@ -532,6 +1288,19 @@ - - notify_uninit (); - -+ indicate_server_hide(indicate_server); -+ -+ if (visibility_managed == TRUE) { -+ pidgin_blist_visibility_manager_remove(); -+ } -+ -+ g_object_unref(G_OBJECT(indicate_server)); -+ -+ /* If this goes off, we were unloaded by the user -+ and not by shutdown. Same thing as us never -+ getting loaded at all. */ -+ never_loaded = g_timeout_add_seconds(30, plugin_never_loaded, NULL); -+ - return TRUE; - } - -@@ -578,7 +1347,24 @@ - info.summary = _("Displays popups via libnotify."); - info.description = _("Pidgin-libnotify:\nDisplays popups via libnotify."); - -+ /* If we get init'd and we never get loaded -+ chances are the user hasn't enabled this -+ plugin. */ -+ never_loaded = g_timeout_add_seconds(30, plugin_never_loaded, NULL); -+ - purple_prefs_add_none ("/plugins/gtk/libnotify"); -+ -+ /* Create a list of nicks that are commonly used by -+ IRC servers but don't represent real people. */ -+ GList * nicklist = NULL; -+ nicklist = g_list_append(nicklist, "NickServ"); -+ nicklist = g_list_append(nicklist, "ChanServ"); -+ nicklist = g_list_append(nicklist, "MsgServ"); -+ nicklist = g_list_append(nicklist, "freenode-connect"); -+ -+ purple_prefs_add_string_list ("/plugins/gtk/libnotify/blocked_nicks", nicklist); -+ g_list_free(nicklist); -+ - purple_prefs_add_bool ("/plugins/gtk/libnotify/newmsg", TRUE); - purple_prefs_add_bool ("/plugins/gtk/libnotify/blocked", TRUE); - purple_prefs_add_bool ("/plugins/gtk/libnotify/newconvonly", FALSE); diff -Nru pidgin-libnotify-0.14/debian/patches/libnotify_0_7.patch pidgin-libnotify-0.14/debian/patches/libnotify_0_7.patch --- pidgin-libnotify-0.14/debian/patches/libnotify_0_7.patch 2012-02-10 14:04:30.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/libnotify_0_7.patch 1969-12-31 19:00:00.000000000 -0500 @@ -1,13 +0,0 @@ -Index: pidgin-libnotify/src/pidgin-libnotify.c -=================================================================== ---- pidgin-libnotify.orig/src/pidgin-libnotify.c 2011-08-10 22:46:33.003107473 -0400 -+++ pidgin-libnotify/src/pidgin-libnotify.c 2011-08-10 22:46:33.963108883 -0400 -@@ -438,7 +438,7 @@ - return; - } - -- notification = notify_notification_new (title, tr_body, "notification-message-im", NULL); -+ notification = notify_notification_new (title, tr_body, "notification-message-im"); - purple_debug_info (PLUGIN_ID, "notify(), new: " - "title: '%s', body: '%s', buddy: '%s'\n", - title, tr_body, buddy != NULL ? best_name (buddy) : "(null)"); diff -Nru pidgin-libnotify-0.14/debian/patches/messaging_menu.patch pidgin-libnotify-0.14/debian/patches/messaging_menu.patch --- pidgin-libnotify-0.14/debian/patches/messaging_menu.patch 1969-12-31 19:00:00.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/messaging_menu.patch 2012-11-14 22:36:33.000000000 -0500 @@ -0,0 +1,569 @@ +=== modified file 'configure.ac' +--- a/configure.ac ++++ b/configure.ac +@@ -74,6 +74,15 @@ + AC_SUBST(LIBNOTIFY_LIBS) + + # ++# Check for libmessaging-menu ++# ++ ++PKG_CHECK_MODULES(LIBMESSAGINGMENU, messaging-menu >= 12.10.4) ++ ++AC_SUBST(LIBMESSAGINGMENU_CFLAGS) ++AC_SUBST(LIBMESSAGINGMENU_LIBS) ++ ++# + # Check for GTK+ + # + PKG_CHECK_MODULES(GTK, gtk+-2.0) +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -10,7 +10,7 @@ + pidgin-libnotify.c \ + gln_intl.h + +-pidgin_libnotify_la_LIBADD = $(LIBNOTIFY_LIBS) $(DBUS_LIBS) $(GTK_LIBS) ++pidgin_libnotify_la_LIBADD = $(LIBMESSAGINGMENU_LIBS) $(LIBNOTIFY_LIBS) $(DBUS_LIBS) $(GTK_LIBS) + + endif + +@@ -24,6 +24,7 @@ + $(PIDGIN_CFLAGS) \ + $(LIBPURPLE_CFLAGS) \ + $(LIBNOTIFY_CFLAGS) \ ++ $(LIBMESSAGINGMENU_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GTK_CFLAGS) + +--- a/src/pidgin-libnotify.c ++++ b/src/pidgin-libnotify.c +@@ -23,6 +23,8 @@ + + #include "gln_intl.h" + ++#include ++ + #ifndef PURPLE_PLUGINS + #define PURPLE_PLUGINS + #endif +@@ -38,6 +40,7 @@ + #include + + #include ++#include + + #include + +@@ -48,7 +51,7 @@ + #endif + #define G_LOG_DOMAIN "pidgin-libnotify-plugin" + +-#define PIDGIN_DESKTOP_FILE "/usr/share/applications/pidgin.desktop" ++#define PIDGIN_DESKTOP_FILE "pidgin.desktop" + #define BLACKLIST_FILENAME "pidgin-libnotify" + #define BLACKLIST_DIR "indicators/messages/applications-blacklist" + +@@ -58,6 +61,8 @@ + /* Globals */ + static GHashTable *buddy_hash; + ++static MessagingMenuApp *m_menu_app = NULL; ++ + static gboolean notify_supports_actions = FALSE; + static gboolean notify_supports_append = FALSE; + static gboolean notify_supports_truncation = FALSE; +@@ -835,10 +840,399 @@ + return; + } + ++static gchar * ++messaging_unique_id (const char *type, ++ PurpleAccount *account, ++ const char *name) ++{ ++ g_return_val_if_fail (type != NULL, NULL); ++ g_return_val_if_fail (account != NULL, NULL); ++ g_return_val_if_fail (name != NULL, NULL); ++ ++ gchar *escaped_type = g_uri_escape_string (type, NULL, TRUE); ++ gchar *buddy_name = g_uri_escape_string (name, NULL, TRUE); ++ gchar *account_name = g_uri_escape_string (purple_account_get_username (account), NULL, TRUE); ++ gchar *protocol_id = g_uri_escape_string (purple_account_get_protocol_id (account), NULL, TRUE); ++ gchar *unique_id = g_strconcat (escaped_type, ":", protocol_id, ":", account_name, ++ ":", buddy_name, NULL); ++ ++ g_free (escaped_type); ++ g_free (buddy_name); ++ g_free (account_name); ++ g_free (protocol_id); ++ ++ return unique_id; ++} ++ ++static PurpleConversation * ++messaging_conversation_for_unique_id (const gchar *unique_id) ++{ ++ g_return_val_if_fail (unique_id != NULL, NULL); ++ ++ gchar **tokens = g_strsplit(unique_id, ":", 0); ++ guint n_tokens = g_strv_length(tokens); ++ ++ if (n_tokens != 4) { ++ purple_debug_warning (PLUGIN_ID, "Invalid unique_id '%s'\n", unique_id); ++ return NULL; ++ } ++ ++ gchar *type_id = g_uri_unescape_string(tokens[0], NULL); ++ gchar *protocol_id = g_uri_unescape_string(tokens[1], NULL); ++ gchar *account_name = g_uri_unescape_string(tokens[2], NULL); ++ gchar *buddy_name = g_uri_unescape_string(tokens[3], NULL); ++ ++ PurpleAccount *account = purple_accounts_find (account_name, protocol_id); ++ ++ if (account == NULL) { ++ g_free (type_id); ++ g_free (protocol_id); ++ g_free (account_name); ++ g_free (buddy_name); ++ g_strfreev (tokens); ++ return NULL; ++ } ++ ++ PurpleConversationType conv_type = PURPLE_CONV_TYPE_IM; ++ if (g_strcmp0 (type_id, "chat") == 0) ++ conv_type = PURPLE_CONV_TYPE_CHAT; ++ ++ PurpleConversation *conv = purple_find_conversation_with_account (conv_type, ++ buddy_name, account); ++ ++ g_free (type_id); ++ g_free (protocol_id); ++ g_free (account_name); ++ g_free (buddy_name); ++ g_strfreev (tokens); ++ ++ return conv; ++} ++ ++static const char * ++messaging_type_from_conv_type (PurpleConversationType type) ++{ ++ const char *messaging_type; ++ ++ switch (type) { ++ case PURPLE_CONV_TYPE_IM: ++ messaging_type = "im"; ++ break; ++ case PURPLE_CONV_TYPE_CHAT: ++ messaging_type = "chat"; ++ break; ++ default: ++ purple_debug_warning (PLUGIN_ID, "Unsupported conversation type\n"); ++ messaging_type = "unknown"; ++ break; ++ } ++ ++ return messaging_type; ++} ++ ++static void ++messaging_conversation_updated_cb (PurpleConversation *conv, ++ PurpleConvUpdateType type, ++ gpointer user_data) ++{ ++ g_return_if_fail (m_menu_app != NULL); ++ ++ const char *type_name; ++ const char *conv_type = messaging_type_from_conv_type (purple_conversation_get_type (conv)); ++ PurpleAccount *account; ++ gchar *buddy_id; ++ int unseen_count; ++ ++ switch (type) { ++ case PURPLE_CONV_UPDATE_ADD: ++ type_name = "ADD"; ++ break; ++ case PURPLE_CONV_UPDATE_REMOVE: ++ type_name = "REMOVE"; ++ break; ++ case PURPLE_CONV_UPDATE_ACCOUNT: ++ type_name = "ACCOUNT"; ++ break; ++ case PURPLE_CONV_UPDATE_TYPING: ++ type_name = "TYPING"; ++ break; ++ case PURPLE_CONV_UPDATE_UNSEEN: ++ type_name = "UNSEEN"; ++ break; ++ case PURPLE_CONV_UPDATE_LOGGING: ++ type_name = "LOGGING"; ++ break; ++ case PURPLE_CONV_UPDATE_TOPIC: ++ type_name = "TOPIC"; ++ break; ++ default: ++ type_name = "OTHER"; ++ } ++ purple_debug_info (PLUGIN_ID, "Conversation Updated (%s)\n", type_name); ++ ++ /* Remove the attention */ ++ if (type == PURPLE_CONV_UPDATE_UNSEEN) { ++ unseen_count = GPOINTER_TO_INT(purple_conversation_get_data (conv, "unseen-count")); ++ account = purple_conversation_get_account (conv); ++ buddy_id = messaging_unique_id (conv_type, account, purple_conversation_get_name (conv)); ++ ++ if (buddy_id != NULL) { ++ if (messaging_menu_app_has_source (m_menu_app, buddy_id)) { ++ if (unseen_count == 0) { ++ purple_debug_info (PLUGIN_ID, "REMOVING ATTENTION FOR (%s) (%d)\n", ++ buddy_id, unseen_count); ++ messaging_menu_app_remove_attention (m_menu_app, buddy_id); ++ } ++ else if (purple_conversation_get_type (conv) == PURPLE_CONV_TYPE_IM) { ++ messaging_menu_app_draw_attention (m_menu_app, buddy_id); ++ } ++ } ++ } ++ g_free (buddy_id); ++ } ++} ++ ++static void ++messaging_conversation_deleted_cb (PurpleConversation *conv, ++ gpointer user_data) ++{ ++ g_return_if_fail (conv != NULL); ++ ++ PurpleAccount *account; ++ const char *conv_type = messaging_type_from_conv_type (purple_conversation_get_type (conv)); ++ gchar *buddy_id; ++ ++ account = purple_conversation_get_account (conv); ++ buddy_id = messaging_unique_id (conv_type, account, purple_conversation_get_name (conv)); ++ ++ if (buddy_id != NULL) { ++ if (messaging_menu_app_has_source (m_menu_app, buddy_id)) { ++ purple_debug_info (PLUGIN_ID, "Removing source (%s)\n", buddy_id); ++ messaging_menu_app_remove_source (m_menu_app, buddy_id); ++ } ++ } ++ ++ g_free (buddy_id); ++} ++ ++static gboolean ++pidgin_conversation_has_focus (PurpleConversation *conv) ++{ ++ if (conv == NULL) ++ return FALSE; ++ ++ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); ++ ++ if (pconv != NULL) { ++ if (pconv->entry != NULL && pconv->imhtml != NULL) { ++ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { ++ return TRUE; ++ } ++ } ++ } ++ ++ return FALSE; ++} ++ ++static void ++messaging_new_message_cb (PurpleAccount *account, ++ const gchar *sender, ++ const gchar *message, ++ int flags, ++ gpointer user_data) ++{ ++ g_return_if_fail (m_menu_app != NULL); ++ ++ PurpleBuddy *buddy = NULL; ++ gchar *buddy_id; ++ ++ if (name_blacklisted(account, sender)) ++ return; ++ ++ if (g_list_find (just_signed_on_accounts, account)) ++ return; ++ ++ if (account == NULL || sender == NULL) ++ return; ++ ++ buddy = purple_find_buddy (account, sender); ++ buddy_id = messaging_unique_id ("im", account, sender); ++ ++ if (buddy_id != NULL) { ++ purple_debug_info (PLUGIN_ID, "Sender: (%s) ID (%s) \n", sender, buddy_id); ++ if (messaging_menu_app_has_source (m_menu_app, buddy_id)) { ++ messaging_menu_app_set_source_time (m_menu_app, buddy_id, g_get_real_time ()); ++ } ++ else { ++ messaging_menu_app_append_source (m_menu_app, buddy_id, NULL, ++ buddy != NULL ? best_name (buddy) : sender); ++ } ++ } ++ ++ g_free (buddy_id); ++} ++ ++static void ++messaging_new_chat_cb (PurpleAccount *account, ++ const gchar *sender, ++ const gchar *message, ++ PurpleConversation *conv, ++ gpointer user_data) ++{ ++ purple_debug_info (PLUGIN_ID, "Chat (%s) (%s)\n", sender, message); ++ ++ if (name_blacklisted(account, sender)) return; ++ ++ const char *nick = purple_conv_chat_get_nick (PURPLE_CONV_CHAT(conv)); ++ if (nick && !g_strcmp0 (sender, nick)) ++ return; ++ ++ if (!purple_utf8_has_word (message, nick)) ++ return; ++ ++ char *buddy_id = messaging_unique_id ("chat", account, purple_conversation_get_name (conv)); ++ ++ if (buddy_id != NULL) { ++ if (messaging_menu_app_has_source (m_menu_app, buddy_id)) { ++ messaging_menu_app_set_source_time (m_menu_app, buddy_id, g_get_real_time ()); ++ } ++ else { ++ messaging_menu_app_append_source (m_menu_app, buddy_id, NULL, ++ purple_conversation_get_title (conv)); ++ } ++ if (!pidgin_conversation_has_focus (conv)) ++ messaging_menu_app_draw_attention (m_menu_app, buddy_id); ++ } ++ ++ g_free (buddy_id); ++} ++ ++static MessagingMenuStatus ++purple_status_to_messaging_status (PurpleStatusPrimitive status) ++{ ++ MessagingMenuStatus messaging_status_value; ++ ++ switch (status) { ++ case PURPLE_STATUS_AVAILABLE: ++ messaging_status_value = MESSAGING_MENU_STATUS_AVAILABLE; ++ break; ++ case PURPLE_STATUS_AWAY: ++ messaging_status_value = MESSAGING_MENU_STATUS_AWAY; ++ break; ++ case PURPLE_STATUS_UNAVAILABLE: ++ messaging_status_value = MESSAGING_MENU_STATUS_BUSY; ++ break; ++ case PURPLE_STATUS_INVISIBLE: ++ messaging_status_value = MESSAGING_MENU_STATUS_INVISIBLE; ++ break; ++ case PURPLE_STATUS_OFFLINE: ++ messaging_status_value = MESSAGING_MENU_STATUS_OFFLINE; ++ break; ++ default: ++ messaging_status_value = MESSAGING_MENU_STATUS_AVAILABLE; ++ } ++ ++ return messaging_status_value; ++} ++ ++static void ++messaging_set_status_from_savedstatus (PurpleSavedStatus *status) ++{ ++ g_return_if_fail (m_menu_app != NULL); ++ ++ PurpleStatusPrimitive purple_status = purple_savedstatus_get_type (status); ++ const char *status_id = purple_primitive_get_id_from_type (purple_status); ++ MessagingMenuStatus messaging_status = purple_status_to_messaging_status (purple_status); ++ messaging_menu_app_set_status (m_menu_app, messaging_status); ++ purple_debug_info (PLUGIN_ID, "Updating status set from pidgin to '%s'\n", status_id); ++} ++ ++static void ++messaging_savedstatus_changed_cb (PurpleSavedStatus *now, ++ PurpleSavedStatus *old, ++ gpointer user_data) ++{ ++ messaging_set_status_from_savedstatus (now); ++} ++ ++static PurpleStatusPrimitive ++messaging_status_to_purple_status (MessagingMenuStatus status) ++{ ++ PurpleStatusPrimitive purple_status_value; ++ ++ switch (status) { ++ case MESSAGING_MENU_STATUS_AVAILABLE: ++ purple_status_value = PURPLE_STATUS_AVAILABLE; ++ break; ++ case MESSAGING_MENU_STATUS_AWAY: ++ purple_status_value = PURPLE_STATUS_AWAY; ++ break; ++ case MESSAGING_MENU_STATUS_BUSY: ++ purple_status_value = PURPLE_STATUS_UNAVAILABLE; ++ break; ++ case MESSAGING_MENU_STATUS_INVISIBLE: ++ purple_status_value = PURPLE_STATUS_INVISIBLE; ++ break; ++ case MESSAGING_MENU_STATUS_OFFLINE: ++ purple_status_value = PURPLE_STATUS_OFFLINE; ++ break; ++ default: ++ purple_status_value = PURPLE_STATUS_UNSET; ++ } ++ ++ return purple_status_value; ++} ++ ++static void ++messaging_status_changed_cb (MessagingMenuApp *app, ++ MessagingMenuStatus status, ++ gpointer user_data) ++{ ++ g_return_if_fail (app != NULL); ++ ++ PurpleStatusPrimitive status_type = messaging_status_to_purple_status (status); ++ const char *status_id = purple_primitive_get_id_from_type (status_type); ++ PurpleSavedStatus *saved_status; ++ ++ purple_debug_info (PLUGIN_ID, "Updating accounts to status '%s'\n", status_id); ++ ++ saved_status = purple_savedstatus_find_transient_by_type_and_message (status_type, NULL); ++ ++ if (saved_status == NULL) { ++ saved_status = purple_savedstatus_new (NULL, status_type); ++ purple_debug_info (PLUGIN_ID, "Status not found\n"); ++ } ++ purple_savedstatus_activate (saved_status); ++ messaging_menu_app_set_status (app, status); ++} ++ ++static void ++messaging_source_activated_cb (MessagingMenuApp *app, ++ const gchar *source_id, ++ gpointer user_data) ++{ ++ PurpleConversation *conv; ++ PidginConversation *gtkconv; ++ purple_debug_info (PLUGIN_ID, "SOURCE activated '%s'\n", source_id); ++ /* find conversation with given source id */ ++ conv = messaging_conversation_for_unique_id (source_id); ++ ++ if (conv) { ++ gtkconv = PIDGIN_CONVERSATION (conv); ++ if (gtkconv == NULL) { ++ purple_debug_warning (PLUGIN_ID, "NULL gtkconv '%s'\n", source_id); ++ return; ++ } ++ pidgin_conv_switch_active_conversation(conv); ++ pidgin_conv_window_switch_gtkconv(gtkconv->win, gtkconv); ++ gtk_window_present(GTK_WINDOW(gtkconv->win->window)); ++ } ++} ++ + static gboolean + plugin_load (PurplePlugin *plugin) + { +- void *conv_handle, *blist_handle, *conn_handle; ++ void *conv_handle, *blist_handle, *conn_handle, *savedstatus_handle; + + if (!notify_is_initted () && !notify_init ("Pidgin")) { + purple_debug_error (PLUGIN_ID, "libnotify not running!\n"); +@@ -853,9 +1247,21 @@ + + notify_check_caps(); + ++ if (m_menu_app == NULL) { ++ m_menu_app = messaging_menu_app_new (PIDGIN_DESKTOP_FILE); ++ messaging_menu_app_register (m_menu_app); ++ g_signal_connect(m_menu_app, "status-changed", ++ G_CALLBACK(messaging_status_changed_cb), NULL); ++ g_signal_connect(m_menu_app, "activate-source", ++ G_CALLBACK(messaging_source_activated_cb), NULL); ++ messaging_set_status_from_savedstatus (purple_savedstatus_get_current ()); ++ pidgin_blist_visibility_manager_add (); ++ } ++ + conv_handle = purple_conversations_get_handle (); + blist_handle = purple_blist_get_handle (); + conn_handle = purple_connections_get_handle(); ++ savedstatus_handle = purple_savedstatuses_get_handle (); + + buddy_hash = g_hash_table_new (NULL, NULL); + +@@ -874,6 +1280,21 @@ + purple_signal_connect (conv_handle, "deleting-conversation", plugin, + PURPLE_CALLBACK(conv_delete_cb), NULL); + ++ purple_signal_connect (conv_handle, "conversation-updated", plugin, ++ PURPLE_CALLBACK(messaging_conversation_updated_cb), NULL); ++ ++ purple_signal_connect (conv_handle, "deleting-conversation", plugin, ++ PURPLE_CALLBACK(messaging_conversation_deleted_cb), NULL); ++ ++ purple_signal_connect (conv_handle, "received-im-msg", plugin, ++ PURPLE_CALLBACK(messaging_new_message_cb), NULL); ++ ++ purple_signal_connect (conv_handle, "received-chat-msg", plugin, ++ PURPLE_CALLBACK(messaging_new_chat_cb), NULL); ++ ++ purple_signal_connect (savedstatus_handle, "savedstatus-changed", plugin, ++ PURPLE_CALLBACK(messaging_savedstatus_changed_cb), NULL); ++ + /* used just to not display the flood of guifications we'd get */ + purple_signal_connect (conn_handle, "signed-on", plugin, + PURPLE_CALLBACK(event_connection_throttle), NULL); +@@ -884,11 +1305,12 @@ + static gboolean + plugin_unload (PurplePlugin *plugin) + { +- void *conv_handle, *blist_handle, *conn_handle; ++ void *conv_handle, *blist_handle, *conn_handle, *savedstatus_handle; + + conv_handle = purple_conversations_get_handle (); + blist_handle = purple_blist_get_handle (); + conn_handle = purple_connections_get_handle(); ++ savedstatus_handle = purple_savedstatuses_get_handle (); + + purple_signal_disconnect (blist_handle, "buddy-signed-on", plugin, + PURPLE_CALLBACK(notify_buddy_signon_cb)); +@@ -905,6 +1327,21 @@ + purple_signal_disconnect (conv_handle, "deleting-conversation", plugin, + PURPLE_CALLBACK(conv_delete_cb)); + ++ purple_signal_disconnect (conv_handle, "conversation-updated", plugin, ++ PURPLE_CALLBACK(messaging_conversation_updated_cb)); ++ ++ purple_signal_disconnect (conv_handle, "deleting-conversation", plugin, ++ PURPLE_CALLBACK(messaging_conversation_deleted_cb)); ++ ++ purple_signal_disconnect (conv_handle, "received-im-msg", plugin, ++ PURPLE_CALLBACK(messaging_new_message_cb)); ++ ++ purple_signal_disconnect (conv_handle, "received-chat-msg", plugin, ++ PURPLE_CALLBACK(messaging_new_chat_cb)); ++ ++ purple_signal_disconnect (savedstatus_handle, "savedstatus-changed", plugin, ++ PURPLE_CALLBACK(messaging_savedstatus_changed_cb)); ++ + purple_signal_disconnect (conn_handle, "signed-on", plugin, + PURPLE_CALLBACK(event_connection_throttle)); + +@@ -912,6 +1349,12 @@ + + notify_uninit (); + ++ if (m_menu_app) { ++ g_object_unref (m_menu_app); ++ m_menu_app = NULL; ++ pidgin_blist_visibility_manager_remove (); ++ } ++ + /* If this goes off, we were unloaded by the user + and not by shutdown. Same thing as us never + getting loaded at all. */ diff -Nru pidgin-libnotify-0.14/debian/patches/series pidgin-libnotify-0.14/debian/patches/series --- pidgin-libnotify-0.14/debian/patches/series 2012-02-10 14:04:30.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/series 2012-10-21 15:37:15.000000000 -0400 @@ -1,6 +1,6 @@ de_po.diff -indicate.patch force-load.patch it_po.diff best_name.patch -libnotify_0_7.patch +ubuntu_notify_support.patch +messaging_menu.patch diff -Nru pidgin-libnotify-0.14/debian/patches/ubuntu_notify_support.patch pidgin-libnotify-0.14/debian/patches/ubuntu_notify_support.patch --- pidgin-libnotify-0.14/debian/patches/ubuntu_notify_support.patch 1969-12-31 19:00:00.000000000 -0500 +++ pidgin-libnotify-0.14/debian/patches/ubuntu_notify_support.patch 2012-11-12 13:54:05.000000000 -0500 @@ -0,0 +1,803 @@ +--- a/src/pidgin-libnotify.c ++++ b/src/pidgin-libnotify.c +@@ -35,6 +35,7 @@ + + /* for pidgin_create_prpl_icon */ + #include ++#include + + #include + +@@ -42,8 +43,29 @@ + + #define PLUGIN_ID "pidgin-libnotify" + ++#ifdef G_LOG_DOMAIN ++#undef G_LOG_DOMAIN ++#endif ++#define G_LOG_DOMAIN "pidgin-libnotify-plugin" ++ ++#define PIDGIN_DESKTOP_FILE "/usr/share/applications/pidgin.desktop" ++#define BLACKLIST_FILENAME "pidgin-libnotify" ++#define BLACKLIST_DIR "indicators/messages/applications-blacklist" ++ ++/* Prototypes */ ++static void notify_new_message_cb (PurpleAccount *account, const gchar *sender, const gchar *message, int flags, gpointer data); ++ ++/* Globals */ + static GHashTable *buddy_hash; + ++static gboolean notify_supports_actions = FALSE; ++static gboolean notify_supports_append = FALSE; ++static gboolean notify_supports_truncation = FALSE; ++ ++static guint never_loaded = 0; ++ ++static void conv_delete_cb (PurpleConversation * conv, void * data); ++ + static PurplePluginPrefFrame * + get_plugin_pref_frame (PurplePlugin *plugin) + { +@@ -82,6 +104,11 @@ + _("Only when available")); + purple_plugin_pref_frame_add (frame, ppref); + ++ ppref = purple_plugin_pref_new_with_name_and_label ( ++ "/plugins/gtk/libnotify/blocked_nicks", ++ _("Names to remove notifications for")); ++ purple_plugin_pref_frame_add (frame, ppref); ++ + return frame; + } + +@@ -127,7 +154,9 @@ + return; + + just_signed_on_accounts = g_list_prepend (just_signed_on_accounts, account); +- g_timeout_add (5000, event_connection_throttle_cb, (gpointer)account); ++ g_timeout_add_seconds (15, event_connection_throttle_cb, (gpointer)account); ++ ++ return; + } + + /* do NOT g_free() the string returned by this function */ +@@ -148,7 +177,6 @@ + data = purple_buddy_icon_get_data (buddy_icon, &len); + + loader = gdk_pixbuf_loader_new (); +- gdk_pixbuf_loader_set_size (loader, 48, 48); + gdk_pixbuf_loader_write (loader, data, len, NULL); + gdk_pixbuf_loader_close (loader, NULL); + +@@ -163,6 +191,97 @@ + return icon; + } + ++/* ++ * This takes a pixbuf that we want to send to the notify server, and ++ * transforms it to the desired dimensions suitable for a notification. ++ * We scale the pixbuf down to size * size (square), but preserve the ++ * original aspect ratio and fill in the edges with transparent pixels ++ * if the original pixbuf was not square. ++ */ ++static GdkPixbuf * ++normalize_icon (GdkPixbuf *icon, gint size) ++{ ++ gint w, h; ++ int dest_x, dest_y; ++ gdouble max_edge; ++ gint new_width, new_height; ++ GdkPixbuf *scaled_icon; ++ GdkPixbuf *new_icon; ++ ++ w = gdk_pixbuf_get_width (icon); ++ h = gdk_pixbuf_get_height (icon); ++ ++ dest_x = dest_y = 0; ++ ++ max_edge = MAX (w, h); ++ ++ new_width = size * (w / max_edge); ++ new_height = size * (h / max_edge); ++ ++ /* Scale the image down, preserving the aspect ratio */ ++ scaled_icon = gdk_pixbuf_scale_simple (icon, ++ new_width, ++ new_height, ++ GDK_INTERP_HYPER); ++ ++ g_object_unref (icon); ++ ++ /* Create a square pixbuf with an alpha channel, dimensions size * size */ ++ new_icon = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (scaled_icon), ++ TRUE, ++ gdk_pixbuf_get_bits_per_sample (scaled_icon), ++ size, size); ++ ++ /* Clear the pixbuf so it is transparent */ ++ gdk_pixbuf_fill (new_icon, 0x00000000); ++ ++ /* Center the aspect ratio preseved pixbuf in the square pixbuf */ ++ if (new_width > new_height) { ++ dest_y = (new_width - new_height) / 2; ++ } else if (new_height > new_width) { ++ dest_x = (new_height - new_width) / 2; ++ } ++ ++ /* Copy from the aspect ratio-preserved scaled pixbuf into the ++ * new pixbuf, at a centered position. */ ++ gdk_pixbuf_copy_area (scaled_icon, ++ 0, 0, ++ gdk_pixbuf_get_width (scaled_icon), ++ gdk_pixbuf_get_height (scaled_icon), ++ new_icon, ++ dest_x, dest_y); ++ ++ g_object_unref (scaled_icon); ++ ++ return new_icon; ++} ++ ++/* Check the name against the static list of black listed ++ names that we're looking out for. These shouldn't result ++ in either notifications or indicators. */ ++static gboolean ++name_blacklisted (PurpleAccount * account, const gchar * name) ++{ ++ if (account != NULL) { ++ const gchar * username = purple_account_get_username(account); ++ gchar ** userparts = g_strsplit(username, "@", 2); ++ if (g_strcmp0(name, userparts[1]) == 0) { ++ g_strfreev(userparts); ++ return TRUE; ++ } ++ g_strfreev(userparts); ++ } ++ ++ GList * blacklist = purple_prefs_get_string_list("/plugins/gtk/libnotify/blocked_nicks"); ++ GList * pnt; ++ for (pnt = blacklist; pnt != NULL; pnt = g_list_next(pnt)) { ++ if (g_strcmp0(name, (gchar *)pnt->data) == 0) { ++ return TRUE; ++ } ++ } ++ return FALSE; ++} ++ + static void + action_cb (NotifyNotification *notification, + gchar *action, gpointer user_data) +@@ -171,9 +290,9 @@ + PurpleConversation *conv = NULL; + + purple_debug_info (PLUGIN_ID, "action_cb(), " +- "notification: 0x%x, action: '%s'", notification, action); ++ "notification: 0x%x, action: '%s'", GPOINTER_TO_UINT(notification), action); + +- buddy = (PurpleBuddy *)g_object_get_data (G_OBJECT(notification), "buddy"); ++ buddy = (PurpleBuddy *)user_data; + + if (!buddy) { + purple_debug_warning (PLUGIN_ID, "Got no buddy!"); +@@ -193,13 +312,25 @@ + } + + static gboolean +-closed_cb (NotifyNotification *notification) ++notification_list_closed_cb (NotifyNotification *notification, PurpleConversation * conv) + { +- PurpleContact *contact; ++ purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", GPOINTER_TO_UINT(notification)); + +- purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", notification); ++ if (conv != NULL) { ++ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); ++ notifylist = g_list_remove(notifylist, notification); ++ purple_conversation_set_data(conv, "notification-list", notifylist); ++ } ++ g_object_unref(notification); ++ ++ return FALSE; ++} ++ ++static gboolean ++closed_cb (NotifyNotification *notification, PurpleContact * contact) ++{ ++ purple_debug_info (PLUGIN_ID, "closed_cb(), notification: 0x%x\n", GPOINTER_TO_UINT(notification)); + +- contact = (PurpleContact *)g_object_get_data (G_OBJECT(notification), "contact"); + if (contact) + g_hash_table_remove (buddy_hash, contact); + +@@ -212,11 +343,12 @@ + * num_chars is utf-8 characters */ + static gchar * + truncate_escape_string (const gchar *str, +- int num_chars) ++ int num_chars, ++ gboolean escape) + { + gchar *escaped_str; + +- if (g_utf8_strlen (str, num_chars*2+1) > num_chars) { ++ if (!notify_supports_truncation && g_utf8_strlen (str, num_chars*2+1) > num_chars) { + gchar *truncated_str; + gchar *str2; + +@@ -225,11 +357,11 @@ + + g_utf8_strncpy (str2, str, num_chars-2); + truncated_str = g_strdup_printf ("%s..", str2); +- escaped_str = g_markup_escape_text (truncated_str, strlen (truncated_str)); ++ escaped_str = escape ? g_markup_escape_text (truncated_str, strlen (truncated_str)) : g_strdup (truncated_str); + g_free (str2); + g_free (truncated_str); + } else { +- escaped_str = g_markup_escape_text (str, strlen (str)); ++ escaped_str = escape ? g_markup_escape_text (str, strlen (str)) : g_strdup (str); + } + + return escaped_str; +@@ -251,67 +383,105 @@ + static void + notify (const gchar *title, + const gchar *body, +- PurpleBuddy *buddy) ++ PurpleBuddy *buddy, ++ PurpleConversation *conv) + { + NotifyNotification *notification = NULL; +- GdkPixbuf *icon; +- PurpleBuddyIcon *buddy_icon; +- gchar *tr_body; +- PurpleContact *contact; ++ GdkPixbuf *icon = NULL; ++ PurpleBuddyIcon *buddy_icon = NULL; ++ gchar *tr_body = NULL; ++ PurpleContact *contact = NULL; + +- contact = purple_buddy_get_contact (buddy); ++ if (buddy != NULL) { ++ contact = purple_buddy_get_contact (buddy); ++ } + + if (body) +- tr_body = truncate_escape_string (body, 60); ++ tr_body = truncate_escape_string (body, 60, TRUE); + else + tr_body = NULL; + +- notification = g_hash_table_lookup (buddy_hash, contact); ++ /* If we're appending we shouldn't update an already ++ existing notification */ ++ if (conv == NULL && contact != NULL) { ++ notification = g_hash_table_lookup (buddy_hash, contact); ++ } + ++ /* This will only happen if we're a login message */ + if (notification != NULL) { + notify_notification_update (notification, title, tr_body, NULL); ++ + /* this shouldn't be necessary, file a bug */ + notify_notification_show (notification, NULL); + + purple_debug_info (PLUGIN_ID, "notify(), update: " + "title: '%s', body: '%s', buddy: '%s'\n", +- title, tr_body, best_name (buddy)); ++ title, tr_body, buddy != NULL ? best_name (buddy) : "(null)"); + + g_free (tr_body); + return; + } +- notification = notify_notification_new (title, tr_body, NULL, NULL); ++ ++ notification = notify_notification_new (title, tr_body, "notification-message-im"); + purple_debug_info (PLUGIN_ID, "notify(), new: " + "title: '%s', body: '%s', buddy: '%s'\n", +- title, tr_body, best_name (buddy)); ++ title, tr_body, buddy != NULL ? best_name (buddy) : "(null)"); + + g_free (tr_body); + +- buddy_icon = purple_buddy_get_icon (buddy); +- if (buddy_icon) { ++ if (notify_supports_append) { ++ if (conv != NULL) { ++ notify_notification_set_hint_string(notification, "x-canonical-append", "allow"); ++ } ++ } ++ ++ if (buddy != NULL) { ++ buddy_icon = purple_buddy_get_icon (buddy); ++ } ++ ++ if (buddy_icon != NULL) { + icon = pixbuf_from_buddy_icon (buddy_icon); + purple_debug_info (PLUGIN_ID, "notify(), has a buddy icon.\n"); + } else { +- icon = pidgin_create_prpl_icon (buddy->account, 1); +- purple_debug_info (PLUGIN_ID, "notify(), has a prpl icon.\n"); ++ if (buddy != NULL) { ++ icon = pidgin_create_prpl_icon (buddy->account, PIDGIN_PRPL_ICON_LARGE); ++ purple_debug_info (PLUGIN_ID, "notify(), has a prpl icon.\n"); ++ } + } + +- if (icon) { ++ icon = normalize_icon (icon, 48); ++ ++ if (icon != NULL) { + notify_notification_set_icon_from_pixbuf (notification, icon); + g_object_unref (icon); +- } else { +- purple_debug_warning (PLUGIN_ID, "notify(), couldn't find any icon!\n"); +- } +- +- g_hash_table_insert (buddy_hash, contact, notification); + +- g_object_set_data (G_OBJECT(notification), "contact", contact); +- +- g_signal_connect (notification, "closed", G_CALLBACK(closed_cb), NULL); ++ GValue iconname = {0}; ++ g_value_init(&iconname, G_TYPE_STRING); ++ g_value_set_static_string(&iconname, ""); ++ g_object_set_property(G_OBJECT(notification), "icon-name", &iconname); ++ } ++ ++ if (contact != NULL && conv == NULL) { ++ g_hash_table_insert (buddy_hash, contact, notification); ++ ++ g_signal_connect (notification, "closed", G_CALLBACK(closed_cb), contact); ++ } ++ if (conv != NULL) { ++ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); ++ notifylist = g_list_append(notifylist, notification); ++ purple_conversation_set_data(conv, "notification-list", notifylist); ++ g_signal_connect(notification, "closed", G_CALLBACK(notification_list_closed_cb), conv); ++ } ++ if (contact == NULL && conv == NULL) { ++ /* Should never happen, but just in case, let's not have a memory leak */ ++ g_signal_connect(notification, "closed", G_CALLBACK(g_object_unref), NULL); ++ } + + notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); + +- notify_notification_add_action (notification, "show", _("Show"), action_cb, NULL, NULL); ++ if (notify_supports_actions) { ++ notify_notification_add_action (notification, "show", _("Show"), action_cb, buddy, NULL); ++ } + + if (!notify_notification_show (notification, NULL)) { + purple_debug_error (PLUGIN_ID, "notify(), failed to send notification\n"); +@@ -323,7 +493,7 @@ + notify_buddy_signon_cb (PurpleBuddy *buddy, + gpointer data) + { +- gchar *tr_name, *title; ++ gchar *tr_name; + gboolean blocked; + + g_return_if_fail (buddy); +@@ -341,21 +511,18 @@ + if (!should_notify_unavailable (purple_buddy_get_account (buddy))) + return; + +- tr_name = truncate_escape_string (best_name (buddy), 25); +- +- title = g_strdup_printf (_("%s signed on"), tr_name); ++ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); + +- notify (title, NULL, buddy); ++ notify (tr_name, _("is online"), buddy, NULL); + + g_free (tr_name); +- g_free (title); + } + + static void + notify_buddy_signoff_cb (PurpleBuddy *buddy, + gpointer data) + { +- gchar *tr_name, *title; ++ gchar *tr_name; + gboolean blocked; + + g_return_if_fail (buddy); +@@ -373,42 +540,61 @@ + if (!should_notify_unavailable (purple_buddy_get_account (buddy))) + return; + +- tr_name = truncate_escape_string (best_name (buddy), 25); +- +- title = g_strdup_printf (_("%s signed off"), tr_name); ++ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); + +- notify (title, NULL, buddy); ++ notify (tr_name, _("is offline"), buddy, NULL); + + g_free (tr_name); +- g_free (title); + } + + static void + notify_msg_sent (PurpleAccount *account, + const gchar *sender, +- const gchar *message) ++ const gchar *message, ++ PurpleConversation * conv) + { +- PurpleBuddy *buddy; +- gchar *title, *body, *tr_name; ++ PurpleBuddy *buddy = NULL; ++ gchar *body = NULL, *tr_name = NULL; + gboolean blocked; + +- buddy = purple_find_buddy (account, sender); +- if (!buddy) +- return; +- + blocked = purple_prefs_get_bool ("/plugins/gtk/libnotify/blocked"); + if (!purple_privacy_check(account, sender) && blocked) + return; + +- tr_name = truncate_escape_string (best_name (buddy), 25); ++ if (g_list_find (just_signed_on_accounts, account)) ++ return; ++ ++ buddy = purple_find_buddy (account, sender); ++ ++ if (buddy != NULL) { ++ tr_name = truncate_escape_string (best_name (buddy), 25, FALSE); ++ } else { ++ if (conv != NULL) { ++ const gchar * temp = purple_conversation_get_title(conv); ++ if (temp != NULL) { ++ if (sender == NULL || !g_strcmp0(sender, temp)) { ++ tr_name = g_strdup(temp); ++ } else { ++ tr_name = g_strdup_printf("%s (%s)", sender, temp); ++ } ++ } else { ++ if (sender != NULL) { ++ tr_name = g_strdup(sender); ++ } ++ } ++ } ++ } ++ ++ if (tr_name == NULL) { ++ purple_debug_warning(PLUGIN_ID, "Unable to find a title for the notification"); ++ return; ++ } + +- title = g_strdup_printf (_("%s says:"), tr_name); + body = purple_markup_strip_html (message); + +- notify (title, body, buddy); ++ notify (tr_name, body, buddy, conv); + + g_free (tr_name); +- g_free (title); + g_free (body); + } + +@@ -424,24 +610,38 @@ + if (!purple_prefs_get_bool ("/plugins/gtk/libnotify/newmsg")) + return; + ++ if (name_blacklisted(account, sender)) return; ++ + conv = purple_find_conversation_with_account (PURPLE_CONV_TYPE_IM, sender, account); + + #ifndef DEBUG /* in debug mode, always show notifications */ + if (conv && purple_conversation_has_focus (conv)) { +- purple_debug_info (PLUGIN_ID, "Conversation has focus 0x%x\n", conv); ++ purple_debug_info (PLUGIN_ID, "Conversation has focus 0x%x\n", GPOINTER_TO_UINT(conv)); + return; + } + #endif + + if (conv && purple_prefs_get_bool ("/plugins/gtk/libnotify/newconvonly")) { +- purple_debug_info (PLUGIN_ID, "Conversation is not new 0x%x\n", conv); ++ purple_debug_info (PLUGIN_ID, "Conversation is not new 0x%x\n", GPOINTER_TO_UINT(conv)); ++ return; ++ } ++ ++ if (conv == NULL) { + return; + } + + if (!should_notify_unavailable (account)) + return; + +- notify_msg_sent (account, sender, message); ++ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); ++ if (pconv != NULL) { ++ if (pconv->entry != NULL && pconv->imhtml != NULL) { ++ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { ++ purple_debug_warning(PLUGIN_ID, "Pidgin conversation's widgets are in focus"); ++ return; ++ }}} ++ ++ notify_msg_sent (account, sender, message, conv); + } + + static void +@@ -457,10 +657,182 @@ + if (nick && !strcmp (sender, nick)) + return; + +- if (!g_strstr_len (message, strlen(message), nick)) ++ if (!purple_utf8_has_word (message, nick)) ++ return; ++ ++ PidginConversation * pconv = PIDGIN_CONVERSATION(conv); ++ if (pconv != NULL) { ++ if (pconv->entry != NULL && pconv->imhtml != NULL) { ++ if (GTK_WIDGET_HAS_FOCUS(pconv->entry) || GTK_WIDGET_HAS_FOCUS(pconv->imhtml)) { ++ purple_debug_warning(PLUGIN_ID, "Pidgin conversation's widgets are in focus"); + return; ++ }}} ++ ++ if (name_blacklisted(account, sender)) return; ++ ++ notify_msg_sent (account, sender, message, conv); ++} ++ ++static void ++conv_delete_cb (PurpleConversation * conv, void * data) ++{ ++ GList * notifylist = purple_conversation_get_data(conv, "notification-list"); ++ if (notifylist != NULL) { ++ GList * i; ++ for (i = notifylist; i != NULL; i = i->next) { ++ NotifyNotification * notification = NOTIFY_NOTIFICATION(i->data); ++ if (notification == NULL) break; ++ ++ g_signal_handlers_disconnect_by_func(G_OBJECT(notification), notification_list_closed_cb, conv); ++ notify_notification_close(notification, NULL); /* Don't care if it fails, it's going to die. */ ++ g_object_unref(G_OBJECT(notification)); ++ } ++ g_list_free(notifylist); ++ ++ purple_conversation_set_data(conv, "notification-list", NULL); ++ } ++ ++ return; ++} ++ ++static void ++remove_from_blacklist (void) ++{ ++ gchar *bpath; ++ ++ bpath = g_build_filename (g_get_user_config_dir(), ++ BLACKLIST_DIR, ++ BLACKLIST_FILENAME, ++ NULL); ++ ++ if (g_file_test (bpath, G_FILE_TEST_EXISTS)) { ++ GFile *bfile; ++ bfile = g_file_new_for_path (bpath); ++ ++ if (bfile) { ++ GError *error = NULL; ++ g_file_delete (bfile, NULL, &error); ++ ++ if (error) { ++ g_warning ("Unable to remove blacklist file: %s", error->message); ++ g_error_free (error); ++ } ++ ++ g_object_unref (bfile); ++ } ++ } ++ ++ g_free (bpath); ++ ++ return; ++} ++ ++static gboolean ++plugin_never_loaded (gpointer data) ++{ ++ gchar *bdir; ++ gchar *bpath; ++ GError *error = NULL; ++ ++ bdir = g_build_filename (g_get_user_config_dir (), ++ BLACKLIST_DIR, ++ NULL); ++ if (!g_file_test (bdir, G_FILE_TEST_IS_DIR)) { ++ GFile *dirfile; ++ ++ dirfile = g_file_new_for_path (bdir); ++ if (dirfile) { ++ g_file_make_directory_with_parents (dirfile, ++ NULL, ++ &error); ++ if (error) { ++ g_warning ("Unable to create blacklist directory: %s", ++ error->message); ++ g_error_free (error); ++ g_object_unref (dirfile); ++ g_free (bdir); ++ return FALSE; ++ } ++ } else { ++ g_warning ("Unable to create blacklist directory: Unable to create " ++ "GFile for path %s", bdir); ++ g_free (bdir); ++ return FALSE; ++ } ++ ++ g_object_unref (dirfile); ++ } ++ g_free (bdir); ++ ++ bpath = g_build_filename (g_get_user_config_dir (), ++ BLACKLIST_DIR, ++ BLACKLIST_FILENAME, ++ NULL); ++ ++ if (g_file_set_contents (bpath, ++ PIDGIN_DESKTOP_FILE, ++ -1, ++ &error)) { ++ g_debug ("Successfully wrote blacklist file to %s", bpath); ++ } else { ++ g_debug ("Unable to write blacklist file to %s: %s", ++ bpath, ++ error ? error->message : "Unknown"); ++ if (error) ++ g_error_free (error); ++ } ++ ++ g_free (bpath); ++ ++ return FALSE; ++} ++ ++static gboolean ++force_load_once (gpointer data) ++{ ++ PurplePlugin * plugin = (PurplePlugin *)data; ++ ++ if (!purple_prefs_get_bool("/plugins/gtk/libnotify/auto_loaded")) { ++ purple_plugin_load(plugin); ++ purple_plugins_save_loaded(PIDGIN_PREFS_ROOT "/plugins/loaded"); ++ purple_prefs_set_bool("/plugins/gtk/libnotify/auto_loaded", TRUE); ++ } ++ ++ return FALSE; ++} ++ ++static void ++notify_check_caps_helper (gpointer data, gpointer user_data) ++{ ++ gchar * cap = (gchar *)data; ++ ++ if (cap == NULL) return; + +- notify_msg_sent (account, sender, message); ++ if (!strcmp(cap, "actions")) { ++ notify_supports_actions = TRUE; ++ } else if (!strcmp(cap, "append")) { ++ notify_supports_append = TRUE; ++ } else if (!strcmp(cap, "x-canonical-append")) { ++ notify_supports_append = TRUE; ++ } else if (!strcmp(cap, "truncation")) { ++ notify_supports_truncation = TRUE; ++ } else if (!strcmp(cap, "x-canonical-truncation")) { ++ notify_supports_truncation = TRUE; ++ } ++ ++ return; ++} ++ ++static void ++notify_check_caps(void) ++{ ++ GList * caps = notify_get_server_caps(); ++ ++ g_list_foreach(caps, notify_check_caps_helper, NULL); ++ g_list_foreach(caps, (GFunc)g_free, NULL); ++ g_list_free(caps); ++ ++ return; + } + + static gboolean +@@ -473,6 +845,14 @@ + return FALSE; + } + ++ /* They really do love me! */ ++ if (never_loaded != 0) { ++ g_source_remove(never_loaded); ++ } ++ remove_from_blacklist(); ++ ++ notify_check_caps(); ++ + conv_handle = purple_conversations_get_handle (); + blist_handle = purple_blist_get_handle (); + conn_handle = purple_connections_get_handle(); +@@ -491,6 +871,9 @@ + purple_signal_connect (conv_handle, "received-chat-msg", plugin, + PURPLE_CALLBACK(notify_chat_nick), NULL); + ++ purple_signal_connect (conv_handle, "deleting-conversation", plugin, ++ PURPLE_CALLBACK(conv_delete_cb), NULL); ++ + /* used just to not display the flood of guifications we'd get */ + purple_signal_connect (conn_handle, "signed-on", plugin, + PURPLE_CALLBACK(event_connection_throttle), NULL); +@@ -519,6 +902,9 @@ + purple_signal_disconnect (conv_handle, "received-chat-msg", plugin, + PURPLE_CALLBACK(notify_chat_nick)); + ++ purple_signal_disconnect (conv_handle, "deleting-conversation", plugin, ++ PURPLE_CALLBACK(conv_delete_cb)); ++ + purple_signal_disconnect (conn_handle, "signed-on", plugin, + PURPLE_CALLBACK(event_connection_throttle)); + +@@ -526,6 +912,11 @@ + + notify_uninit (); + ++ /* If this goes off, we were unloaded by the user ++ and not by shutdown. Same thing as us never ++ getting loaded at all. */ ++ never_loaded = g_timeout_add_seconds(30, plugin_never_loaded, NULL); ++ + return TRUE; + } + +@@ -562,20 +953,6 @@ + &prefs_info /* prefs info */ + }; + +-static gboolean +-force_load_once (gpointer data) +-{ +- PurplePlugin * plugin = (PurplePlugin *)data; +- +- if (!purple_prefs_get_bool("/plugins/gtk/libnotify/auto_loaded")) { +- purple_plugin_load(plugin); +- purple_plugins_save_loaded(PIDGIN_PREFS_ROOT "/plugins/loaded"); +- purple_prefs_set_bool("/plugins/gtk/libnotify/auto_loaded", TRUE); +- } +- +- return FALSE; +-} +- + static void + init_plugin (PurplePlugin *plugin) + { +@@ -586,7 +963,24 @@ + info.summary = _("Displays popups via libnotify."); + info.description = _("Pidgin-libnotify:\nDisplays popups via libnotify."); + ++ /* If we get init'd and we never get loaded ++ chances are the user hasn't enabled this ++ plugin. */ ++ never_loaded = g_timeout_add_seconds(30, plugin_never_loaded, NULL); ++ + purple_prefs_add_none ("/plugins/gtk/libnotify"); ++ ++ /* Create a list of nicks that are commonly used by ++ IRC servers but don't represent real people. */ ++ GList * nicklist = NULL; ++ nicklist = g_list_append(nicklist, "NickServ"); ++ nicklist = g_list_append(nicklist, "ChanServ"); ++ nicklist = g_list_append(nicklist, "MsgServ"); ++ nicklist = g_list_append(nicklist, "freenode-connect"); ++ ++ purple_prefs_add_string_list ("/plugins/gtk/libnotify/blocked_nicks", nicklist); ++ g_list_free(nicklist); ++ + purple_prefs_add_bool ("/plugins/gtk/libnotify/newmsg", TRUE); + purple_prefs_add_bool ("/plugins/gtk/libnotify/blocked", TRUE); + purple_prefs_add_bool ("/plugins/gtk/libnotify/newconvonly", FALSE);