[glib] Add gtk notification backend



commit 766f5584cea0f78921c9288ba7c1c489e6252dd4
Author: Lars Uebernickel <lars uebernic de>
Date:   Tue Oct 15 12:19:09 2013 -0400

    Add gtk notification backend
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688492

 gio/Makefile.am               |    1 +
 gio/gfdonotificationbackend.c |   15 ++--
 gio/ggtknotificationbackend.c |  144 +++++++++++++++++++++++++++++++++++++++++
 gio/giomodule.c               |    2 +
 gio/gnotification-private.h   |    4 +-
 gio/gnotification.c           |  108 ++++++++++++++++++++++++++----
 gio/gnotification.h           |    4 +-
 gio/gnotificationbackend.c    |   12 +++-
 8 files changed, 261 insertions(+), 29 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index a6fd62c..d57510c 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -267,6 +267,7 @@ unix_sources = \
        gcontenttype.c          \
        gcontenttypeprivate.h   \
        gfdonotificationbackend.c \
+       ggtknotificationbackend.c \
        $(NULL)
 
 
diff --git a/gio/gfdonotificationbackend.c b/gio/gfdonotificationbackend.c
index 91af278..ad665be 100644
--- a/gio/gfdonotificationbackend.c
+++ b/gio/gfdonotificationbackend.c
@@ -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);
diff --git a/gio/ggtknotificationbackend.c b/gio/ggtknotificationbackend.c
new file mode 100644
index 0000000..79486b1
--- /dev/null
+++ b/gio/ggtknotificationbackend.c
@@ -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;
+}
diff --git a/gio/giomodule.c b/gio/giomodule.c
index 77624ad..92aa97b 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -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 ());
diff --git a/gio/gnotification-private.h b/gio/gnotification-private.h
index 9521b80..e6513b3 100644
--- a/gio/gnotification-private.h
+++ b/gio/gnotification-private.h
@@ -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
diff --git a/gio/gnotification.c b/gio/gnotification.c
index d912e9f..ec6e061 100644
--- a/gio/gnotification.c
+++ b/gio/gnotification.c
@@ -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);
+}
diff --git a/gio/gnotification.h b/gio/gnotification.h
index 652d7dd..c7e8277 100644
--- a/gio/gnotification.h
+++ b/gio/gnotification.h
@@ -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,
diff --git a/gio/gnotificationbackend.c b/gio/gnotificationbackend.c
index d5ced9c..a3bcde5 100644
--- a/gio/gnotificationbackend.c
+++ b/gio/gnotificationbackend.c
@@ -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 *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]