diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 47 | ||||
-rw-r--r-- | src/dbus-shared.h | 32 | ||||
-rw-r--r-- | src/dbus-spy.c | 27 | ||||
-rw-r--r-- | src/indicator-notifications.c | 194 | ||||
-rw-r--r-- | src/notifications-interface.c | 210 | ||||
-rw-r--r-- | src/notifications-interface.h | 56 | ||||
-rw-r--r-- | src/notifications-service.c | 290 | ||||
-rw-r--r-- | src/notifications-service.xml | 11 | ||||
-rw-r--r-- | src/settings-shared.h | 25 |
9 files changed, 112 insertions, 780 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2b92fc7..803402a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,32 +1,14 @@ AM_CPPFLAGS = -DICONS_DIR='"$(INDICATORICONSDIR)"' \ -DWITH_GTK='$(GTK_VERSION)' -libexec_PROGRAMS = indicator-notifications-service - -indicator_notifications_service_SOURCES = \ - dbus-spy.c \ - 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 -indicator_notifications_service_CFLAGS = \ - -Wall \ - $(SERVICE_CFLAGS) \ - -DG_LOG_DOMAIN=\"Indicator-Notifications\" -indicator_notifications_service_LDADD = \ - $(SERVICE_LIBS) - notificationslibdir = $(INDICATORDIR) notificationslib_LTLIBRARIES = libnotifications.la libnotifications_la_SOURCES = \ - dbus-shared.h \ - settings-shared.h \ - indicator-notifications.c + dbus-spy.c \ + dbus-spy.h \ + indicator-notifications.c \ + notification.c \ + notification.h libnotifications_la_CFLAGS = \ $(INDICATOR_CFLAGS) \ -Wall \ @@ -37,22 +19,3 @@ libnotifications_la_LDFLAGS = \ -module \ -avoid-version -gen-notifications-service.xml.c: notifications-service.xml - @echo "Building $@ from $<" - @echo "const char * _notifications_service = " > $@ - @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ - @echo ";" >> $@ - -gen-notifications-service.xml.h: notifications-service.xml - @echo "Building $@ from $<" - @echo "extern const char * _notifications_service;" > $@ - -BUILT_SOURCES = \ - gen-notifications-service.xml.c \ - gen-notifications-service.xml.h - -CLEANFILES = \ - $(BUILT_SOURCES) - -EXTRA_DIST = \ - notifications-service.xml diff --git a/src/dbus-shared.h b/src/dbus-shared.h deleted file mode 100644 index da93e73..0000000 --- a/src/dbus-shared.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -An indicator to display recent notifications. - -Adapted from: indicator-datetime/src/dbus-shared.c by - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#define SERVICE_NAME "com.launchpad.RecentNotifications.indicator" -#define SERVICE_IFACE "com.launchpad.RecentNotifications.indicator.service" -#define SERVICE_OBJ "/com/launchpad/RecentNotifications/indicator/service" -#define SERVICE_VERSION 1 - -#define MENU_OBJ "/com/launchpad/RecentNotifications/indicator/menu" - -#define NOTIFICATION_MENUITEM_TYPE "notification-menuitem" -#define NOTIFICATION_MENUITEM_PROP_APP_NAME "notification-menuitem-prop-app-name" -#define NOTIFICATION_MENUITEM_PROP_APP_ICON "notification-menuitem-prop-app-icon" -#define NOTIFICATION_MENUITEM_PROP_SUMMARY "notification-menuitem-prop-summary" -#define NOTIFICATION_MENUITEM_PROP_BODY "notification-menuitem-prop-body" -#define NOTIFICATION_MENUITEM_PROP_TIMESTAMP_STRING "notification-menuitem-prop-timestamp-string" diff --git a/src/dbus-spy.c b/src/dbus-spy.c index 4fe5141..e63a5ee 100644 --- a/src/dbus-spy.c +++ b/src/dbus-spy.c @@ -9,6 +9,13 @@ enum { LAST_SIGNAL }; +typedef struct _IdleMessage IdleMessage; +struct _IdleMessage +{ + DBusSpy *spy; + Notification *note; +}; + static guint signals[LAST_SIGNAL]; static void dbus_spy_class_init(DBusSpyClass *klass); @@ -22,6 +29,8 @@ static void bus_get_cb(GObject *source_object, GAsyncResult *res, gpointer user_ static GDBusMessage *message_filter(GDBusConnection *connection, GDBusMessage *message, gboolean incoming, gpointer user_data); +static gboolean idle_message_emit(gpointer user_data); + #define MATCH_STRING "type='method_call',interface='org.freedesktop.Notifications',member='Notify'" G_DEFINE_TYPE (DBusSpy, dbus_spy, G_TYPE_OBJECT); @@ -115,8 +124,10 @@ message_filter(GDBusConnection *connection, GDBusMessage *message, gboolean inco { DBusSpy *spy = DBUS_SPY(user_data); Notification *note = notification_new_from_dbus_message(message); - g_signal_emit(spy, signals[MESSAGE_RECEIVED], 0, note); - g_object_unref(note); + IdleMessage *im = g_new0(IdleMessage, 1); + im->spy = spy; + im->note = note; + g_idle_add(idle_message_emit, im); g_object_unref(message); message = NULL; } @@ -124,6 +135,18 @@ message_filter(GDBusConnection *connection, GDBusMessage *message, gboolean inco return message; } +static gboolean +idle_message_emit(gpointer user_data) +{ + IdleMessage *message = (IdleMessage *)user_data; + + g_signal_emit(message->spy, signals[MESSAGE_RECEIVED], 0, message->note); + + g_free(message); + + return FALSE; +} + static void dbus_spy_init(DBusSpy *self) { diff --git a/src/indicator-notifications.c b/src/indicator-notifications.c index 237c4d0..3d4dc56 100644 --- a/src/indicator-notifications.c +++ b/src/indicator-notifications.c @@ -39,17 +39,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libindicator/indicator-object.h> #include <libindicator/indicator-service-manager.h> -/* DBusMenu */ -#if WITH_GTK == 3 -#include <libdbusmenu-gtk3/menu.h> -#include <libdbusmenu-gtk3/menuitem.h> -#else -#include <libdbusmenu-gtk/menu.h> -#include <libdbusmenu-gtk/menuitem.h> -#endif - -#include "dbus-shared.h" -#include "settings-shared.h" +#include "dbus-spy.h" #define INDICATOR_NOTIFICATIONS_TYPE (indicator_notifications_get_type ()) #define INDICATOR_NOTIFICATIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_NOTIFICATIONS_TYPE, IndicatorNotifications)) @@ -79,13 +69,11 @@ struct _IndicatorNotificationsPrivate { gboolean have_unread; - IndicatorServiceManager *sm; - DbusmenuGtkMenu *menu; + GtkMenu *menu; gchar *accessible_desc; - GCancellable *service_proxy_cancel; - GDBusProxy *service_proxy; + DBusSpy *spy; }; #define INDICATOR_NOTIFICATIONS_GET_PRIVATE(o) \ @@ -106,9 +94,14 @@ static GtkMenu *get_menu(IndicatorObject *io); static const gchar *get_accessible_desc(IndicatorObject *io); static GdkPixbuf *load_icon(const gchar *name, gint size); static void menu_visible_notify_cb(GtkWidget *menu, GParamSpec *pspec, gpointer user_data); -static gboolean new_notification_menuitem(DbusmenuMenuitem *new_item, DbusmenuMenuitem *parent, DbusmenuClient *client, gpointer user_data); -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); + +#if WITH_GTK == 3 +static void calculate_size_cb(GtkWidget *item, gpointer user_data); +static void resize_menu(GtkWidget *menu); +#endif + +static void message_received_cb(DBusSpy *spy, Notification *note, gpointer user_data); +static GtkWidget *new_notification_menuitem(Notification *note); static void style_changed(GtkWidget *widget, GtkStyle *oldstyle, gpointer user_data); /* Indicator Module Config */ @@ -151,80 +144,91 @@ menu_visible_notify_cb(GtkWidget *menu, G_GNUC_UNUSED GParamSpec *pspec, gpointe } } +#if WITH_GTK == 3 +/* In GTK3 labels can now automatically wrap to fit the size of their parent, + * however, it seems to take several tries for GtkMenu to resize properly. + * + * As a workaround, calculate the preferred size for each of the menu items and + * set the menu's size request appropriately. + */ static void -indicator_notifications_init(IndicatorNotifications *self) +calculate_size_cb(GtkWidget *item, gpointer user_data) { - self->priv = INDICATOR_NOTIFICATIONS_GET_PRIVATE(self); - - self->priv->service_proxy = NULL; + GtkAllocation *alloc = (GtkAllocation *)user_data; + gint width; + gint height; - self->priv->sm = NULL; - self->priv->menu = NULL; + gtk_widget_get_preferred_width(item, NULL, &width); + gtk_widget_get_preferred_height_for_width(item, width, NULL, &height); - self->priv->image = NULL; - self->priv->pixbuf_read = NULL; - self->priv->pixbuf_unread = NULL; + if(alloc->width < width) + alloc->width = width; - self->priv->have_unread = FALSE; + alloc->height += height; +} - self->priv->accessible_desc = _("Notifications"); +static void +resize_menu(GtkWidget *menu) +{ + GtkAllocation alloc; + GtkAllocation child_alloc; - self->priv->sm = indicator_service_manager_new_version(SERVICE_NAME, SERVICE_VERSION); + gtk_widget_get_allocation(menu, &alloc); - self->priv->menu = dbusmenu_gtkmenu_new(SERVICE_NAME, MENU_OBJ); + child_alloc.x = 0; + child_alloc.y = 0; + child_alloc.width = 1; + child_alloc.height = 1; - g_signal_connect(self->priv->menu, "notify::visible", G_CALLBACK(menu_visible_notify_cb), self); + gtk_container_foreach(GTK_CONTAINER(menu), calculate_size_cb, &child_alloc); + gtk_widget_set_size_request(menu, child_alloc.width, child_alloc.height); + g_debug("RESIZE_MENU: W: %d H: %d -> W: %d H: %d", alloc.width, alloc.height, + child_alloc.width, child_alloc.height); +} +#endif - DbusmenuGtkClient *client = dbusmenu_gtkmenu_get_client(self->priv->menu); +static void +message_received_cb(DBusSpy *spy, Notification *note, gpointer user_data) +{ + IndicatorNotifications *self = INDICATOR_NOTIFICATIONS(user_data); - dbusmenu_client_add_type_handler_full(DBUSMENU_CLIENT(client), - NOTIFICATION_MENUITEM_TYPE, - new_notification_menuitem, - self, NULL); + /* Discard volume notifications */ + if(notification_is_volume(note)) return; - self->priv->service_proxy_cancel = g_cancellable_new(); + GtkWidget *item = new_notification_menuitem(note); + g_object_unref(note); - g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - SERVICE_NAME, - SERVICE_OBJ, - SERVICE_IFACE, - self->priv->service_proxy_cancel, - service_proxy_cb, - self); + gtk_menu_shell_append(GTK_MENU_SHELL(self->priv->menu), item); - return; + if(self->priv->pixbuf_unread != NULL) { + self->priv->have_unread = TRUE; + gtk_image_set_from_pixbuf(self->priv->image, self->priv->pixbuf_unread); + } +#if WITH_GTK == 3 + resize_menu(GTK_WIDGET(self->priv->menu)); +#endif } static void -service_proxy_cb(GObject *object, GAsyncResult *res, gpointer user_data) +indicator_notifications_init(IndicatorNotifications *self) { - GError *error = NULL; - - IndicatorNotifications *self = INDICATOR_NOTIFICATIONS(user_data); - g_return_if_fail(self != NULL); - - GDBusProxy *proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + self->priv = INDICATOR_NOTIFICATIONS_GET_PRIVATE(self); - IndicatorNotificationsPrivate *priv = INDICATOR_NOTIFICATIONS_GET_PRIVATE(self); + self->priv->menu = NULL; - if(priv->service_proxy_cancel != NULL) { - g_object_unref(priv->service_proxy_cancel); - priv->service_proxy_cancel = NULL; - } + self->priv->image = NULL; + self->priv->pixbuf_read = NULL; + self->priv->pixbuf_unread = NULL; - if(error != NULL) { - g_warning("Could not grab DBus proxy for %s: %s", SERVICE_NAME, error->message); - g_error_free(error); - return; - } + self->priv->have_unread = FALSE; - priv->service_proxy = proxy; + self->priv->accessible_desc = _("Notifications"); - g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self); + self->priv->menu = GTK_MENU(gtk_menu_new()); + g_signal_connect(self->priv->menu, "notify::visible", G_CALLBACK(menu_visible_notify_cb), self); - return; + self->priv->spy = dbus_spy_new(); + g_signal_connect(self->priv->spy, DBUS_SPY_SIGNAL_MESSAGE_RECEIVED, G_CALLBACK(message_received_cb), self); } static void @@ -252,16 +256,6 @@ indicator_notifications_dispose(GObject *object) self->priv->menu = NULL; } - if(self->priv->sm != NULL) { - g_object_unref(G_OBJECT(self->priv->sm)); - self->priv->sm = NULL; - } - - if(self->priv->service_proxy != NULL) { - g_object_unref(self->priv->service_proxy); - self->priv->service_proxy = NULL; - } - G_OBJECT_CLASS (indicator_notifications_parent_class)->dispose (object); return; } @@ -275,39 +269,15 @@ indicator_notifications_finalize(GObject *object) return; } -static void -receive_signal(GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, - GVariant *parameters, gpointer user_data) +static GtkWidget * +new_notification_menuitem(Notification *note) { - IndicatorNotifications *self = INDICATOR_NOTIFICATIONS(user_data); + gchar *unescaped_timestamp_string = notification_timestamp_for_locale(note); - g_debug("received signal '%s'", signal_name); - if(g_strcmp0(signal_name, "MessageAdded") == 0) { - if(self->priv->pixbuf_unread != NULL) { - self->priv->have_unread = TRUE; - gtk_image_set_from_pixbuf(self->priv->image, self->priv->pixbuf_unread); - } - } - - return; -} - -static gboolean -new_notification_menuitem(DbusmenuMenuitem *new_item, DbusmenuMenuitem *parent, - DbusmenuClient *client, gpointer user_data) -{ - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(new_item), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - g_return_val_if_fail(IS_INDICATOR_NOTIFICATIONS(user_data), FALSE); - - gchar *app_name = g_markup_escape_text(dbusmenu_menuitem_property_get(new_item, - NOTIFICATION_MENUITEM_PROP_APP_NAME), -1); - gchar *summary = g_markup_escape_text(dbusmenu_menuitem_property_get(new_item, - NOTIFICATION_MENUITEM_PROP_SUMMARY), -1); - gchar *body = g_markup_escape_text(dbusmenu_menuitem_property_get(new_item, - NOTIFICATION_MENUITEM_PROP_BODY), -1); - gchar *timestamp_string = g_markup_escape_text(dbusmenu_menuitem_property_get(new_item, - NOTIFICATION_MENUITEM_PROP_TIMESTAMP_STRING), -1); + gchar *app_name = g_markup_escape_text(notification_get_app_name(note), -1); + gchar *summary = g_markup_escape_text(notification_get_summary(note), -1); + gchar *body = g_markup_escape_text(notification_get_body(note), -1); + gchar *timestamp_string = g_markup_escape_text(unescaped_timestamp_string, -1); gchar *markup = g_strdup_printf("<b>%s</b>\n%s\n<small><i>%s %s <b>%s</b></i></small>", summary, body, timestamp_string, _("from"), app_name); @@ -315,6 +285,7 @@ new_notification_menuitem(DbusmenuMenuitem *new_item, DbusmenuMenuitem *parent, g_free(app_name); g_free(summary); g_free(body); + g_free(unescaped_timestamp_string); g_free(timestamp_string); #if WITH_GTK == 3 @@ -344,10 +315,9 @@ new_notification_menuitem(DbusmenuMenuitem *new_item, DbusmenuMenuitem *parent, GtkWidget *item = gtk_menu_item_new(); gtk_container_add(GTK_CONTAINER(item), hbox); gtk_widget_show(hbox); + gtk_widget_show(item); - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), new_item, GTK_MENU_ITEM(item), parent); - - return TRUE; + return item; } static void diff --git a/src/notifications-interface.c b/src/notifications-interface.c deleted file mode 100644 index d130049..0000000 --- a/src/notifications-interface.c +++ /dev/null @@ -1,210 +0,0 @@ -/* -An indicator to display recent notifications. - -Adapted from: indicator-notifications/src/notifications-service.c by - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gio/gio.h> - -#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; -} - -NotificationsInterface * -notifications_interface_new() -{ - return NOTIFICATIONS_INTERFACE(g_object_new(NOTIFICATIONS_INTERFACE_TYPE, NULL)); -} - -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 deleted file mode 100644 index 1af5824..0000000 --- a/src/notifications-interface.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -An indicator to display recent notifications. - -Adapted from: indicator-notifications/src/notifications-interface.c by - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef __NOTIFICATIONS_INTERFACE_H__ -#define __NOTIFICATIONS_INTERFACE_H__ - -#include <glib.h> -#include <glib-object.h> - -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); -NotificationsInterface *notifications_interface_new(); -void notifications_interface_message_added(NotificationsInterface *self); - -G_END_DECLS - -#endif diff --git a/src/notifications-service.c b/src/notifications-service.c deleted file mode 100644 index d3c7da2..0000000 --- a/src/notifications-service.c +++ /dev/null @@ -1,290 +0,0 @@ -/* -An indicator to display recent notifications. - -Adapted from: indicator-datetime/src/datetime-service.c by - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#include <config.h> -#include <libindicator/indicator-service.h> -#include <locale.h> -#include <stdio.h> - -#include <gtk/gtk.h> -#include <glib/gi18n.h> -#include <gio/gio.h> - -#if WITH_GTK == 3 -#include <libdbusmenu-gtk3/menuitem.h> -#else -#include <libdbusmenu-gtk/menuitem.h> -#endif - -#include <libdbusmenu-glib/server.h> -#include <libdbusmenu-glib/client.h> -#include <libdbusmenu-glib/menuitem.h> - -#include "dbus-shared.h" -#include "dbus-spy.h" -#include "notifications-interface.h" -#include "settings-shared.h" - -static IndicatorService *service = NULL; -static GMainLoop *mainloop = NULL; -static DbusmenuServer *server = NULL; -static DbusmenuMenuitem *root = NULL; -static DBusSpy *spy = NULL; -static NotificationsInterface *dbus = NULL; - -/* Global Items */ -static DbusmenuMenuitem *clear_item = NULL; -static DbusmenuMenuitem *empty_item = NULL; -static GQueue *notification_items = NULL; -static guint notification_limit = 5; - -/* Logging */ -#define LOG_FILE_NAME "indicator-notifications-service.log" -static FILE *log_file = NULL; - -static gboolean add_notification_item(gpointer); -static gboolean clear_notification_items(gpointer); -static void build_menus(DbusmenuMenuitem *); -static void clear_notifications_cb(DbusmenuMenuitem *, guint, gpointer); -static void log_cb(const gchar *, GLogLevelFlags, const gchar *, gpointer); -static void log_init(); -static void message_received_cb(DBusSpy *, Notification *, gpointer); -static void service_shutdown_cb(IndicatorService *, gpointer); - -static gboolean -add_notification_item(gpointer user_data) -{ - Notification *note = NOTIFICATION(user_data); - DbusmenuMenuitem *item; - - guint length = g_queue_get_length(notification_items); - - /* Remove the empty item from the menu */ - if(length == 0) { - dbusmenu_menuitem_child_delete(root, empty_item); - } - - gchar *timestamp_string = notification_timestamp_for_locale(note); - - item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TYPE, NOTIFICATION_MENUITEM_TYPE); - dbusmenu_menuitem_property_set(item, NOTIFICATION_MENUITEM_PROP_APP_NAME, notification_get_app_name(note)); - dbusmenu_menuitem_property_set(item, NOTIFICATION_MENUITEM_PROP_SUMMARY, notification_get_summary(note)); - dbusmenu_menuitem_property_set(item, NOTIFICATION_MENUITEM_PROP_BODY, notification_get_body(note)); - dbusmenu_menuitem_property_set(item, NOTIFICATION_MENUITEM_PROP_TIMESTAMP_STRING, timestamp_string); - dbusmenu_menuitem_child_prepend(root, item); - g_queue_push_head(notification_items, item); - length++; - - g_debug("Adding message from %s (Queue length: %d)", notification_get_app_name(note), - length); - - if(length > notification_limit) { - item = DBUSMENU_MENUITEM(g_queue_pop_tail(notification_items)); - dbusmenu_menuitem_child_delete(root, item); - g_object_unref(item); - item = NULL; - } - - /* Notify the indicator that a new message has been added */ - notifications_interface_message_added(dbus); - - g_free(timestamp_string); - g_object_unref(note); - - return FALSE; -} - -static gboolean -clear_notification_items(gpointer user_data) -{ - DbusmenuMenuitem *item; - - while(!g_queue_is_empty(notification_items)) { - item = DBUSMENU_MENUITEM(g_queue_pop_tail(notification_items)); - dbusmenu_menuitem_child_delete(root, item); - g_object_unref(item); - } - - item = NULL; - - /* Add the empty item back, if it isn't already there */ - if(dbusmenu_menuitem_child_find(root, dbusmenu_menuitem_get_id(empty_item)) == NULL) { - dbusmenu_menuitem_child_prepend(root, empty_item); - } - - return FALSE; -} - -static void -build_menus(DbusmenuMenuitem *root) -{ - g_debug("Building Menus."); - - if(empty_item == NULL) { - empty_item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(empty_item, DBUSMENU_MENUITEM_PROP_LABEL, _("There are 0 notifications.")); - dbusmenu_menuitem_child_append(root, empty_item); - } - - if(clear_item == NULL) { - DbusmenuMenuitem *item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append(root, item); - - clear_item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(clear_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Clear")); - dbusmenu_menuitem_child_append(root, clear_item); - - g_signal_connect(G_OBJECT(clear_item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(clear_notifications_cb), NULL); - } - - return; -} - -static void -clear_notifications_cb(DbusmenuMenuitem *item, guint timestamp, gpointer user_data) -{ - g_idle_add(clear_notification_items, NULL); -} - -/* from lightdm */ -static void -log_cb(const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer user_data) -{ - if(log_file) { - const gchar *prefix; - - switch(level & G_LOG_LEVEL_MASK) { - case G_LOG_LEVEL_ERROR: - prefix = "ERROR:"; - break; - case G_LOG_LEVEL_CRITICAL: - prefix = "CRITICAL:"; - break; - case G_LOG_LEVEL_WARNING: - prefix = "WARNING:"; - break; - case G_LOG_LEVEL_MESSAGE: - prefix = "MESSAGE:"; - break; - case G_LOG_LEVEL_INFO: - prefix = "INFO:"; - break; - case G_LOG_LEVEL_DEBUG: - prefix = "DEBUG:"; - break; - default: - prefix = "LOG:"; - break; - } - - fprintf(log_file, "%s %s\n", prefix, message); - fflush(log_file); - } - - g_log_default_handler(domain, level, message, user_data); -} - -/* from lightdm */ -static void -log_init() -{ - gchar *path; - - g_mkdir_with_parents(g_get_user_cache_dir(), 0755); - path = g_build_filename(g_get_user_cache_dir(), LOG_FILE_NAME, NULL); - - log_file = fopen(path, "w"); - g_log_set_default_handler(log_cb, NULL); - - g_debug("Logging to %s", path); - g_free(path); -} - -static void -message_received_cb(DBusSpy *spy, Notification *note, gpointer user_data) -{ - /* Discard volume notifications */ - if(notification_is_volume(note)) return; - - g_object_ref(note); - g_idle_add(add_notification_item, note); -} - -/* Responds to the service object saying it's time to shutdown. - It stops the mainloop. */ -static void -service_shutdown_cb(IndicatorService *service, gpointer user_data) -{ - g_warning("Shutting down service!"); - g_main_loop_quit(mainloop); - return; -} - -/* Function to build everything up. Entry point from asm. */ -int -main(int argc, char **argv) -{ - g_type_init(); - - /* Logging */ - log_init(); - - /* Acknowledging the service init and setting up the interface */ - service = indicator_service_new_version(SERVICE_NAME, SERVICE_VERSION); - g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown_cb), NULL); - - /* Setting up i18n and gettext. Apparently, we need - all of these. */ - setlocale(LC_ALL, ""); - bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain(GETTEXT_PACKAGE); - - /* Building the base menu */ - server = dbusmenu_server_new(MENU_OBJ); - root = dbusmenu_menuitem_new(); - dbusmenu_server_set_root(server, root); - - build_menus(root); - - /* Create the notification queue */ - notification_items = g_queue_new(); - - /* Set up the notification spy */ - spy = dbus_spy_new(); - g_signal_connect(spy, DBUS_SPY_SIGNAL_MESSAGE_RECEIVED, G_CALLBACK(message_received_cb), NULL); - - /* Setup the dbus interface */ - dbus = notifications_interface_new(); - - mainloop = g_main_loop_new(NULL, FALSE); - g_main_loop_run(mainloop); - - g_object_unref(G_OBJECT(dbus)); - g_object_unref(G_OBJECT(spy)); - g_object_unref(G_OBJECT(service)); - g_object_unref(G_OBJECT(server)); - g_object_unref(G_OBJECT(root)); - - fclose(log_file); - - return 0; -} diff --git a/src/notifications-service.xml b/src/notifications-service.xml deleted file mode 100644 index 36edd68..0000000 --- a/src/notifications-service.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<node name="/"> - <interface name="com.launchpad.RecentNotifications.indicator.service"> - -<!-- Methods --> - -<!-- Signals --> - <signal name="MessageAdded" /> - - </interface> -</node> diff --git a/src/settings-shared.h b/src/settings-shared.h deleted file mode 100644 index 3297ad2..0000000 --- a/src/settings-shared.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -An indicator to display recent notifications. - -Adapted from: indicator-datetime/src/settings-shared.c by - Ted Gould <ted@canonical.com> - -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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef __NOTIFICATIONS_SETTINGS_SHARED_H__ -#define __NOTIFICATIONS_SETTINGS_SHARED_H__ - -#define SETTINGS_INTERFACE "com.launchpad.RecentNotifications.indicator" - -#endif |