Add gtk notification backend

https://bugzilla.gnome.org/show_bug.cgi?id=688492
This commit is contained in:
Lars Uebernickel 2013-10-15 12:19:09 -04:00 committed by Ryan Lortie
parent 639bd3626b
commit 766f5584ce
8 changed files with 261 additions and 29 deletions

View File

@ -267,6 +267,7 @@ unix_sources = \
gcontenttype.c \
gcontenttypeprivate.h \
gfdonotificationbackend.c \
ggtknotificationbackend.c \
$(NULL)

View File

@ -176,7 +176,7 @@ call_notify (GDBusConnection *con,
guint n_buttons;
guint i;
GVariantBuilder hints_builder;
GIcon *image;
GIcon *icon;
GVariant *parameters;
const gchar *body;
@ -222,12 +222,12 @@ call_notify (GDBusConnection *con,
g_variant_new_string (g_application_get_application_id (app)));
if (g_notification_get_urgent (notification))
g_variant_builder_add (&hints_builder, "{sv}", "urgency", g_variant_new_byte (2));
image = g_notification_get_image (notification);
if (image != NULL && G_IS_FILE_ICON (image))
icon = g_notification_get_icon (notification);
if (icon != NULL && G_IS_FILE_ICON (icon))
{
GFile *file;
file = g_file_icon_get_file (G_FILE_ICON (image));
file = g_file_icon_get_file (G_FILE_ICON (icon));
g_variant_builder_add (&hints_builder, "{sv}", "image-path",
g_variant_new_take_string (g_file_get_uri (file)));
}
@ -339,7 +339,7 @@ g_fdo_notification_backend_send_notification (GNotificationBackend *backend,
n = g_fdo_notification_backend_find_notification (self, id);
if (n == NULL)
{
n = g_slice_new (FreedesktopNotification);
n = g_slice_new0 (FreedesktopNotification);
n->backend = self;
n->id = g_strdup (id);
n->notify_id = 0;
@ -349,9 +349,8 @@ g_fdo_notification_backend_send_notification (GNotificationBackend *backend,
else
{
/* Only clear default action. All other fields are still valid */
g_free (n->default_action);
if (n->default_action_target)
g_variant_unref (n->default_action_target);
g_clear_pointer (&n->default_action, g_free);
g_clear_pointer (&n->default_action_target, g_variant_unref);
}
g_notification_get_default_action (notification, &n->default_action, &n->default_action_target);

View File

@ -0,0 +1,144 @@
/*
* Copyright © 2013 Lars Uebernickel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Lars Uebernickel <lars@uebernic.de>
*/
#include "gnotificationbackend.h"
#include "giomodule-priv.h"
#include "gdbusconnection.h"
#include "gapplication.h"
#include "gnotification-private.h"
#define G_TYPE_GTK_NOTIFICATION_BACKEND (g_gtk_notification_backend_get_type ())
#define G_GTK_NOTIFICATION_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_GTK_NOTIFICATION_BACKEND, GGtkNotificationBackend))
typedef struct _GGtkNotificationBackend GGtkNotificationBackend;
typedef GNotificationBackendClass GGtkNotificationBackendClass;
struct _GGtkNotificationBackend
{
GNotificationBackend parent;
GDBusConnection *session_bus;
};
GType g_gtk_notification_backend_get_type (void);
G_DEFINE_TYPE_WITH_CODE (GGtkNotificationBackend, g_gtk_notification_backend, G_TYPE_NOTIFICATION_BACKEND,
_g_io_modules_ensure_extension_points_registered ();
g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME,
g_define_type_id, "gtk", 100))
static void
g_gtk_notification_backend_dispose (GObject *object)
{
GGtkNotificationBackend *backend = G_GTK_NOTIFICATION_BACKEND (object);
g_clear_object (&backend->session_bus);
G_OBJECT_CLASS (g_gtk_notification_backend_parent_class)->dispose (object);
}
static gboolean
g_gtk_notification_backend_is_supported (void)
{
GDBusConnection *session_bus;
GVariant *reply;
/* Find out if the notification server is running. This is a
* synchronous call because gio extension points don't support asnyc
* backend verification. This is only run once and only contacts the
* dbus daemon. */
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
if (session_bus == NULL)
return FALSE;
reply = g_dbus_connection_call_sync (session_bus, "org.freedesktop.DBus", "/", "org.freedesktop.DBus",
"GetNameOwner", g_variant_new ("(s)", "org.gtk.Notifications"),
G_VARIANT_TYPE ("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL);
g_object_unref (session_bus);
if (reply)
{
g_variant_unref (reply);
return TRUE;
}
else
return FALSE;
}
static void
g_gtk_notification_backend_send_notification (GNotificationBackend *backend,
const gchar *id,
GNotification *notification)
{
GApplication *application;
GVariant *params;
application = g_notification_backend_get_application (backend);
params = g_variant_new ("(ss@a{sv})", g_application_get_application_id (application),
id,
g_notification_serialize (notification));
g_dbus_connection_call (g_notification_backend_get_dbus_connection (backend),
"org.gtk.Notifications", "/org/gtk/Notifications",
"org.gtk.Notifications", "AddNotification", params,
G_VARIANT_TYPE_UNIT,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static void
g_gtk_notification_backend_withdraw_notification (GNotificationBackend *backend,
const gchar *id)
{
GGtkNotificationBackend *self = G_GTK_NOTIFICATION_BACKEND (backend);
GApplication *application;
GVariant *params;
application = g_notification_backend_get_application (backend);
params = g_variant_new ("(ss)", g_application_get_application_id (application), id);
g_dbus_connection_call (self->session_bus, "org.gtk.Notifications",
"/org/gtk/Notifications", "org.gtk.Notifications",
"RemoveNotification", params, G_VARIANT_TYPE_UNIT,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static void
g_gtk_notification_backend_init (GGtkNotificationBackend *backend)
{
}
static void
g_gtk_notification_backend_class_init (GGtkNotificationBackendClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GNotificationBackendClass *backend_class = G_NOTIFICATION_BACKEND_CLASS (class);
object_class->dispose = g_gtk_notification_backend_dispose;
backend_class->is_supported = g_gtk_notification_backend_is_supported;
backend_class->send_notification = g_gtk_notification_backend_send_notification;
backend_class->withdraw_notification = g_gtk_notification_backend_withdraw_notification;
}

View File

@ -897,6 +897,7 @@ extern GType _g_network_monitor_netlink_get_type (void);
#ifdef G_OS_UNIX
extern GType g_fdo_notification_backend_get_type (void);
extern GType g_gtk_notification_backend_get_type (void);
#endif
#ifdef G_PLATFORM_WIN32
@ -1074,6 +1075,7 @@ _g_io_modules_ensure_loaded (void)
#ifdef G_OS_UNIX
g_type_ensure (_g_unix_volume_monitor_get_type ());
g_type_ensure (g_fdo_notification_backend_get_type ());
g_type_ensure (g_gtk_notification_backend_get_type ());
#endif
#ifdef G_OS_WIN32
g_type_ensure (_g_winhttp_vfs_get_type ());

View File

@ -30,7 +30,7 @@ const gchar * g_notification_get_title (GNotifi
const gchar * g_notification_get_body (GNotification *notification);
GIcon * g_notification_get_image (GNotification *notification);
GIcon * g_notification_get_icon (GNotification *notification);
gboolean g_notification_get_urgent (GNotification *notification);
@ -51,4 +51,6 @@ gboolean g_notification_get_default_action (GNotifi
GVariant * g_notification_serialize (GNotification *notification);
GVariant * g_notification_serialize (GNotification *notification);
#endif

View File

@ -34,7 +34,7 @@ struct _GNotification
gchar *title;
gchar *body;
GIcon *image;
GIcon *icon;
gboolean urgent;
GPtrArray *buttons;
gchar *default_action;
@ -68,7 +68,7 @@ g_notification_dispose (GObject *object)
{
GNotification *notification = G_NOTIFICATION (object);
g_clear_object (&notification->image);
g_clear_object (&notification->icon);
G_OBJECT_CLASS (g_notification_parent_class)->dispose (object);
}
@ -210,42 +210,42 @@ g_notification_set_body (GNotification *notification,
}
/**
* g_notification_get_image:
* g_notification_get_icon:
* @notification: a #GNotification
*
* Gets the image currently set on @notification.
* Gets the icon currently set on @notification.
*
* Returns: (transfer none): the image associated with @notification
* Returns: (transfer none): the icon associated with @notification
*
* Since: 2.40
*/
GIcon *
g_notification_get_image (GNotification *notification)
g_notification_get_icon (GNotification *notification)
{
g_return_val_if_fail (G_IS_NOTIFICATION (notification), NULL);
return notification->image;
return notification->icon;
}
/**
* g_notification_set_image:
* g_notification_set_icon:
* @notification: a #GNotification
* @image: the image to be shown in @notification, as a #GIcon
* @icon: the icon to be shown in @notification, as a #GIcon
*
* Sets the image of @notification to @image.
* Sets the icon of @notification to @icon.
*
* Since: 2.40
*/
void
g_notification_set_image (GNotification *notification,
GIcon *image)
g_notification_set_icon (GNotification *notification,
GIcon *icon)
{
g_return_if_fail (G_IS_NOTIFICATION (notification));
if (notification->image)
g_object_unref (notification->image);
if (notification->icon)
g_object_unref (notification->icon);
notification->image = g_object_ref (image);
notification->icon = g_object_ref (icon);
}
/**
@ -637,3 +637,81 @@ g_notification_set_default_action_and_target_value (GNotification *notification,
if (target)
notification->default_action_target = g_variant_ref_sink (target);
}
static GVariant *
g_notification_serialize_button (Button *button)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (button->label));
g_variant_builder_add (&builder, "{sv}", "action", g_variant_new_string (button->action_name));
if (button->target)
g_variant_builder_add (&builder, "{sv}", "target", button->target);
return g_variant_builder_end (&builder);
}
/*< private >
* g_notification_serialize:
*
* Serializes @notification into an floating variant of type a{sv}.
*
* Returns: the serialized @notification as a floating variant.
*/
GVariant *
g_notification_serialize (GNotification *notification)
{
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
if (notification->title)
g_variant_builder_add (&builder, "{sv}", "title", g_variant_new_string (notification->title));
if (notification->body)
g_variant_builder_add (&builder, "{sv}", "body", g_variant_new_string (notification->body));
if (notification->icon)
{
GVariant *serialized_icon;
if ((serialized_icon = g_icon_serialize (notification->icon)))
{
g_variant_builder_add (&builder, "{sv}", "icon", serialized_icon);
g_variant_unref (serialized_icon);
}
}
g_variant_builder_add (&builder, "{sv}", "urgent", g_variant_new_boolean (notification->urgent));
if (notification->default_action)
{
g_variant_builder_add (&builder, "{sv}", "default-action",
g_variant_new_string (notification->default_action));
if (notification->default_action_target)
g_variant_builder_add (&builder, "{sv}", "default-action-target",
notification->default_action_target);
}
if (notification->buttons->len > 0)
{
GVariantBuilder actions_builder;
guint i;
g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
for (i = 0; i < notification->buttons->len; i++)
{
Button *button = g_ptr_array_index (notification->buttons, i);
g_variant_builder_add (&actions_builder, "@a{sv}", g_notification_serialize_button (button));
}
g_variant_builder_add (&builder, "{sv}", "buttons", g_variant_builder_end (&actions_builder));
}
return g_variant_builder_end (&builder);
}

View File

@ -49,8 +49,8 @@ void g_notification_set_body (GNotifi
const gchar *body);
GLIB_AVAILABLE_IN_2_40
void g_notification_set_image (GNotification *notification,
GIcon *image);
void g_notification_set_icon (GNotification *notification,
GIcon *icon);
GLIB_AVAILABLE_IN_2_40
void g_notification_set_urgent (GNotification *notification,

View File

@ -97,10 +97,16 @@ g_notification_backend_activate_action (GNotificationBackend *backend,
GVariant *parameter)
{
g_return_if_fail (G_IS_NOTIFICATION_BACKEND (backend));
g_return_if_fail (name != NULL);
if (g_str_has_prefix (name, "app."))
g_action_group_activate_action (G_ACTION_GROUP (backend->application), name + 4, parameter);
if (name)
{
if (g_str_has_prefix (name, "app."))
g_action_group_activate_action (G_ACTION_GROUP (backend->application), name + 4, parameter);
}
else
{
g_application_activate (backend->application);
}
}
GDBusConnection *