aboutsummaryrefslogtreecommitdiff
path: root/src/indicator-notifications.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/indicator-notifications.c')
-rw-r--r--src/indicator-notifications.c194
1 files changed, 82 insertions, 112 deletions
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