Port to gdbus

Bug #622891.
This commit is contained in:
Christian Persch 2010-10-12 01:13:31 +02:00
parent ccff2c5b24
commit f63e8ab8b1
12 changed files with 316 additions and 533 deletions

View File

@ -88,17 +88,16 @@ AC_EXEEXT
AM_PROG_LIBTOOL AM_PROG_LIBTOOL
REQ_DBUS_VERSION=0.76
REQ_GTK_VERSION=2.90 REQ_GTK_VERSION=2.90
REQ_GLIB_VERSION=2.6 REQ_GLIB_VERSION=2.26.0
pkg_modules="gdk-pixbuf-2.0 glib-2.0 >= $REQ_GLIB_VERSION, dbus-1 >= $REQ_DBUS_VERSION, dbus-glib-1 >= $REQ_DBUS_VERSION" pkg_modules="gdk-pixbuf-2.0 glib-2.0 >= $REQ_GLIB_VERSION gio-2.0 >= $REQ_GLIB_VERSION"
PKG_CHECK_MODULES(PACKAGE, [$pkg_modules]) PKG_CHECK_MODULES(PACKAGE, [$pkg_modules])
AC_SUBST(PACKAGE_LIBS) AC_SUBST(PACKAGE_LIBS)
AC_SUBST(PACKAGE_CFLAGS) AC_SUBST(PACKAGE_CFLAGS)
AC_SUBST(pkg_modules) AC_SUBST(pkg_modules)
tests_modules="gtk+-3.0 >= $REQ_GTK_VERSION dbus-glib-1 >= $REQ_DBUS_VERSION" tests_modules="gtk+-3.0 >= $REQ_GTK_VERSION"
PKG_CHECK_MODULES(TESTS, [$tests_modules]) PKG_CHECK_MODULES(TESTS, [$tests_modules])
AC_SUBST(TESTS_LIBS) AC_SUBST(TESTS_LIBS)
AC_SUBST(TESTS_CFLAGS) AC_SUBST(TESTS_CFLAGS)
@ -110,18 +109,6 @@ dnl
dnl Check the D-BUS version. dnl Check the D-BUS version.
dnl dnl
AC_MSG_CHECKING([dbus version])
DBUS_VERSION=`$PKG_CONFIG --modversion dbus-1`
DBUS_MAJOR_VER=`echo $DBUS_VERSION | cut -d. -f 1`
DBUS_MINOR_VER=`echo $DBUS_VERSION | cut -d. -f 2`
DBUS_MICRO_VER=`echo $DBUS_VERSION | cut -d. -f 3`
AC_MSG_RESULT($DBUS_VERSION)
AC_DEFINE_UNQUOTED(DBUS_MAJOR_VER, $DBUS_MAJOR_VER, [D-BUS major version.])
AC_DEFINE_UNQUOTED(DBUS_MINOR_VER, $DBUS_MINOR_VER, [D-BUS minor version.])
AC_DEFINE_UNQUOTED(DBUS_MICRO_VER, $DBUS_MICRO_VER, [D-BUS micro version.])
dnl ################################################################ dnl ################################################################
dnl # Set up gtk-doc dnl # Set up gtk-doc
dnl ################################################################ dnl ################################################################

View File

@ -18,6 +18,7 @@ notify_notification_set_timeout
notify_notification_set_category notify_notification_set_category
notify_notification_set_urgency notify_notification_set_urgency
notify_notification_set_icon_from_pixbuf notify_notification_set_icon_from_pixbuf
notify_notification_set_hint
notify_notification_set_hint_int32 notify_notification_set_hint_int32
notify_notification_set_hint_double notify_notification_set_hint_double
notify_notification_set_hint_string notify_notification_set_hint_string

View File

@ -183,6 +183,16 @@ is much like G_CALLBACK().
@icon: @icon:
<!-- ##### FUNCTION notify_notification_set_hint ##### -->
<para>
</para>
@notification:
@key:
@value:
<!-- ##### FUNCTION notify_notification_set_hint_int32 ##### --> <!-- ##### FUNCTION notify_notification_set_hint_int32 ##### -->
<para> <para>

View File

@ -22,19 +22,13 @@
#ifndef _LIBNOTIFY_INTERNAL_H_ #ifndef _LIBNOTIFY_INTERNAL_H_
#define _LIBNOTIFY_INTERNAL_H_ #define _LIBNOTIFY_INTERNAL_H_
#include "config.h"
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#define NOTIFY_DBUS_NAME "org.freedesktop.Notifications" #define NOTIFY_DBUS_NAME "org.freedesktop.Notifications"
#define NOTIFY_DBUS_CORE_INTERFACE "org.freedesktop.Notifications" #define NOTIFY_DBUS_CORE_INTERFACE "org.freedesktop.Notifications"
#define NOTIFY_DBUS_CORE_OBJECT "/org/freedesktop/Notifications" #define NOTIFY_DBUS_CORE_OBJECT "/org/freedesktop/Notifications"
G_BEGIN_DECLS G_BEGIN_DECLS
DBusGConnection * _notify_get_dbus_g_conn (void); GDBusProxy * _notify_get_proxy (GError **error);
DBusGProxy * _notify_get_g_proxy (void);
void _notify_cache_add_notification (NotifyNotification *n); void _notify_cache_add_notification (NotifyNotification *n);
void _notify_cache_remove_notification (NotifyNotification *n); void _notify_cache_remove_notification (NotifyNotification *n);

View File

@ -3,6 +3,7 @@
* Copyright (C) 2006 Christian Hammond * Copyright (C) 2006 Christian Hammond
* Copyright (C) 2006 John Palmieri * Copyright (C) 2006 John Palmieri
* Copyright (C) 2010 Red Hat, Inc. * Copyright (C) 2010 Red Hat, Inc.
* Copyright © 2010 Christian Persch
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -22,8 +23,7 @@
#include "config.h" #include "config.h"
#include <dbus/dbus.h> #include <gio/gio.h>
#include <dbus/dbus-glib.h>
#include "notify.h" #include "notify.h"
#include "internal.h" #include "internal.h"
@ -38,15 +38,6 @@
static void notify_notification_class_init (NotifyNotificationClass *klass); static void notify_notification_class_init (NotifyNotificationClass *klass);
static void notify_notification_init (NotifyNotification *sp); static void notify_notification_init (NotifyNotification *sp);
static void notify_notification_finalize (GObject *object); static void notify_notification_finalize (GObject *object);
static void _close_signal_handler (DBusGProxy *proxy,
guint32 id,
guint32 reason,
NotifyNotification *notification);
static void _action_signal_handler (DBusGProxy *proxy,
guint32 id,
char *action,
NotifyNotification *notification);
typedef struct typedef struct
{ {
@ -78,7 +69,8 @@ struct _NotifyNotificationPrivate
gboolean has_nondefault_actions; gboolean has_nondefault_actions;
gboolean updates_pending; gboolean updates_pending;
gboolean signals_registered;
gulong proxy_signal_handler;
gint closed_reason; gint closed_reason;
}; };
@ -298,13 +290,6 @@ notify_notification_get_property (GObject *object,
} }
} }
static void
_g_value_free (GValue *value)
{
g_value_unset (value);
g_free (value);
}
static void static void
destroy_pair (CallbackPair *pair) destroy_pair (CallbackPair *pair)
{ {
@ -324,29 +309,12 @@ notify_notification_init (NotifyNotification *obj)
obj->priv->hints = g_hash_table_new_full (g_str_hash, obj->priv->hints = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
(GFreeFunc) _g_value_free); (GDestroyNotify) g_variant_unref);
obj->priv->action_map = g_hash_table_new_full (g_str_hash, obj->priv->action_map = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
(GFreeFunc) destroy_pair); (GDestroyNotify) destroy_pair);
}
static void
on_proxy_destroy (DBusGProxy *proxy,
NotifyNotification *notification)
{
if (notification->priv->signals_registered) {
dbus_g_proxy_disconnect_signal (proxy,
"NotificationClosed",
G_CALLBACK (_close_signal_handler),
notification);
dbus_g_proxy_disconnect_signal (proxy,
"ActionInvoked",
G_CALLBACK (_action_signal_handler),
notification);
notification->priv->signals_registered = FALSE;
}
} }
static void static void
@ -354,7 +322,7 @@ notify_notification_finalize (GObject *object)
{ {
NotifyNotification *obj = NOTIFY_NOTIFICATION (object); NotifyNotification *obj = NOTIFY_NOTIFICATION (object);
NotifyNotificationPrivate *priv = obj->priv; NotifyNotificationPrivate *priv = obj->priv;
DBusGProxy *proxy; GDBusProxy *proxy;
_notify_cache_remove_notification (obj); _notify_cache_remove_notification (obj);
@ -373,20 +341,9 @@ notify_notification_finalize (GObject *object)
if (priv->hints != NULL) if (priv->hints != NULL)
g_hash_table_destroy (priv->hints); g_hash_table_destroy (priv->hints);
proxy = _notify_get_g_proxy (); proxy = _notify_get_proxy (NULL);
if (proxy != NULL && priv->signals_registered) { if (proxy != NULL && priv->proxy_signal_handler != 0) {
g_signal_handlers_disconnect_by_func (proxy, g_signal_handler_disconnect (proxy, priv->proxy_signal_handler);
G_CALLBACK (on_proxy_destroy),
object);
dbus_g_proxy_disconnect_signal (proxy,
"NotificationClosed",
G_CALLBACK (_close_signal_handler),
object);
dbus_g_proxy_disconnect_signal (proxy,
"ActionInvoked",
G_CALLBACK (_action_signal_handler),
object);
} }
g_free (obj->priv); g_free (obj->priv);
@ -466,64 +423,51 @@ notify_notification_update (NotifyNotification *notification,
} }
static void static void
_close_signal_handler (DBusGProxy *proxy, proxy_g_signal_cb (GDBusProxy *proxy,
guint32 id, const char *sender_name,
guint32 reason, const char *signal_name,
NotifyNotification *notification) GVariant *parameters,
NotifyNotification *notification)
{ {
if (id == notification->priv->id) { g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
if (g_strcmp0 (signal_name, "NotificationClosed") == 0 &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) {
guint32 id, reason;
g_variant_get (parameters, "(uu)", &id, &reason);
if (id != notification->priv->id)
return;
g_object_ref (G_OBJECT (notification)); g_object_ref (G_OBJECT (notification));
notification->priv->closed_reason = reason; notification->priv->closed_reason = reason;
g_signal_emit (notification, signals[SIGNAL_CLOSED], 0); g_signal_emit (notification, signals[SIGNAL_CLOSED], 0);
notification->priv->id = 0; notification->priv->id = 0;
g_object_unref (G_OBJECT (notification)); g_object_unref (G_OBJECT (notification));
} } else if (g_strcmp0 (signal_name, "ActionInvoked") == 0 &&
} g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(us)"))) {
guint32 id;
const char *action;
CallbackPair *pair;
static void g_variant_get (parameters, "(u&s)", &id, &action);
_action_signal_handler (DBusGProxy *proxy,
guint32 id,
char *action,
NotifyNotification *notification)
{
CallbackPair *pair;
g_return_if_fail (notification != NULL); if (id != notification->priv->id)
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification)); return;
if (id != notification->priv->id) pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map,
return; action);
pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map, if (pair == NULL) {
action); if (g_ascii_strcasecmp (action, "default")) {
g_warning ("Received unknown action %s", action);
if (pair == NULL) { }
if (g_ascii_strcasecmp (action, "default")) { } else {
g_warning ("Received unknown action %s", action); pair->cb (notification, (char *) action, pair->user_data);
} }
} else {
pair->cb (notification, action, pair->user_data);
} }
} }
static char **
_gslist_to_string_array (GSList *list)
{
GSList *l;
GArray *a;
a = g_array_sized_new (TRUE,
FALSE,
sizeof (char *),
g_slist_length (list));
for (l = list; l != NULL; l = l->next) {
g_array_append_val (a, l->data);
}
return (char **) g_array_free (a, FALSE);
}
/** /**
* notify_notification_show: * notify_notification_show:
* @notification: The notification. * @notification: The notification.
@ -539,70 +483,69 @@ notify_notification_show (NotifyNotification *notification,
GError **error) GError **error)
{ {
NotifyNotificationPrivate *priv; NotifyNotificationPrivate *priv;
GError *tmp_error = NULL; GDBusProxy *proxy;
char **action_array; GVariantBuilder actions_builder, hints_builder;
DBusGProxy *proxy; GSList *l;
GHashTableIter iter;
gpointer key, data;
GVariant *result;
g_return_val_if_fail (notification != NULL, FALSE); g_return_val_if_fail (notification != NULL, FALSE);
g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE); g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
priv = notification->priv; priv = notification->priv;
proxy = _notify_get_g_proxy (); proxy = _notify_get_proxy (error);
if (proxy == NULL) { if (proxy == NULL) {
g_set_error (error, 0, 0, "Unable to connect to server");
return FALSE; return FALSE;
} }
if (!priv->signals_registered) { if (priv->proxy_signal_handler == 0) {
g_signal_connect (proxy, priv->proxy_signal_handler = g_signal_connect (proxy,
"destroy", "g-signal",
G_CALLBACK (on_proxy_destroy), G_CALLBACK (proxy_g_signal_cb),
notification); notification);
dbus_g_proxy_connect_signal (proxy,
"NotificationClosed",
G_CALLBACK (_close_signal_handler),
notification,
NULL);
dbus_g_proxy_connect_signal (proxy,
"ActionInvoked",
G_CALLBACK (_action_signal_handler),
notification,
NULL);
priv->signals_registered = TRUE;
} }
action_array = _gslist_to_string_array (priv->actions); g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("as"));
for (l = priv->actions; l != NULL; l = l->next) {
g_variant_builder_add (&actions_builder, "s", l->data);
}
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
g_hash_table_iter_init (&iter, priv->hints);
while (g_hash_table_iter_next (&iter, &key, &data)) {
g_variant_builder_add (&hints_builder, "{sv}", key, data);
}
/* TODO: make this nonblocking */ /* TODO: make this nonblocking */
dbus_g_proxy_call (proxy, result = g_dbus_proxy_call_sync (proxy,
"Notify", "Notify",
&tmp_error, g_variant_new ("(susssasa{sv}i)",
G_TYPE_STRING, notify_get_app_name (), notify_get_app_name (),
G_TYPE_UINT, priv->id, priv->id,
G_TYPE_STRING, priv->icon_name, priv->icon_name ? priv->icon_name : "",
G_TYPE_STRING, priv->summary, priv->summary ? priv->summary : "",
G_TYPE_STRING, priv->body, priv->body ? priv->body : "",
G_TYPE_STRV, action_array, &actions_builder,
dbus_g_type_get_map ("GHashTable", &hints_builder,
G_TYPE_STRING, priv->timeout),
G_TYPE_VALUE), G_DBUS_CALL_FLAGS_NONE,
priv->hints, -1 /* FIXME ? */,
G_TYPE_INT, priv->timeout, NULL,
G_TYPE_INVALID, error);
G_TYPE_UINT, &priv->id, if (result == NULL) {
G_TYPE_INVALID);
/* Don't free the elements because they are owned by priv->actions */
g_free (action_array);
if (tmp_error != NULL) {
g_propagate_error (error, tmp_error);
return FALSE; return FALSE;
} }
if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(u)"))) {
g_variant_unref (result);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"Unexpected reply type");
return FALSE;
}
g_variant_get (result, "(u)", &priv->id);
g_variant_unref (result);
return TRUE; return TRUE;
} }
@ -676,47 +619,6 @@ notify_notification_set_urgency (NotifyNotification *notification,
(guchar) urgency); (guchar) urgency);
} }
static void
_gvalue_array_append_int (GValueArray *array,
gint i)
{
GValue value = { 0 };
g_value_init (&value, G_TYPE_INT);
g_value_set_int (&value, i);
g_value_array_append (array, &value);
g_value_unset (&value);
}
static void
_gvalue_array_append_bool (GValueArray *array, gboolean b)
{
GValue value = { 0 };
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, b);
g_value_array_append (array, &value);
g_value_unset (&value);
}
static void
_gvalue_array_append_byte_array (GValueArray *array,
guchar *bytes,
gsize len)
{
GArray *byte_array;
GValue value = { 0 };
byte_array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
g_assert (byte_array != NULL);
byte_array = g_array_append_vals (byte_array, bytes, len);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (&value, byte_array);
g_value_array_append (array, &value);
g_value_unset (&value);
}
/** /**
* notify_notification_set_icon_from_pixbuf: * notify_notification_set_icon_from_pixbuf:
* @notification: The notification. * @notification: The notification.
@ -757,12 +659,21 @@ notify_notification_set_image_from_pixbuf (NotifyNotification *notification,
guchar *image; guchar *image;
gboolean has_alpha; gboolean has_alpha;
gsize image_len; gsize image_len;
GValueArray *image_struct; GVariant *value;
GValue *value;
const char *hint_name; const char *hint_name;
g_return_if_fail (notification != NULL); g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
if (_notify_check_spec_version(1, 1)) {
hint_name = "image_data";
} else {
hint_name = "icon_data";
}
if (pixbuf == NULL) {
notify_notification_set_hint (notification, hint_name, NULL);
return;
}
g_object_get (pixbuf, g_object_get (pixbuf,
"width", &width, "width", &width,
@ -776,29 +687,50 @@ notify_notification_set_image_from_pixbuf (NotifyNotification *notification,
image_len = (height - 1) * rowstride + width * image_len = (height - 1) * rowstride + width *
((n_channels * bits_per_sample + 7) / 8); ((n_channels * bits_per_sample + 7) / 8);
image_struct = g_value_array_new (1); value = g_variant_new ("(iiibii@ay)",
width,
height,
rowstride,
has_alpha,
bits_per_sample,
n_channels,
g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
image,
image_len,
TRUE,
(GDestroyNotify) g_object_unref,
pixbuf));
notify_notification_set_hint (notification, hint_name, value);
}
_gvalue_array_append_int (image_struct, width); /**
_gvalue_array_append_int (image_struct, height); * notify_notification_set_hint:
_gvalue_array_append_int (image_struct, rowstride); * @notification: a #NotifyNotification
_gvalue_array_append_bool (image_struct, has_alpha); * @key: the hint key
_gvalue_array_append_int (image_struct, bits_per_sample); * @variant: (allow-none): the hint value, or %NULL to unset the hint
_gvalue_array_append_int (image_struct, n_channels); *
_gvalue_array_append_byte_array (image_struct, image, image_len); * Sets a hint for @key with value @variant. If @value is %NULL,
* a previously set hint for @key is unset.
*
* If @variant is floating, it is consumed.
*
* Since: 0.6
*/
void
notify_notification_set_hint (NotifyNotification *notification,
const char *key,
GVariant *value)
{
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
value = g_new0 (GValue, 1); if (value != NULL) {
g_value_init (value, G_TYPE_VALUE_ARRAY); g_hash_table_insert (notification->priv->hints,
g_value_take_boxed (value, image_struct); g_strdup (key),
g_variant_ref_sink (value));
if (_notify_check_spec_version(1, 1)) {
hint_name = "image_data";
} else { } else {
hint_name = "icon_data"; g_hash_table_remove (notification->priv->hints, key);
} }
g_hash_table_insert (notification->priv->hints,
g_strdup (hint_name),
value);
} }
/** /**
@ -808,24 +740,16 @@ notify_notification_set_image_from_pixbuf (NotifyNotification *notification,
* @value: The hint's value. * @value: The hint's value.
* *
* Sets a hint with a 32-bit integer value. * Sets a hint with a 32-bit integer value.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_int32 (NotifyNotification *notification, notify_notification_set_hint_int32 (NotifyNotification *notification,
const char *key, const char *key,
gint value) gint value)
{ {
GValue *hint_value; notify_notification_set_hint (notification, key,
g_variant_new_int32 (value));
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
hint_value = g_new0 (GValue, 1);
g_value_init (hint_value, G_TYPE_INT);
g_value_set_int (hint_value, value);
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
@ -836,24 +760,16 @@ notify_notification_set_hint_int32 (NotifyNotification *notification,
* @value: The hint's value. * @value: The hint's value.
* *
* Sets a hint with an unsigned 32-bit integer value. * Sets a hint with an unsigned 32-bit integer value.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_uint32 (NotifyNotification *notification, notify_notification_set_hint_uint32 (NotifyNotification *notification,
const char *key, const char *key,
guint value) guint value)
{ {
GValue *hint_value; notify_notification_set_hint (notification, key,
g_variant_new_uint32 (value));
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
hint_value = g_new0 (GValue, 1);
g_value_init (hint_value, G_TYPE_UINT);
g_value_set_uint (hint_value, value);
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
/** /**
@ -863,24 +779,16 @@ notify_notification_set_hint_uint32 (NotifyNotification *notification,
* @value: The hint's value. * @value: The hint's value.
* *
* Sets a hint with a double value. * Sets a hint with a double value.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_double (NotifyNotification *notification, notify_notification_set_hint_double (NotifyNotification *notification,
const char *key, const char *key,
gdouble value) gdouble value)
{ {
GValue *hint_value; notify_notification_set_hint (notification, key,
g_variant_new_double (value));
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
hint_value = g_new0 (GValue, 1);
g_value_init (hint_value, G_TYPE_FLOAT);
g_value_set_float (hint_value, value);
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
/** /**
@ -890,25 +798,16 @@ notify_notification_set_hint_double (NotifyNotification *notification,
* @value: The hint's value. * @value: The hint's value.
* *
* Sets a hint with a byte value. * Sets a hint with a byte value.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_byte (NotifyNotification *notification, notify_notification_set_hint_byte (NotifyNotification *notification,
const char *key, const char *key,
guchar value) guchar value)
{ {
GValue *hint_value; notify_notification_set_hint (notification, key,
g_variant_new_byte (value));
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
hint_value = g_new0 (GValue, 1);
g_value_init (hint_value, G_TYPE_UCHAR);
g_value_set_uchar (hint_value, value);
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
/** /**
@ -920,6 +819,8 @@ notify_notification_set_hint_byte (NotifyNotification *notification,
* *
* Sets a hint with a byte array value. The length of @value must be passed * Sets a hint with a byte array value. The length of @value must be passed
* as @len. * as @len.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_byte_array (NotifyNotification *notification, notify_notification_set_hint_byte_array (NotifyNotification *notification,
@ -927,26 +828,18 @@ notify_notification_set_hint_byte_array (NotifyNotification *notification,
const guchar *value, const guchar *value,
gsize len) gsize len)
{ {
GValue *hint_value; gpointer value_dup;
GArray *byte_array;
g_return_if_fail (notification != NULL); g_return_if_fail (value != NULL || len == 0);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
g_return_if_fail (value != NULL);
g_return_if_fail (len > 0);
byte_array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len); value_dup = g_memdup (value, len);
byte_array = g_array_append_vals (byte_array, value, len); notify_notification_set_hint (notification, key,
g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
hint_value = g_new0 (GValue, 1); value_dup,
g_value_init (hint_value, dbus_g_type_get_collection ("GArray", len,
G_TYPE_UCHAR)); TRUE,
g_value_take_boxed (hint_value, byte_array); g_free,
value_dup));
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
/** /**
@ -956,24 +849,16 @@ notify_notification_set_hint_byte_array (NotifyNotification *notification,
* @value: The hint's value. * @value: The hint's value.
* *
* Sets a hint with a string value. * Sets a hint with a string value.
*
* Deprecated: 0.6. Use notify_notification_set_hint() instead
*/ */
void void
notify_notification_set_hint_string (NotifyNotification *notification, notify_notification_set_hint_string (NotifyNotification *notification,
const char *key, const char *key,
const char *value) const char *value)
{ {
GValue *hint_value; notify_notification_set_hint (notification, key,
g_variant_new_string (value));
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (key != NULL && *key != '\0');
hint_value = g_new0 (GValue, 1);
g_value_init (hint_value, G_TYPE_STRING);
g_value_set_string (hint_value, value);
g_hash_table_insert (notification->priv->hints,
g_strdup (key),
hint_value);
} }
static gboolean static gboolean
@ -1051,7 +936,6 @@ notify_notification_add_action (NotifyNotification *notification,
NotifyNotificationPrivate *priv; NotifyNotificationPrivate *priv;
CallbackPair *pair; CallbackPair *pair;
g_return_if_fail (notification != NULL);
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification)); g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
g_return_if_fail (action != NULL && *action != '\0'); g_return_if_fail (action != NULL && *action != '\0');
g_return_if_fail (label != NULL && *label != '\0'); g_return_if_fail (label != NULL && *label != '\0');
@ -1088,44 +972,42 @@ _notify_notification_has_nondefault_actions (const NotifyNotification *n)
* @notification: The notification. * @notification: The notification.
* @error: The returned error information. * @error: The returned error information.
* *
* Tells the notification server to hide the notification on the screen. * Synchronously tells the notification server to hide the notification on the screen.
* *
* Returns: %TRUE if successful. On error, this will return %FALSE and set * Returns: %TRUE on success, or %FALSE on error with @error filled in
* @error.
*/ */
gboolean gboolean
notify_notification_close (NotifyNotification *notification, notify_notification_close (NotifyNotification *notification,
GError **error) GError **error)
{ {
NotifyNotificationPrivate *priv; NotifyNotificationPrivate *priv;
GError *tmp_error = NULL; GDBusProxy *proxy;
DBusGProxy *proxy; GVariant *result;
g_return_val_if_fail (notification != NULL, FALSE);
g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE); g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
priv = notification->priv; priv = notification->priv;
proxy = _notify_get_g_proxy (); proxy = _notify_get_proxy (error);
if (proxy == NULL) { if (proxy == NULL) {
g_set_error (error, 0, 0, "Unable to connect to server");
return FALSE; return FALSE;
} }
dbus_g_proxy_call (proxy, /* FIXME: make this nonblocking! */
"CloseNotification", result = g_dbus_proxy_call_sync (proxy,
&tmp_error, "CloseNotification",
G_TYPE_UINT, g_variant_new ("(u)", priv->id),
priv->id, G_DBUS_CALL_FLAGS_NONE,
G_TYPE_INVALID, -1 /* FIXME! */,
G_TYPE_INVALID); NULL,
error);
if (tmp_error != NULL) { if (result == NULL) {
g_propagate_error (error, tmp_error);
return FALSE; return FALSE;
} }
g_variant_unref (result);
return TRUE; return TRUE;
} }

View File

@ -126,6 +126,10 @@ void notify_notification_set_hint_byte_array (NotifyNotificatio
const guchar *value, const guchar *value,
gsize len); gsize len);
void notify_notification_set_hint (NotifyNotification *notification,
const char *key,
GVariant *value);
void notify_notification_clear_hints (NotifyNotification *notification); void notify_notification_clear_hints (NotifyNotification *notification);
void notify_notification_add_action (NotifyNotification *notification, void notify_notification_add_action (NotifyNotification *notification,

View File

@ -3,6 +3,7 @@
* Copyright (C) 2004-2006 Christian Hammond <chipx86@chipx86.com> * Copyright (C) 2004-2006 Christian Hammond <chipx86@chipx86.com>
* Copyright (C) 2004-2006 Mike Hearn <mike@navi.cx> * Copyright (C) 2004-2006 Mike Hearn <mike@navi.cx>
* Copyright (C) 2010 Red Hat, Inc. * Copyright (C) 2010 Red Hat, Inc.
* Copyright © 2010 Christian Persch
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -28,8 +29,7 @@
#include <unistd.h> #include <unistd.h>
#include <glib.h> #include <glib.h>
#include <dbus/dbus.h> #include <gio/gio.h>
#include <dbus/dbus-glib.h>
#include "notify.h" #include "notify.h"
#include "internal.h" #include "internal.h"
@ -37,8 +37,7 @@
static gboolean _initted = FALSE; static gboolean _initted = FALSE;
static char *_app_name = NULL; static char *_app_name = NULL;
static DBusGProxy *_proxy = NULL; static GDBusProxy *_proxy = NULL;
static DBusGConnection *_dbus_gconn = NULL;
static GList *_active_notifications = NULL; static GList *_active_notifications = NULL;
static int _spec_version_major = 0; static int _spec_version_major = 0;
static int _spec_version_minor = 0; static int _spec_version_minor = 0;
@ -55,11 +54,52 @@ _notify_check_spec_version (int major,
} }
static gboolean static gboolean
_notify_update_spec_version (void) _notify_get_server_info (char **ret_name,
char **ret_vendor,
char **ret_version,
char **ret_spec_version,
GError **error)
{
GDBusProxy *proxy;
GVariant *result;
proxy = _notify_get_proxy (error);
if (proxy == NULL) {
return FALSE;
}
result = g_dbus_proxy_call_sync (proxy,
"GetServerInformation",
g_variant_new ("()"),
G_DBUS_CALL_FLAGS_NONE,
-1 /* FIXME shorter timeout? */,
NULL,
error);
if (result == NULL) {
return FALSE;
}
if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(ssss)"))) {
g_variant_unref (result);
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
"Unexpected reply type");
return FALSE;
}
g_variant_get (result, "(ssss)",
ret_name,
ret_vendor,
ret_version,
ret_spec_version);
g_variant_unref (result);
return TRUE;
}
static gboolean
_notify_update_spec_version (GError **error)
{ {
char *spec_version; char *spec_version;
if (!notify_get_server_info (NULL, NULL, NULL, &spec_version)) { if (!_notify_get_server_info (NULL, NULL, NULL, &spec_version, error)) {
return FALSE; return FALSE;
} }
@ -146,6 +186,7 @@ notify_uninit (void)
if (_proxy != NULL) { if (_proxy != NULL) {
g_object_unref (_proxy); g_object_unref (_proxy);
_proxy = NULL;
} }
_initted = FALSE; _initted = FALSE;
@ -164,136 +205,105 @@ notify_is_initted (void)
return _initted; return _initted;
} }
DBusGConnection * /*
_notify_get_dbus_g_conn (void) * _notify_get_proxy:
* @error: (allow-none): a location to store a #GError, or %NULL
*
* Synchronously creates the #GDBusProxy for the notification service,
* and caches the result.
*
* Returns: the #GDBusProxy for the notification service, or %NULL on error
*/
GDBusProxy *
_notify_get_proxy (GError **error)
{ {
return _dbus_gconn;
}
static void
on_proxy_destroy (DBusGProxy *proxy,
gpointer data)
{
_proxy = NULL;
}
DBusGProxy *
_notify_get_g_proxy (void)
{
GError *error;
DBusGConnection *bus;
if (_proxy != NULL) if (_proxy != NULL)
return _proxy; return _proxy;
/* lazily initialize D-Bus connection */ _proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
error = NULL; G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); NULL,
if (error != NULL) { NOTIFY_DBUS_NAME,
g_error_free (error); NOTIFY_DBUS_CORE_OBJECT,
NOTIFY_DBUS_CORE_INTERFACE,
NULL,
error);
if (_proxy == NULL) {
return NULL; return NULL;
} }
_proxy = dbus_g_proxy_new_for_name (bus, if (!_notify_update_spec_version (error)) {
NOTIFY_DBUS_NAME, g_object_unref (_proxy);
NOTIFY_DBUS_CORE_OBJECT, _proxy = NULL;
NOTIFY_DBUS_CORE_INTERFACE);
dbus_g_connection_unref (bus);
g_signal_connect (_proxy,
"destroy",
G_CALLBACK (on_proxy_destroy),
NULL);
dbus_g_object_register_marshaller (notify_marshal_VOID__UINT_UINT,
G_TYPE_NONE,
G_TYPE_UINT,
G_TYPE_UINT,
G_TYPE_INVALID);
dbus_g_object_register_marshaller (notify_marshal_VOID__UINT_STRING,
G_TYPE_NONE,
G_TYPE_UINT,
G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (_proxy,
"NotificationClosed",
G_TYPE_UINT,
G_TYPE_UINT,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (_proxy,
"ActionInvoked",
G_TYPE_UINT,
G_TYPE_STRING,
G_TYPE_INVALID);
if (!_notify_update_spec_version ()) {
return NULL; return NULL;
} }
g_object_add_weak_pointer (G_OBJECT (_proxy), (gpointer *) &_proxy);
return _proxy; return _proxy;
} }
/** /**
* notify_get_server_caps: * notify_get_server_caps:
* *
* Queries the server for its capabilities and returns them in a #GList. * Synchronously queries the server for its capabilities and returns them in a #GList.
* *
* Returns: A #GList of server capability strings. * Returns: (transfer full) (element-type utf-8): a #GList of server capability strings. Free
* the list elements with g_free() and the list itself with g_list_free().
*/ */
GList * GList *
notify_get_server_caps (void) notify_get_server_caps (void)
{ {
GError *error; GDBusProxy *proxy;
char **caps; GVariant *result;
char **cap; char **cap, **caps;
GList *result; GList *list = NULL;
DBusGProxy *proxy;
caps = NULL; proxy = _notify_get_proxy (NULL);
result = NULL;
proxy = _notify_get_g_proxy ();
if (proxy == NULL) { if (proxy == NULL) {
return NULL; return FALSE;
} }
error = NULL; result = g_dbus_proxy_call_sync (proxy,
if (!dbus_g_proxy_call (proxy, "GetCapabilities",
"GetCapabilities", g_variant_new ("()"),
&error, G_DBUS_CALL_FLAGS_NONE,
G_TYPE_INVALID, -1 /* FIXME shorter timeout? */,
G_TYPE_STRV, NULL,
&caps, NULL);
G_TYPE_INVALID)) { if (result == NULL) {
g_error_free (error); return FALSE;
return NULL;
} }
if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(as)"))) {
g_variant_unref (result);
return FALSE;
}
g_variant_get (result, "(^as)", &caps);
for (cap = caps; *cap != NULL; cap++) { for (cap = caps; *cap != NULL; cap++) {
result = g_list_append (result, g_strdup (*cap)); list = g_list_prepend (list, *cap);
} }
g_strfreev (caps); g_free (caps);
g_variant_unref (result);
return result; return g_list_reverse (list);
} }
/** /**
* notify_get_server_info: * notify_get_server_info:
* @ret_name: The resulting server name. * @ret_name: (out) (allow-none): a location to store the server name, or %NULL
* @ret_vendor: The resulting server vendor. * @ret_vendor: (out) (allow-none): a location to store the server vendor, or %NULL
* @ret_version: The resulting server version. * @ret_version: (out) (allow-none): a location to store the server version, or %NULL
* @ret_spec_version: The resulting version of the specification the server is * @ret_spec_version: (out) (allow-none): a location to store the version the service is compliant with, or %NULL
* compliant with.
* *
* Queries the server for its information, specifically, the name, vendor, * Synchronously queries the server for its information, specifically, the name, vendor,
* server version, and the version of the notifications specification that it * server version, and the version of the notifications specification that it
* is compliant with. * is compliant with.
* *
* Returns: %TRUE if successful, and the variables passed will be set. %FALSE * Returns: %TRUE if successful, and the variables passed will be set, %FALSE
* on failure. * on error. The returned strings must be freed with g_free
*/ */
gboolean gboolean
notify_get_server_info (char **ret_name, notify_get_server_info (char **ret_name,
@ -301,57 +311,7 @@ notify_get_server_info (char **ret_name,
char **ret_version, char **ret_version,
char **ret_spec_version) char **ret_spec_version)
{ {
GError *error; return _notify_get_server_info (ret_name, ret_vendor, ret_version, ret_spec_version, NULL);
DBusGProxy *proxy;
char *name;
char *vendor;
char *version;
char *spec_version;
proxy = _notify_get_g_proxy ();
if (proxy == NULL) {
return FALSE;
}
error = NULL;
if (!dbus_g_proxy_call (proxy,
"GetServerInformation",
&error,
G_TYPE_INVALID,
G_TYPE_STRING, &name,
G_TYPE_STRING, &vendor,
G_TYPE_STRING, &version,
G_TYPE_STRING, &spec_version,
G_TYPE_INVALID)) {
g_error_free (error);
return FALSE;
}
if (ret_name != NULL) {
*ret_name = name;
} else {
g_free (name);
}
if (ret_vendor != NULL) {
*ret_vendor = vendor;
} else {
g_free (vendor);
}
if (ret_version != NULL) {
*ret_version = version;
} else {
g_free (version);
}
if (ret_spec_version != NULL) {
*ret_spec_version = spec_version;
} else {
g_free (spec_version);
}
return TRUE;
} }
void void

View File

@ -60,25 +60,8 @@ gboolean notify_is_initted (void);
*/ */
const char *notify_get_app_name (void); const char *notify_get_app_name (void);
/**
* Returns the capabilities of the notification server.
*
* @return A list of capability strings. These strings must be freed.
*/
GList *notify_get_server_caps (void); GList *notify_get_server_caps (void);
/**
* Returns the server notification information.
*
* The strings returned must be freed.
*
* @param ret_name The returned product name of the server.
* @param ret_vendor The returned vendor.
* @param ret_version The returned server version.
* @param ret_spec_version The returned specification version supported.
*
* @return TRUE if the call succeeded, or FALSE if there were errors.
*/
gboolean notify_get_server_info (char **ret_name, gboolean notify_get_server_info (char **ret_name,
char **ret_vendor, char **ret_vendor,
char **ret_version, char **ret_version,

View File

@ -27,13 +27,6 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
static GMainLoop *loop; static GMainLoop *loop;
static void static void
@ -54,16 +47,12 @@ int
main () main ()
{ {
NotifyNotification *n; NotifyNotification *n;
DBusConnection *conn;
if (!notify_init ("Default Action Test")) if (!notify_init ("Default Action Test"))
exit (1); exit (1);
conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
loop = g_main_loop_new (NULL, FALSE); loop = g_main_loop_new (NULL, FALSE);
dbus_connection_setup_with_g_main (conn, NULL);
n = notify_notification_new ("Matt is online", "", NULL); n = notify_notification_new ("Matt is online", "", NULL);
notify_notification_set_timeout (n, NOTIFY_EXPIRES_DEFAULT); notify_notification_set_timeout (n, NOTIFY_EXPIRES_DEFAULT);
notify_notification_add_action (n, notify_notification_add_action (n,

View File

@ -31,14 +31,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <glib.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
GMainLoop *loop; GMainLoop *loop;
NotifyNotification *n; NotifyNotification *n;

View File

@ -26,13 +26,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
static GMainLoop *loop; static GMainLoop *loop;
static void static void
@ -82,16 +75,12 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
NotifyNotification *n; NotifyNotification *n;
DBusConnection *conn;
if (!notify_init ("Multi Action Test")) if (!notify_init ("Multi Action Test"))
exit (1); exit (1);
conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
loop = g_main_loop_new (NULL, FALSE); loop = g_main_loop_new (NULL, FALSE);
dbus_connection_setup_with_g_main (conn, NULL);
n = notify_notification_new ("Low disk space", n = notify_notification_new ("Low disk space",
"You can free up some disk space by " "You can free up some disk space by "
"emptying the trash can.", "emptying the trash can.",

View File

@ -24,11 +24,6 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
static GMainLoop *loop; static GMainLoop *loop;
static void static void
@ -44,15 +39,11 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
NotifyNotification *n; NotifyNotification *n;
DBusConnection *conn;
notify_init ("XY"); notify_init ("XY");
conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
loop = g_main_loop_new (NULL, FALSE); loop = g_main_loop_new (NULL, FALSE);
dbus_connection_setup_with_g_main (conn, NULL);
n = notify_notification_new ("System update available", n = notify_notification_new ("System update available",
"New system updates are available. It is " "New system updates are available. It is "
"recommended that you install the updates.", "recommended that you install the updates.",