From: Christopher Aillon <caillon@redhat.com>
Date: Thu, 7 Apr 2011 19:34:14 -0700
Subject: [PATCH] Link directly against libnotify

Dynamically loading the library isn't ideal since the soname
can change silently on us.  Additionally, notify-send is
shipped as part of libnotify, so we aren't actually bringing
in a new dependency.  Since we'd need to patch the source and
rebuild for new sonames anyway, there's little benefit to
dynamically loading libnotify.

Plus, this has the benefit of cleaning up the code, as well as
ensuring we'll catch any future soname changes sooner.

https://bugzilla.redhat.com/show_bug.cgi?id=693362
---
 configure.in             |   23 +++++++
 src/fe-gtk/plugin-tray.c |  144 ++++++++++-------------------------------------
 2 files changed, 55 insertions(+), 112 deletions(-)

diff -p -U8 xchat-2.8.8/configure.in.libnotifyso4 xchat-2.8.8/configure.in
--- xchat-2.8.8/configure.in.libnotifyso4	2010-05-29 23:01:16.000000000 -0700
+++ xchat-2.8.8/configure.in	2011-04-07 19:27:00.448137113 -0700
@@ -34,16 +34,17 @@ AH_VERBATIM([PREFIX],[#undef PREFIX])
 AH_VERBATIM([XCHATLIBDIR],[#undef XCHATLIBDIR])
 AH_VERBATIM([XCHATSHAREDIR],[#undef XCHATSHAREDIR])
 AH_VERBATIM([SOCKS],[#undef SOCKS])
 AH_VERBATIM([USE_MSPROXY],[#undef USE_MSPROXY])
 dnl AH_VERBATIM([USE_GNOME],[#undef USE_GNOME])
 AH_VERBATIM([USE_SHM],[#undef USE_SHM])
 AH_VERBATIM([USE_GTKSPELL],[#undef USE_GTKSPELL])
 AH_VERBATIM([USE_LIBSEXY],[#undef USE_LIBSEXY])
+AH_VERBATIM([USE_LIBNOTIFY],[#undef USE_LIBNOTIFY])
 AH_VERBATIM([USE_IPV6],[#undef USE_IPV6])
 AH_VERBATIM([USE_MMX],[#undef USE_MMX])
 AH_VERBATIM([USE_OPENSSL],[#undef USE_OPENSSL])
 AH_VERBATIM([USE_PLUGIN],[#undef USE_PLUGIN])
 AH_VERBATIM([USE_XFT],[#undef USE_XFT])
 AH_VERBATIM([USE_XLIB],[#undef USE_XLIB])
 AH_VERBATIM([USE_SIGACTION],[#undef USE_SIGACTION])
 AH_VERBATIM([USING_FREEBSD],[#undef USING_FREEBSD])
@@ -126,16 +127,20 @@ AC_ARG_ENABLE(tcl,
 AC_ARG_ENABLE(plugin,
 [  --disable-plugin        disable plugin support],
         plugin=$enableval, plugin=yes)
 
 AC_ARG_ENABLE(dbus,
 [  --disable-dbus          disable DBUS support],
         dbus=$enableval, dbus=yes)
 
+AC_ARG_ENABLE(libnotify,
+[  --disable-libnotify     disable libnotify support],
+        libnotify=$enableval, libnotify=yes)
+
 AC_ARG_ENABLE(mmx,
 [  --disable-mmx           disable MMX assembly routines],
         mmx=$enableval, mmx=yes)
 
 AC_ARG_ENABLE(shm,
 [  --enable-shm            enable use of XShm for fast tinting (default: no)],
         shm=$enableval, shm=no)
 
@@ -482,16 +487,32 @@ if test "x$dbus" = "xyes" ; then
 
 		DBUS_SERVICES_DIR="$DATADIR/dbus-1/services"
 		AC_SUBST(DBUS_SERVICES_DIR)
 		AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is])
 	fi
 fi
 
 dnl *********************************************************************
+dnl ** LIBNOTIFY ********************************************************
+dnl *********************************************************************
+
+if test "x$libnotify" = "xyes" ; then
+	PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= 0.4, [], [
+		AC_MSG_RESULT(no)
+		libnotify=no
+	])
+	if test "$libnotify" != "no" ; then
+		GUI_LIBS="$GUI_LIBS $LIBNOTIFY_LIBS"
+		GUI_CFLAGS="$GUI_CFLAGS $LIBNOTIFY_CFLAGS"
+		AC_DEFINE(USE_LIBNOTIFY)
+	fi
+fi
+
+dnl *********************************************************************
 dnl ** SPELL ************************************************************
 dnl *********************************************************************
 
 if test "$spell" = "gtkspell" ; then
 	PKG_CHECK_MODULES(GTKSPELL, gtkspell-2.0 >= 2.0.2, [], [
 		AC_MSG_RESULT(no)
 		spell=no
 	])
@@ -519,16 +540,17 @@ if test "$spell" = "static" ; then
 fi
 
 dnl *********************************************************************
 dnl ** CONDITIONALS *****************************************************
 dnl *********************************************************************
 
 AM_CONDITIONAL(USE_OPENSSL, test "x$openssl" = "xyes")
 AM_CONDITIONAL(USE_LIBSEXY, test "x$spell" = "xstatic")
+AM_CONDITIONAL(USE_LIBNOTIFY, test "x$libnotify" = "xyes")
 AM_CONDITIONAL(DO_TEXT, test "x$textfe" = "xyes")
 AM_CONDITIONAL(DO_GTK, test "x$gtkfe" = "xyes")
 AM_CONDITIONAL(DO_PERL, test "x$perl" = "xyes")
 AM_CONDITIONAL(DO_PYTHON, test "x$python" = "xyes")
 AM_CONDITIONAL(DO_TCL, test "x$tcl" = "xyes")
 AM_CONDITIONAL(DO_PLUGIN, test "x$plugin" = "xyes")
 AM_CONDITIONAL(USE_DBUS, test "x$dbus" = "xyes")
 AM_CONDITIONAL(DO_GCONF, test "x$GCONFTOOL" != "xno")
@@ -807,16 +829,17 @@ echo mmx tinting ......... : $mmx\	spell
 echo XShm tinting ........ : $shm\	plugin interface ...... : $plugin
 if test "$xft" = no; then
   echo text backend ........ : pango\	nls/gettext ........... : $USE_NLS
 else
   echo text backend ........ : xft\	nls/gettext ........... : $USE_NLS
 fi
 echo openssl support ..... : $openssl\	ipv6 support .......... : $ipv6
 echo dbus support ........ : $dbus\	msproxy ntlm \(ISA\) .... : $have_ntlm
+echo libnotify support ... : $libnotify
 echo
 echo The binary will be installed in $prefix/bin
 echo
 
 if test "$gtkfe" = no; then
 	echo Warning: The GTK \(GUI\) frontend will not be built.
 	echo
 fi
diff -p -U8 xchat-2.8.8/src/fe-gtk/plugin-tray.c.libnotifyso4 xchat-2.8.8/src/fe-gtk/plugin-tray.c
--- xchat-2.8.8/src/fe-gtk/plugin-tray.c.libnotifyso4	2011-04-07 17:57:27.524307905 -0700
+++ xchat-2.8.8/src/fe-gtk/plugin-tray.c	2011-04-07 19:18:33.429475719 -0700
@@ -10,17 +10,27 @@
 #include "../common/fe.h"
 #include "../common/util.h"
 #include "fe-gtk.h"
 #include "pixmaps.h"
 #include "maingui.h"
 #include "menu.h"
 #include <gtk/gtk.h>
 
-#define LIBNOTIFY
+#ifdef USE_LIBNOTIFY
+#include <libnotify/notify.h>
+#ifndef NOTIFY_CHECK_VERSION
+#define NOTIFY_CHECK_VERSION(x,y,z) 0
+#endif
+#if NOTIFY_CHECK_VERSION(0,7,0)
+#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c)
+#else
+#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c,d)
+#endif
+#endif
 
 typedef enum	/* current icon status */
 {
 	TS_NONE,
 	TS_MESSAGE,
 	TS_HIGHLIGHT,
 	TS_FILEOFFER,
 	TS_CUSTOM /* plugin */
@@ -112,90 +122,16 @@ tray_count_networks (void)
 
 void
 fe_tray_set_tooltip (const char *text)
 {
 	if (sticon)
 		gtk_status_icon_set_tooltip (sticon, text);
 }
 
-#ifdef LIBNOTIFY
-
-/* dynamic access to libnotify.so */
-
-static void *nn_mod = NULL;
-/* prototypes */
-static gboolean (*nn_init) (char *);
-static void (*nn_uninit) (void);
-/* recent versions of libnotify don't take the fourth GtkWidget argument, but passing an
- * extra NULL argument will be fine */
-static void *(*nn_new) (const gchar *summary, const gchar *message, const gchar *icon, gpointer dummy);
-static gboolean (*nn_show) (void *noti, GError **error);
-static void (*nn_set_timeout) (void *noti, gint timeout);
-
-static void
-libnotify_cleanup (void)
-{
-	if (nn_mod)
-	{
-		nn_uninit ();
-		g_module_close (nn_mod);
-		nn_mod = NULL;
-	}
-}
-
-static gboolean
-libnotify_notify_new (const char *title, const char *text, GtkStatusIcon *icon)
-{
-	void *noti;
-
-	if (!nn_mod)
-	{
-		nn_mod = g_module_open ("libnotify", G_MODULE_BIND_LAZY);
-		if (!nn_mod)
-		{
-			nn_mod = g_module_open ("libnotify.so.1", G_MODULE_BIND_LAZY);
-			if (!nn_mod)
-				return FALSE;
-		}
-
-		if (!g_module_symbol (nn_mod, "notify_init", (gpointer)&nn_init))
-			goto bad;
-		if (!g_module_symbol (nn_mod, "notify_uninit", (gpointer)&nn_uninit))
-			goto bad;
-		if (!g_module_symbol (nn_mod, "notify_notification_new", (gpointer)&nn_new))
-			goto bad;
-		if (!g_module_symbol (nn_mod, "notify_notification_show", (gpointer)&nn_show))
-			goto bad;
-		if (!g_module_symbol (nn_mod, "notify_notification_set_timeout", (gpointer)&nn_set_timeout))
-			goto bad;
-		if (!nn_init (PACKAGE_NAME))
-			goto bad;
-	}
-
-	text = strip_color (text, -1, STRIP_ALL|STRIP_ESCMARKUP);
-	title = strip_color (title, -1, STRIP_ALL);
-	noti = nn_new (title, text, XCHATSHAREDIR"/pixmaps/xchat.png", NULL);
-	g_free ((char *)title);
-	g_free ((char *)text);
-
-	nn_set_timeout (noti, prefs.input_balloon_time*1000);
-	nn_show (noti, NULL);
-	g_object_unref (G_OBJECT (noti));
-
-	return TRUE;
-
-bad:
-	g_module_close (nn_mod);
-	nn_mod = NULL;
-	return FALSE;
-}
-
-#endif
-
 void
 fe_tray_set_balloon (const char *title, const char *text)
 {
 #ifndef WIN32
 	const char *argv[8];
 	const char *path;
 	char time[16];
 	WinStatus ws;
@@ -208,52 +144,36 @@ fe_tray_set_balloon (const char *title, 
 	/* bit 1 of flags means "no balloons unless hidden/iconified" */
 	if (ws != WS_HIDDEN && (prefs.gui_tray_flags & 2))
 		return;
 
 	/* FIXME: this should close the current balloon */
 	if (!text)
 		return;
 
-#ifdef LIBNOTIFY
-	/* try it via libnotify.so */
-	if (libnotify_notify_new (title, text, sticon))
-		return;	/* success */
-#endif
+#ifdef USE_LIBNOTIFY
+	NotifyNotification *notification;
+	char *notify_text, *notify_title;
 
-	/* try it the crude way */
-	path = g_find_program_in_path ("notify-send");
-	if (path)
-	{
-		sprintf(time, "%d000",prefs.input_balloon_time);
-		argv[0] = path;
-		argv[1] = "-i";
-		argv[2] = "gtk-dialog-info";
-		if (access (XCHATSHAREDIR"/pixmaps/xchat.png", R_OK) == 0)
-			argv[2] = XCHATSHAREDIR"/pixmaps/xchat.png";
-		argv[3] = "-t";
-		argv[4] = time;
-		argv[5] = title;
-		text = strip_color (text, -1, STRIP_ALL|STRIP_ESCMARKUP);
-		argv[6] = text;
-		argv[7] = NULL;
-		xchat_execv (argv);
-		g_free ((char *)path);
-		g_free ((char *)text);
-	}
-	else
-	{
-		/* show this error only once */
-		static unsigned char said_it = FALSE;
-		if (!said_it)
-		{
-			said_it = TRUE;
-			fe_message (_("Cannot find 'notify-send' to open balloon alerts.\nPlease install libnotify."), FE_MSG_ERROR);
-		}
-	}
+	if (!notify_is_initted())
+		notify_init(PACKAGE_NAME);
+
+	notify_text = strip_color (text, -1, STRIP_ALL|STRIP_ESCMARKUP);
+	notify_title = strip_color (title, -1, STRIP_ALL);
+
+	notification = XC_NOTIFY_NEW (notify_title, notify_text, XCHATSHAREDIR"/pixmaps/xchat.png", NULL);
+
+	g_free ((char *)notify_title);
+	g_free ((char *)notify_text);
+
+	notify_notification_set_timeout (notification, prefs.input_balloon_time*1000);
+	notify_notification_show (notification, NULL);
+
+	g_object_unref (notification);
+#endif
 #endif
 }
 
 static void
 tray_set_balloonf (const char *text, const char *format, ...)
 {
 	va_list args;
 	char *buf;
@@ -840,13 +760,13 @@ tray_plugin_init (xchat_plugin *plugin_h
 	return 1;       /* return 1 for success */
 }
 
 int
 tray_plugin_deinit (xchat_plugin *plugin_handle)
 {
 #ifdef WIN32
 	tray_cleanup ();
-#elif defined(LIBNOTIFY)
-	libnotify_cleanup ();
+#elif defined(USE_LIBNOTIFY)
+	notify_uninit ();
 #endif
 	return 1;
 }
