From 239dec68b0e37d20d07af51e4bc21200447b0aaa Mon Sep 17 00:00:00 2001 From: Jason Conti Date: Sun, 15 May 2011 15:41:32 -0400 Subject: Couldn't seem to get a signal when a menu item is added to the dbusmenu, so adding the interface back from indicator-datetime with a MessageAdded signal to notify the indicator when a notification is added to the menu. --- src/Makefile.am | 22 +++++ src/indicator-notifications.c | 6 +- src/notifications-interface.c | 204 ++++++++++++++++++++++++++++++++++++++++++ src/notifications-interface.h | 55 ++++++++++++ src/notifications-service.xml | 11 +++ 5 files changed, 295 insertions(+), 3 deletions(-) create mode 100644 src/notifications-interface.c create mode 100644 src/notifications-interface.h create mode 100644 src/notifications-service.xml (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index fc973f4..486770f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,9 @@ indicator_notifications_service_SOURCES = \ dbus-spy.h \ notification.c \ notification.h \ + notifications-interface.c \ + notifications-interface.h \ + gen-notifications-service.xml.c \ notifications-service.c \ dbus-shared.h \ settings-shared.h @@ -33,3 +36,22 @@ libnotifications_la_LDFLAGS = \ -module \ -avoid-version +gen-%.xml.c: %.xml + @echo "Building $@ from $<" + @echo "const char * _$(subst -,_,$(subst .,_,$(basename $<))) = " > $@ + @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ + @echo ";" >> $@ + +gen-%.xml.h: %.xml + @echo "Building $@ from $<" + @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $<)));" > $@ + +BUILT_SOURCES = \ + gen-notifications-service.xml.c \ + gen-notifications-service.xml.h + +CLEANFILES = \ + $(BUILT_SOURCES) + +EXTRA_DIST = \ + notifications-service.xml diff --git a/src/indicator-notifications.c b/src/indicator-notifications.c index 8238e02..2e75a97 100644 --- a/src/indicator-notifications.c +++ b/src/indicator-notifications.c @@ -97,6 +97,7 @@ static GtkImage *get_image(IndicatorObject *io); static GtkMenu *get_menu(IndicatorObject *io); static const gchar *get_accessible_desc(IndicatorObject *io); static GdkPixbuf *load_icon(const gchar *, guint); +static void menu_visible_notify_cb(GtkWidget *, GParamSpec *, gpointer); static void receive_signal(GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, gpointer user_data); static void service_proxy_cb(GObject *object, GAsyncResult *res, gpointer user_data); @@ -128,7 +129,8 @@ indicator_notifications_class_init(IndicatorNotificationsClass *klass) static void menu_visible_notify_cb(GtkWidget *menu, G_GNUC_UNUSED GParamSpec *pspec, gpointer user_data) { - /*IndicatorNotifications *self = INDICATOR_NOTIFICATIONS(user_data);*/ + /* IndicatorNotifications *self = INDICATOR_NOTIFICATIONS(user_data); */ + g_debug("notify visible signal received"); gboolean visible; @@ -163,8 +165,6 @@ indicator_notifications_init(IndicatorNotifications *self) g_signal_connect(self->priv->menu, "notify::visible", G_CALLBACK(menu_visible_notify_cb), self); - /*DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(self->priv->menu);*/ - self->priv->service_proxy_cancel = g_cancellable_new(); g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, diff --git a/src/notifications-interface.c b/src/notifications-interface.c new file mode 100644 index 0000000..6326bf2 --- /dev/null +++ b/src/notifications-interface.c @@ -0,0 +1,204 @@ +/* +An indicator to display recent notifications. + +Adapted from: indicator-notifications/src/notifications-service.c by + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "notifications-interface.h" +#include "gen-notifications-service.xml.h" +#include "dbus-shared.h" + +/** + NotificationsInterfacePrivate: + @dbus_registration: The handle for this object being registered + on dbus. + + Structure to define the memory for the private area + of the notifications interface instance. +*/ +struct _NotificationsInterfacePrivate { + GDBusConnection *bus; + GCancellable *bus_cancel; + guint dbus_registration; +}; + +#define NOTIFICATIONS_INTERFACE_GET_PRIVATE(o) (NOTIFICATIONS_INTERFACE(o)->priv) + +/* GDBus Stuff */ +static GDBusNodeInfo *node_info = NULL; +static GDBusInterfaceInfo *interface_info = NULL; + +static void notifications_interface_class_init(NotificationsInterfaceClass *klass); +static void notifications_interface_init(NotificationsInterface *self); +static void notifications_interface_dispose(GObject *object); +static void notifications_interface_finalize(GObject *object); +static void bus_get_cb(GObject *object, GAsyncResult *res, gpointer user_data); + +G_DEFINE_TYPE (NotificationsInterface, notifications_interface, G_TYPE_OBJECT); + +static void +notifications_interface_class_init(NotificationsInterfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private(klass, sizeof(NotificationsInterfacePrivate)); + + object_class->dispose = notifications_interface_dispose; + object_class->finalize = notifications_interface_finalize; + + /* Setting up the DBus interfaces */ + if(node_info == NULL) { + GError * error = NULL; + + node_info = g_dbus_node_info_new_for_xml(_notifications_service, &error); + if(error != NULL) { + g_error("Unable to parse Notifications Service Interface description: %s", error->message); + g_error_free(error); + } + } + + if(interface_info == NULL) { + interface_info = g_dbus_node_info_lookup_interface(node_info, SERVICE_IFACE); + + if(interface_info == NULL) { + g_error("Unable to find interface '" SERVICE_IFACE "'"); + } + } + + return; +} + +static void +notifications_interface_init(NotificationsInterface *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NOTIFICATIONS_INTERFACE_TYPE, NotificationsInterfacePrivate); + + self->priv->bus = NULL; + self->priv->bus_cancel = NULL; + self->priv->dbus_registration = 0; + + self->priv->bus_cancel = g_cancellable_new(); + g_bus_get(G_BUS_TYPE_SESSION, + self->priv->bus_cancel, + bus_get_cb, + self); + + return; +} + +static void +bus_get_cb(GObject *object, GAsyncResult *res, gpointer user_data) +{ + GError *error = NULL; + GDBusConnection *connection = g_bus_get_finish(res, &error); + + if(error != NULL) { + g_error("OMG! Unable to get a connection to DBus: %s", error->message); + g_error_free(error); + return; + } + + NotificationsInterfacePrivate *priv = NOTIFICATIONS_INTERFACE_GET_PRIVATE(user_data); + + g_warn_if_fail(priv->bus == NULL); + priv->bus = connection; + + if(priv->bus_cancel != NULL) { + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } + + /* Now register our object on our new connection */ + priv->dbus_registration = g_dbus_connection_register_object(priv->bus, + SERVICE_OBJ, + interface_info, + NULL, + user_data, + NULL, + &error); + + if(error != NULL) { + g_error("Unable to register the object to DBus: %s", error->message); + g_error_free(error); + return; + } + + return; +} + +static void +notifications_interface_dispose(GObject *object) +{ + NotificationsInterfacePrivate *priv = NOTIFICATIONS_INTERFACE_GET_PRIVATE(object); + + if(priv->dbus_registration != 0) { + g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration); + /* Don't care if it fails, there's nothing we can do */ + priv->dbus_registration = 0; + } + + if(priv->bus != NULL) { + g_object_unref(priv->bus); + priv->bus = NULL; + } + + if(priv->bus_cancel != NULL) { + g_cancellable_cancel(priv->bus_cancel); + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } + + G_OBJECT_CLASS (notifications_interface_parent_class)->dispose (object); + return; +} + +static void +notifications_interface_finalize(GObject *object) +{ + G_OBJECT_CLASS (notifications_interface_parent_class)->finalize (object); + return; +} + +void +notifications_interface_message_added(NotificationsInterface *self) +{ + g_return_if_fail(IS_NOTIFICATIONS_INTERFACE(self)); + + NotificationsInterfacePrivate *priv = NOTIFICATIONS_INTERFACE_GET_PRIVATE(self); + GError *error = NULL; + + g_dbus_connection_emit_signal(priv->bus, + NULL, + SERVICE_OBJ, + SERVICE_IFACE, + "MessageAdded", + NULL, + &error); + + if(error != NULL) { + g_error("Unable to send MessageAdded signal: %s", error->message); + g_error_free(error); + return; + } + + return; +} diff --git a/src/notifications-interface.h b/src/notifications-interface.h new file mode 100644 index 0000000..7cce828 --- /dev/null +++ b/src/notifications-interface.h @@ -0,0 +1,55 @@ +/* +An indicator to display recent notifications. + +Adapted from: indicator-notifications/src/notifications-interface.c by + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#ifndef __NOTIFICATIONS_INTERFACE_H__ +#define __NOTIFICATIONS_INTERFACE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define NOTIFICATIONS_INTERFACE_TYPE (notifications_interface_get_type ()) +#define NOTIFICATIONS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NOTIFICATIONS_INTERFACE_TYPE, NotificationsInterface)) +#define NOTIFICATIONS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NOTIFICATIONS_INTERFACE_TYPE, NotificationsInterfaceClass)) +#define IS_NOTIFICATIONS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NOTIFICATIONS_INTERFACE_TYPE)) +#define IS_NOTIFICATIONS_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NOTIFICATIONS_INTERFACE_TYPE)) +#define NOTIFICATIONS_INTERFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NOTIFICATIONS_INTERFACE_TYPE, NotificationsInterfaceClass)) + +typedef struct _NotificationsInterface NotificationsInterface; +typedef struct _NotificationsInterfacePrivate NotificationsInterfacePrivate; +typedef struct _NotificationsInterfaceClass NotificationsInterfaceClass; + +struct _NotificationsInterfaceClass { + GObjectClass parent_class; + + void (*message_added) (void); +}; + +struct _NotificationsInterface { + GObject parent; + NotificationsInterfacePrivate *priv; +}; + +GType notifications_interface_get_type(void); +void notifications_interface_message_added(NotificationsInterface *self); + +G_END_DECLS + +#endif diff --git a/src/notifications-service.xml b/src/notifications-service.xml new file mode 100644 index 0000000..36edd68 --- /dev/null +++ b/src/notifications-service.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + -- cgit v1.2.3