diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | applets/Makefile.am | 2 | ||||
-rw-r--r-- | applets/startup-notify/Makefile.am | 15 | ||||
-rw-r--r-- | applets/startup-notify/marshal.list | 1 | ||||
-rw-r--r-- | applets/startup-notify/startup.c | 177 | ||||
-rw-r--r-- | configure.ac | 14 |
6 files changed, 151 insertions, 70 deletions
@@ -1,5 +1,17 @@ 2008-02-18 Ross Burton <ross@openedhand.com> + * configure.ac: + Don't check for libnotify. + + * applets/Makefile.am: + Build startup-notify if we have DBus. + + * applets/startup-notify: + Don't use libnotify as it doesn't conform to the specification and + makes blocking DBus calls. Instead, call it directly. + +2008-02-18 Ross Burton <ross@openedhand.com> + * applets/clock/clock.c: Don't set a colour in the code, let the theme style it. diff --git a/applets/Makefile.am b/applets/Makefile.am index cbac0e7..aae9972 100644 --- a/applets/Makefile.am +++ b/applets/Makefile.am @@ -6,7 +6,7 @@ endif if HAVE_LIBSN SUBDIRS += startup -if HAVE_LIBNOTIFY +if HAVE_DBUS SUBDIRS += startup-notify endif endif diff --git a/applets/startup-notify/Makefile.am b/applets/startup-notify/Makefile.am index 74b7273..550606a 100644 --- a/applets/startup-notify/Makefile.am +++ b/applets/startup-notify/Makefile.am @@ -2,13 +2,22 @@ AM_CPPFLAGS=-DPKGDATADIR=\"$(pkgdatadir)\" \ -DGETTEXT_PACKAGE=\"matchbox-panel\" AM_CFLAGS = -Wall -g $(MATCHBOX_PANEL_CFLAGS) \ -I$(top_srcdir) -I$(top_builddir) -Werror \ - $(SN_CFLAGS) $(LIBNOTIFY_CFLAGS) + $(SN_CFLAGS) $(DBUS_CFLAGS) appletdir = $(pkglibdir) applet_LTLIBRARIES = libstartup-notify.la -libstartup_notify_la_SOURCES = startup.c -libstartup_notify_la_LIBADD = $(SN_LIBS) $(LIBNOTIFY_LIBS) +libstartup_notify_la_SOURCES = startup.c $(MARSHALS) +libstartup_notify_la_LIBADD = $(SN_LIBS) $(DBUS_LIBS) libstartup_notify_la_LDFLAGS = -avoid-version +MARSHALS = marshal.c marshal.h +%.c: %.list + $(GLIB_GENMARSHAL) --prefix=mb_marshal $^ --body > $@ +%.h: %.list + $(GLIB_GENMARSHAL) --prefix=mb_marshal $^ --header > $@ + +BUILT_SOURCES = $(MARSHALS) +CLEANFILES = $(BUILT_SOURCES) + MAINTAINERCLEANFILES = Makefile.in diff --git a/applets/startup-notify/marshal.list b/applets/startup-notify/marshal.list new file mode 100644 index 0000000..6cb7431 --- /dev/null +++ b/applets/startup-notify/marshal.list @@ -0,0 +1 @@ +VOID:UINT,UINT diff --git a/applets/startup-notify/startup.c b/applets/startup-notify/startup.c index 48158be..cb5aa01 100644 --- a/applets/startup-notify/startup.c +++ b/applets/startup-notify/startup.c @@ -1,21 +1,20 @@ /* - * startup-monitor - A tray app that provides feedback on application startup. + * startup-notify: invisible applet which fires a notification when an + * application is started. * - * Copyright 2004 - 2007, Openedhand Ltd. - * By Matthew Allum <mallum@o-hand.com>, - * Stefan Schmidt <stefan@openmoko.org>, + * Copyright 2004 - 2008, Openedhand Ltd. * Ross Burton <ross@openedhand.com> + * Portions by Matthew Allum <mallum@o-hand.com>, + * Stefan Schmidt <stefan@openmoko.org>. * - * Originally based on mb-applet-startup-monitor + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; version 2 of the license. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * */ @@ -23,6 +22,8 @@ #include <stdlib.h> #include <time.h> +#include <dbus/dbus-glib.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -33,9 +34,9 @@ #define SN_API_NOT_YET_FROZEN 1 #include <libsn/sn.h> -#include <libnotify/notify.h> #include <string.h> +#include "marshal.h" #define TIMEOUT 20 @@ -50,7 +51,8 @@ typedef struct { GdkWindow *root_window; SnDisplay *sn_display; GList *launch_list; - NotifyNotification *notify; + DBusGProxy *proxy; + guint notify_id; } StartupApplet; static GdkFilterReturn filter_func (GdkXEvent *gdk_xevent, @@ -58,12 +60,46 @@ static GdkFilterReturn filter_func (GdkXEvent *gdk_xevent, static gboolean timeout (StartupApplet *applet); +/* + * Notify code + */ + +static void +notify_done (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + StartupApplet *applet = user_data; + GError *error = NULL; + + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_UINT, &applet->notify_id, G_TYPE_INVALID); + if (error) { + g_printerr ("Cannot send notification: %s", error->message); + g_error_free (error); + } +} + +void +notify_send (StartupApplet *applet, const char *summary) +{ + dbus_g_proxy_begin_call (applet->proxy, "Notify", + notify_done, applet, NULL, + G_TYPE_STRING, "matchbox-panel", + G_TYPE_UINT, applet->notify_id, + G_TYPE_STRING, NULL, /* icon name */ + G_TYPE_STRING, summary, + G_TYPE_STRING, NULL, /* body */ + G_TYPE_STRV, NULL, /* actions */ + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), g_hash_table_new (NULL, NULL), /* Hints */ + G_TYPE_INT, -1, /* timeout */ + G_TYPE_INVALID); +} + /* Destroy applet */ static void startup_applet_free (StartupApplet *applet) { gdk_window_remove_filter (applet->root_window, (GdkFilterFunc) filter_func, applet); + g_object_unref (applet->proxy); g_slice_free (StartupApplet, applet); } @@ -76,26 +112,24 @@ update_notify (StartupApplet *applet) g_return_if_fail (applet->launch_list != NULL); item = applet->launch_list->data; - + msg = g_strdup_printf ("Starting %s...", item->name); - - if (applet->notify) { - notify_notification_update (applet->notify, msg, NULL, NULL); - } else { - applet->notify = notify_notification_new (msg, NULL, NULL, NULL); - } - notify_notification_show (applet->notify, NULL); - + + notify_send (applet, msg); + g_free (msg); } static void hide_notify (StartupApplet *applet) { - if (applet->notify) { - notify_notification_close (applet->notify, NULL); - g_object_unref (applet->notify); - applet->notify = NULL; + if (applet->notify_id) { + dbus_g_proxy_call_no_reply (applet->proxy, "CloseNotification", + G_TYPE_UINT, applet->notify_id, + G_TYPE_INVALID); + /* Unset this here just in case the close signal never arrives. Not that + notification-daemon doesn't respect the specification or anything... */ + applet->notify_id = 0; } } @@ -189,7 +223,7 @@ timeout (StartupApplet *applet) time_t t; GList *l; - if (!applet->notify) + if (!applet->notify_id) return TRUE; t = time (NULL); @@ -225,6 +259,46 @@ filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, StartupApplet *applet) return GDK_FILTER_CONTINUE; } +static void +close_cb (DBusGProxy *proxy, guint id, guint reason, StartupApplet *applet) +{ + applet->notify_id = 0; +} + +static gboolean +init_notify (StartupApplet *applet) +{ + DBusGConnection *bus; + GError *error = NULL; + + bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (error) { + g_printerr ("Cannot get DBus connection: %s\n", error->message); + g_error_free (error); + return FALSE; + } + + applet->proxy = dbus_g_proxy_new_for_name (bus, + "org.freedesktop.Notifications", + "/org/freedesktop/Notifications", + "org.freedesktop.Notifications"); + + dbus_g_object_register_marshaller(mb_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID); + + dbus_g_proxy_add_signal (applet->proxy, "NotificationClosed", + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (applet->proxy, "NotificationClosed", + G_CALLBACK (close_cb), + applet, NULL); + + dbus_g_connection_unref (bus); + + return TRUE; +} + G_MODULE_EXPORT GtkWidget * mb_panel_applet_create (const char *id, GtkOrientation orientation) { @@ -233,32 +307,31 @@ mb_panel_applet_create (const char *id, GtkOrientation orientation) Display *xdisplay; SnMonitorContext *context; - if (!notify_is_initted ()) - notify_init ("matchbox-panel"); - applet = g_slice_new0 (StartupApplet); - + widget = gtk_hbox_new (0, FALSE); /* grr */ g_object_weak_ref (G_OBJECT (widget), (GWeakNotify)startup_applet_free, applet); - - xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); - - applet->sn_display = sn_display_new (xdisplay, NULL, NULL); - - context = sn_monitor_context_new (applet->sn_display, - DefaultScreen (xdisplay), - monitor_event_func, - applet, NULL); - - /* We have to select for property events on at least one root window (but not - * all as INITIATE messages go to all root windows) - */ - XSelectInput (xdisplay, DefaultRootWindow (xdisplay), PropertyChangeMask); - - applet->root_window = gdk_window_lookup_for_display - (gdk_x11_lookup_xdisplay (xdisplay), 0); - - gdk_window_add_filter (applet->root_window, (GdkFilterFunc)filter_func, applet); + + if (init_notify (applet)) { + xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); + + applet->sn_display = sn_display_new (xdisplay, NULL, NULL); + + context = sn_monitor_context_new (applet->sn_display, + DefaultScreen (xdisplay), + monitor_event_func, + applet, NULL); + + /* We have to select for property events on at least one root window (but not + * all as INITIATE messages go to all root windows) + */ + XSelectInput (xdisplay, DefaultRootWindow (xdisplay), PropertyChangeMask); + + applet->root_window = gdk_window_lookup_for_display + (gdk_x11_lookup_xdisplay (xdisplay), 0); + + gdk_window_add_filter (applet->root_window, (GdkFilterFunc)filter_func, applet); + } /* TODO: need to fix the panel to support invisible widgets */ return widget; diff --git a/configure.ac b/configure.ac index d04265b..03cc81c 100644 --- a/configure.ac +++ b/configure.ac @@ -30,20 +30,6 @@ fi AM_CONDITIONAL(HAVE_LIBSN, test x$enable_startup_notification = xyes) -# libnotify -AC_ARG_ENABLE(libnotify, - AC_HELP_STRING([--disable-libnotify], [disable libnotify support]), - enable_libnotify=$enableval, enable_libnotify=yes ) - -if test x$enable_libnotify != xno; then - PKG_CHECK_MODULES(LIBNOTIFY, libnotify, , - AC_MSG_ERROR([*** Required libnotify library not installed ***])) - - AC_DEFINE(USE_LIBNOTIFY, [1], [Has libnotify Support]) -fi -AM_CONDITIONAL(HAVE_LIBNOTIFY, test x$enable_libnotify = xyes) - - # DBus AC_ARG_ENABLE(dbus, AC_HELP_STRING([--disable-dbus], [disable DBus support]), |