diff --git a/ChangeLog b/ChangeLog index 6837709..2b50c4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sat Jan 21 00:37:03 PST 2006 Christian Hammond + + * libnotify/internal.h: + * libnotify/notification.c: + * libnotify/notify.c: + * tests/test-image.c: + - Use one D-BUS connection, one GProxy, total. This is better than the + one per notification, and fixes a few bugs. + Fri Jan 20 20:49:31 PST 2006 Christian Hammond * libnotify/notify.c: diff --git a/libnotify/internal.h b/libnotify/internal.h index 2aa1155..9c46374 100644 --- a/libnotify/internal.h +++ b/libnotify/internal.h @@ -21,8 +21,22 @@ #ifndef _LIBNOTIFY_INTERNAL_H_ #define _LIBNOTIFY_INTERNAL_H_ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef DBUS_API_SUBJECT_TO_CHANGE +# define DBUS_API_SUBJECT_TO_CHANGE 1 +#endif + +#include +#include + #define NOTIFY_DBUS_NAME "org.freedesktop.Notifications" #define NOTIFY_DBUS_CORE_INTERFACE "org.freedesktop.Notifications" #define NOTIFY_DBUS_CORE_OBJECT "/org/freedesktop/Notifications" +DBusGConnection *get_dbus_g_conn(void); +DBusGProxy *get_g_proxy(void); + #endif /* _LIBNOTIFY_INTERNAL_H_ */ diff --git a/libnotify/notification.c b/libnotify/notification.c index 12dea92..4fa182b 100644 --- a/libnotify/notification.c +++ b/libnotify/notification.c @@ -24,7 +24,6 @@ #include #include -#include #include static void notify_notification_class_init(NotifyNotificationClass *klass); @@ -70,8 +69,7 @@ struct _NotifyNotificationPrivate gint widget_old_y; gboolean updates_pending; - - DBusGProxy *proxy; + gboolean signals_registered; }; enum @@ -102,11 +100,6 @@ notify_notification_class_init(NotifyNotificationClass * klass) G_STRUCT_OFFSET(NotifyNotificationClass, closed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - dbus_g_object_register_marshaller(notify_marshal_VOID__UINT_STRING, - G_TYPE_NONE, - G_TYPE_UINT, - G_TYPE_STRING, G_TYPE_INVALID); } static void @@ -129,13 +122,7 @@ static void notify_notification_init(NotifyNotification *obj) { obj->priv = g_new0(NotifyNotificationPrivate, 1); - - obj->priv->id = 0; - obj->priv->summary = NULL; - obj->priv->body = NULL; - obj->priv->icon_name = NULL; obj->priv->timeout = NOTIFY_EXPIRES_DEFAULT; - obj->priv->actions = NULL; obj->priv->hints = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GFreeFunc)_g_value_free); @@ -143,15 +130,6 @@ notify_notification_init(NotifyNotification *obj) obj->priv->action_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GFreeFunc)destroy_pair); - - obj->priv->attached_widget = NULL; - - obj->priv->updates_pending = FALSE; - - obj->priv->widget_old_x = 0; - obj->priv->widget_old_y = 0; - - obj->priv->proxy = NULL; } static void @@ -159,6 +137,7 @@ notify_notification_finalize(GObject *object) { NotifyNotification *obj = NOTIFY_NOTIFICATION(object); NotifyNotificationPrivate *priv = obj->priv; + DBusGProxy *proxy = get_g_proxy(); g_free(priv->summary); g_free(priv->body); @@ -179,13 +158,15 @@ notify_notification_finalize(GObject *object) if (priv->attached_widget != NULL) g_object_unref(G_OBJECT(priv->attached_widget)); - dbus_g_proxy_disconnect_signal(priv->proxy, "NotificationClosed", - G_CALLBACK(_close_signal_handler), - object); - - dbus_g_proxy_disconnect_signal(priv->proxy, "ActionInvoked", - G_CALLBACK(_action_signal_handler), - object); + if (priv->signals_registered) + { + 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); @@ -388,42 +369,26 @@ notify_notification_show(NotifyNotification *notification, GError **error) NotifyNotificationPrivate *priv; GError *tmp_error = NULL; gchar **action_array; + DBusGProxy *proxy; g_return_val_if_fail(notification != NULL, FALSE); g_return_val_if_fail(NOTIFY_IS_NOTIFICATION(notification), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = notification->priv; + proxy = get_g_proxy(); - if (priv->proxy == NULL) + if (!priv->signals_registered) { - DBusGConnection *bus = dbus_g_bus_get(DBUS_BUS_SESSION, &tmp_error); - - if (tmp_error != NULL) - { - g_propagate_error(error, tmp_error); - return FALSE; - } - - priv->proxy = dbus_g_proxy_new_for_name(bus, - NOTIFY_DBUS_NAME, - NOTIFY_DBUS_CORE_OBJECT, - NOTIFY_DBUS_CORE_INTERFACE); - - dbus_g_proxy_add_signal(priv->proxy, "NotificationClosed", - G_TYPE_UINT, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, "NotificationClosed", + dbus_g_proxy_connect_signal(proxy, "NotificationClosed", G_CALLBACK(_close_signal_handler), notification, NULL); - dbus_g_proxy_add_signal(priv->proxy, "ActionInvoked", - G_TYPE_UINT, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(priv->proxy, "ActionInvoked", + dbus_g_proxy_connect_signal(proxy, "ActionInvoked", G_CALLBACK(_action_signal_handler), notification, NULL); - dbus_g_connection_unref(bus); + priv->signals_registered = TRUE; } /* If attached to a widget, modify x and y in hints */ @@ -432,20 +397,19 @@ notify_notification_show(NotifyNotification *notification, GError **error) action_array = _gslist_to_string_array(priv->actions); /* TODO: make this nonblocking */ - dbus_g_proxy_call( - priv->proxy, "Notify", &tmp_error, - G_TYPE_STRING, notify_get_app_name(), - G_TYPE_UINT, priv->id, - G_TYPE_STRING, priv->icon_name != NULL ? priv->icon_name : "", - G_TYPE_STRING, priv->summary, - G_TYPE_STRING, priv->body, - G_TYPE_STRV, action_array, - dbus_g_type_get_map("GHashTable", G_TYPE_STRING, - G_TYPE_VALUE), priv->hints, - G_TYPE_INT, priv->timeout, - G_TYPE_INVALID, - G_TYPE_UINT, &priv->id, - G_TYPE_INVALID); + dbus_g_proxy_call(proxy, "Notify", &tmp_error, + G_TYPE_STRING, notify_get_app_name(), + G_TYPE_UINT, priv->id, + G_TYPE_STRING, priv->icon_name, + G_TYPE_STRING, priv->summary, + G_TYPE_STRING, priv->body, + G_TYPE_STRV, action_array, + dbus_g_type_get_map("GHashTable", G_TYPE_STRING, + G_TYPE_VALUE), priv->hints, + G_TYPE_INT, priv->timeout, + G_TYPE_INVALID, + G_TYPE_UINT, &priv->id, + G_TYPE_INVALID); /* Don't free the elements because they are owned by priv->actions */ g_free(action_array); @@ -538,7 +502,7 @@ _gvalue_array_append_byte_array(GValueArray *array, guchar *bytes, gsize len) return FALSE; } - g_value_init(value, dbus_g_type_get_collection("GArray", G_TYPE_UCHAR)); + g_value_init(value, dbus_g_type_get_collection("GArray", G_TYPE_CHAR)); g_value_set_boxed_take_ownership(value, byte_array); g_value_array_append(array, value); @@ -572,35 +536,22 @@ notify_notification_set_icon_from_pixbuf(NotifyNotification *notification, image = gdk_pixbuf_get_pixels(icon); - image_struct = g_value_array_new(8); - - if (image_struct == NULL) - goto fail; + image_struct = g_value_array_new(1); _gvalue_array_append_int(image_struct, width); - _gvalue_array_append_int(image_struct, height); - _gvalue_array_append_int(image_struct, rowstride); - _gvalue_array_append_bool(image_struct, gdk_pixbuf_get_has_alpha(icon)); - _gvalue_array_append_int(image_struct, bits_per_sample); - _gvalue_array_append_int(image_struct, n_channels); - _gvalue_array_append_byte_array(image_struct, image, image_len); +// _gvalue_array_append_int(image_struct, height); +// _gvalue_array_append_int(image_struct, rowstride); +// _gvalue_array_append_bool(image_struct, gdk_pixbuf_get_has_alpha(icon)); +// _gvalue_array_append_int(image_struct, bits_per_sample); +// _gvalue_array_append_int(image_struct, n_channels); +// _gvalue_array_append_byte_array(image_struct, image, image_len); value = g_new0(GValue, 1); - - if (value == NULL) - goto fail; - g_value_init(value, G_TYPE_VALUE_ARRAY); g_value_set_boxed(value, image_struct); g_hash_table_insert(notification->priv->hints, g_strdup("icon_data"), value); - - return; - -fail: - if (image_struct != NULL) - g_value_array_free(image_struct); } void @@ -771,24 +722,7 @@ notify_notification_close(NotifyNotification *notification, priv = notification->priv; - if (priv->proxy == NULL) - { - DBusGConnection *bus = dbus_g_bus_get(DBUS_BUS_SESSION, &tmp_error); - - if (tmp_error != NULL) - { - g_propagate_error(error, tmp_error); - return FALSE; - } - - priv->proxy = dbus_g_proxy_new_for_name(bus, - NOTIFY_DBUS_NAME, - NOTIFY_DBUS_CORE_OBJECT, - NOTIFY_DBUS_CORE_INTERFACE); - dbus_g_connection_unref(bus); - } - - dbus_g_proxy_call(priv->proxy, "CloseNotification", &tmp_error, + dbus_g_proxy_call(get_g_proxy(), "CloseNotification", &tmp_error, G_TYPE_UINT, priv->id, G_TYPE_INVALID, G_TYPE_INVALID); diff --git a/libnotify/notify.c b/libnotify/notify.c index 489a7e0..c77a9aa 100644 --- a/libnotify/notify.c +++ b/libnotify/notify.c @@ -19,27 +19,18 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifndef DBUS_API_SUBJECT_TO_CHANGE -# define DBUS_API_SUBJECT_TO_CHANGE 1 -#endif - -#include -#include #include #include #include #include #include #include +#include static gboolean _initted = FALSE; static gchar *_app_name = NULL; static DBusGProxy *_proxy = NULL; +static DBusGConnection *_dbus_gconn = NULL; #ifdef __GNUC__ # define format_func __attribute__((format(printf, 1, 2))) @@ -50,6 +41,9 @@ static DBusGProxy *_proxy = NULL; gboolean notify_init(const char *app_name) { + GError *error = NULL; + DBusGConnection *bus = NULL; + g_return_val_if_fail(app_name != NULL, FALSE); g_return_val_if_fail(*app_name != '\0', FALSE); @@ -60,6 +54,32 @@ notify_init(const char *app_name) g_type_init(); + bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + + if (error != NULL) + { + g_message("Unable to get session bus: %s", error->message); + g_error_free(error); + return FALSE; + } + + _proxy = dbus_g_proxy_new_for_name(bus, + NOTIFY_DBUS_NAME, + NOTIFY_DBUS_CORE_OBJECT, + NOTIFY_DBUS_CORE_INTERFACE); + dbus_g_connection_unref(bus); + + 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_INVALID); + dbus_g_proxy_add_signal(_proxy, "ActionInvoked", + G_TYPE_UINT, G_TYPE_STRING, + G_TYPE_INVALID); + #ifdef HAVE_ATEXIT atexit(notify_uninit); #endif /* HAVE_ATEXIT */ @@ -96,30 +116,15 @@ notify_is_initted(void) return _initted; } -static DBusGProxy * -get_proxy(void) +DBusGConnection * +get_dbus_g_conn(void) { - DBusGConnection *bus; - GError *error = NULL; - - if (_proxy != NULL) - return _proxy; - - bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - - if (error != NULL) - { - g_message("Unable to get session bus: %s", error->message); - g_error_free(error); - return NULL; - } - - _proxy = dbus_g_proxy_new_for_name(bus, - NOTIFY_DBUS_NAME, - NOTIFY_DBUS_CORE_OBJECT, - NOTIFY_DBUS_CORE_INTERFACE); - dbus_g_connection_unref(bus); + return _dbus_gconn; +} +DBusGProxy * +get_g_proxy(void) +{ return _proxy; } @@ -129,7 +134,7 @@ notify_get_server_caps(void) GError *error = NULL; char **caps = NULL, **cap; GList *result = NULL; - DBusGProxy *proxy = get_proxy(); + DBusGProxy *proxy = get_g_proxy(); g_return_val_if_fail(proxy != NULL, NULL); @@ -157,7 +162,7 @@ notify_get_server_info(char **ret_name, char **ret_vendor, char **ret_version, char **ret_spec_version) { GError *error = NULL; - DBusGProxy *proxy = get_proxy(); + DBusGProxy *proxy = get_g_proxy(); char *name, *vendor, *version, *spec_version; g_return_val_if_fail(proxy != NULL, FALSE); diff --git a/tests/test-image.c b/tests/test-image.c index c921f72..32f5471 100644 --- a/tests/test-image.c +++ b/tests/test-image.c @@ -56,27 +56,17 @@ main(int argc, char *argv[]) if (!notify_init("Images Test")) exit(1); + /* Stock icon */ n = notify_notification_new("Icon Test", "Testing stock icon", "stock_help", NULL); - notify_notification_set_hint_int32(n, "x", 300); - notify_notification_set_hint_int32(n, "y", 24); - notify_notification_set_timeout(n, NOTIFY_EXPIRES_DEFAULT); - helper = gtk_button_new(); - icon = gtk_widget_render_icon(helper, - GTK_STOCK_DIALOG_QUESTION, - GTK_ICON_SIZE_DIALOG, - NULL); - - notify_notification_set_icon_from_pixbuf(n, icon); - if (!notify_notification_show(n, NULL)) { fprintf(stderr, "failed to send notification\n"); return 1; } - g_usleep(5000000); // 5 seconds + g_object_unref(G_OBJECT(n)); size = readlink("/proc/self/cwd", file, PATH_MAX - 1); file[size] = '\0'; @@ -84,7 +74,8 @@ main(int argc, char *argv[]) printf("sending %s\n", uri); - notify_notification_update(n, "Alert!", "Testing URI icons", uri); + /* URIs */ + n = notify_notification_new("Alert!", "Testing URI icons", uri, NULL); if (!notify_notification_show(n, NULL)) { @@ -92,10 +83,11 @@ main(int argc, char *argv[]) return 1; } - g_usleep(5000000); // 5 seconds + g_object_unref(G_OBJECT(n)); - notify_notification_update(n, "Raw image test", - "Testing sending raw pixbufs", NULL); + /* Raw image */ + n = notify_notification_new("Raw image test", + "Testing sending raw pixbufs", NULL, NULL); /* * This is just a hack to get a stock icon's pixbuf in a realworld app @@ -107,8 +99,10 @@ main(int argc, char *argv[]) GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG, NULL); + gtk_widget_destroy(helper); notify_notification_set_icon_from_pixbuf(n, icon); + g_object_unref(G_OBJECT(icon)); if (!notify_notification_show(n, NULL)) { @@ -116,11 +110,7 @@ main(int argc, char *argv[]) return 1; } - - gtk_widget_destroy(helper); - g_object_unref(G_OBJECT(icon)); - - g_usleep(5000000); // 5 seconds + g_object_unref(G_OBJECT(n)); return 0; }