diff options
Diffstat (limited to 'src/indicator-notifications.c')
-rw-r--r-- | src/indicator-notifications.c | 194 |
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 |