~ubuntu-branches/ubuntu/saucy/libnotify/saucy

« back to all changes in this revision

Viewing changes to libnotify/notification.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-07-31 00:15:19 UTC
  • mfrom: (2.1.27 oneiric)
  • Revision ID: james.westby@ubuntu.com-20110731001519-rmpx11anrwlnjvw0
Tags: 0.7.3-2
* debian/control.in:
  - Remove duplicates Section to please lintian
  - Fix duplicate Description to please lintian
* debian/rules: Drop include of check-dist.mk
* debian/watch:
  - Switch to .bz2 tarballs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 * Copyright (C) 2006 Christian Hammond
4
4
 * Copyright (C) 2006 John Palmieri
5
5
 * Copyright (C) 2010 Red Hat, Inc.
 
6
 * Copyright © 2010 Christian Persch
6
7
 *
7
8
 * This library is free software; you can redistribute it and/or
8
9
 * modify it under the terms of the GNU Lesser General Public
22
23
 
23
24
#include "config.h"
24
25
 
25
 
#include <dbus/dbus.h>
26
 
#include <dbus/dbus-glib.h>
27
 
 
28
 
#include <gtk/gtk.h>
29
 
#include <gdk/gdkx.h>
 
26
#include <gio/gio.h>
30
27
 
31
28
#include "notify.h"
32
29
#include "internal.h"
33
30
 
 
31
 
 
32
/**
 
33
 * SECTION:notification
 
34
 * @Short_description: A passive pop-up notification.
 
35
 * @Title: NotifyNotification
 
36
 *
 
37
 * #NotifyNotification represents a passive pop-up notification. It can
 
38
 * contain summary text, body text, and an icon, as well as hints specifying
 
39
 * how the notification should be presented. The notification is rendered
 
40
 * by a notification daemon, and may present the notification in any number
 
41
 * of ways. As such, there is a clear separation of content and presentation,
 
42
 * and this API enforces that.
 
43
 */
 
44
 
 
45
 
34
46
#if !defined(G_PARAM_STATIC_NAME) && !defined(G_PARAM_STATIC_NICK) && \
35
47
    !defined(G_PARAM_STATIC_BLURB)
36
48
# define G_PARAM_STATIC_NAME 0
41
53
static void     notify_notification_class_init (NotifyNotificationClass *klass);
42
54
static void     notify_notification_init       (NotifyNotification *sp);
43
55
static void     notify_notification_finalize   (GObject            *object);
44
 
static void     _close_signal_handler          (DBusGProxy         *proxy,
45
 
                                                guint32             id,
46
 
                                                guint32             reason,
47
 
                                                NotifyNotification *notification);
48
 
 
49
 
static void     _action_signal_handler         (DBusGProxy         *proxy,
50
 
                                                guint32             id,
51
 
                                                char               *action,
52
 
                                                NotifyNotification *notification);
53
56
 
54
57
typedef struct
55
58
{
62
65
struct _NotifyNotificationPrivate
63
66
{
64
67
        guint32         id;
 
68
        char           *app_name;
65
69
        char           *summary;
66
70
        char           *body;
67
71
 
79
83
        GHashTable     *action_map;
80
84
        GHashTable     *hints;
81
85
 
82
 
        GtkWidget      *attached_widget;
83
 
        GtkStatusIcon  *status_icon;
84
 
 
85
86
        gboolean        has_nondefault_actions;
86
87
        gboolean        updates_pending;
87
 
        gboolean        signals_registered;
 
88
 
 
89
        gulong          proxy_signal_handler;
88
90
 
89
91
        gint            closed_reason;
90
92
};
99
101
{
100
102
        PROP_0,
101
103
        PROP_ID,
 
104
        PROP_APP_NAME,
102
105
        PROP_SUMMARY,
103
106
        PROP_BODY,
104
107
        PROP_ICON_NAME,
105
 
        PROP_ATTACH_WIDGET,
106
 
        PROP_STATUS_ICON,
107
108
        PROP_CLOSED_REASON
108
109
};
109
110
 
180
181
                                                           | G_PARAM_STATIC_BLURB));
181
182
 
182
183
        g_object_class_install_property (object_class,
 
184
                                         PROP_APP_NAME,
 
185
                                         g_param_spec_string ("app-name",
 
186
                                                              "Application name",
 
187
                                                              "The application name to use for this notification",
 
188
                                                              NULL,
 
189
                                                              G_PARAM_READWRITE
 
190
                                                              | G_PARAM_STATIC_NAME
 
191
                                                              | G_PARAM_STATIC_NICK
 
192
                                                              | G_PARAM_STATIC_BLURB));
 
193
 
 
194
        g_object_class_install_property (object_class,
183
195
                                         PROP_SUMMARY,
184
196
                                         g_param_spec_string ("summary",
185
197
                                                              "Summary",
216
228
                                                              | G_PARAM_STATIC_BLURB));
217
229
 
218
230
        g_object_class_install_property (object_class,
219
 
                                         PROP_ATTACH_WIDGET,
220
 
                                         g_param_spec_object ("attach-widget",
221
 
                                                              "Attach Widget",
222
 
                                                              "The widget to attach the notification to",
223
 
                                                              GTK_TYPE_WIDGET,
224
 
                                                              G_PARAM_READWRITE
225
 
                                                              | G_PARAM_CONSTRUCT
226
 
                                                              | G_PARAM_STATIC_NAME
227
 
                                                              | G_PARAM_STATIC_NICK
228
 
                                                              | G_PARAM_STATIC_BLURB));
229
 
 
230
 
        g_object_class_install_property (object_class,
231
 
                                         PROP_STATUS_ICON,
232
 
                                         g_param_spec_object ("status-icon",
233
 
                                                              "Status Icon",
234
 
                                                              "The status icon to attach the notification to",
235
 
                                                              GTK_TYPE_STATUS_ICON,
236
 
                                                              G_PARAM_READWRITE
237
 
                                                              | G_PARAM_CONSTRUCT
238
 
                                                              | G_PARAM_STATIC_NAME
239
 
                                                              | G_PARAM_STATIC_NICK
240
 
                                                              | G_PARAM_STATIC_BLURB));
241
 
 
242
 
        g_object_class_install_property (object_class,
243
231
                                         PROP_CLOSED_REASON,
244
232
                                         g_param_spec_int ("closed-reason",
245
233
                                                           "Closed Reason",
254
242
}
255
243
 
256
244
static void
 
245
notify_notification_update_internal (NotifyNotification *notification,
 
246
                                     const char         *app_name,
 
247
                                     const char         *summary,
 
248
                                     const char         *body,
 
249
                                     const char         *icon);
 
250
 
 
251
static void
257
252
notify_notification_set_property (GObject      *object,
258
253
                                  guint         prop_id,
259
254
                                  const GValue *value,
267
262
                priv->id = g_value_get_int (value);
268
263
                break;
269
264
 
 
265
        case PROP_APP_NAME:
 
266
                notify_notification_update_internal (notification,
 
267
                                                     g_value_get_string (value),
 
268
                                                     priv->summary,
 
269
                                                     priv->body,
 
270
                                                     priv->icon_name);
 
271
                break;
 
272
 
270
273
        case PROP_SUMMARY:
271
 
                notify_notification_update (notification,
272
 
                                            g_value_get_string (value),
273
 
                                            priv->body,
274
 
                                            priv->icon_name);
 
274
                notify_notification_update_internal (notification,
 
275
                                                     priv->app_name,
 
276
                                                     g_value_get_string (value),
 
277
                                                     priv->body,
 
278
                                                     priv->icon_name);
275
279
                break;
276
280
 
277
281
        case PROP_BODY:
278
 
                notify_notification_update (notification,
279
 
                                            priv->summary,
280
 
                                            g_value_get_string (value),
281
 
                                            priv->icon_name);
 
282
                notify_notification_update_internal (notification,
 
283
                                                     priv->app_name,
 
284
                                                     priv->summary,
 
285
                                                     g_value_get_string (value),
 
286
                                                     priv->icon_name);
282
287
                break;
283
288
 
284
289
        case PROP_ICON_NAME:
285
 
                notify_notification_update (notification,
286
 
                                            priv->summary,
287
 
                                            priv->body,
288
 
                                            g_value_get_string (value));
289
 
                break;
290
 
 
291
 
        case PROP_ATTACH_WIDGET:
292
 
                notify_notification_attach_to_widget (notification,
293
 
                                                      g_value_get_object (value));
294
 
                break;
295
 
 
296
 
        case PROP_STATUS_ICON:
297
 
                notify_notification_attach_to_status_icon (notification,
298
 
                                                           g_value_get_object (value));
 
290
                notify_notification_update_internal (notification,
 
291
                                                     priv->app_name,
 
292
                                                     priv->summary,
 
293
                                                     priv->body,
 
294
                                                     g_value_get_string (value));
299
295
                break;
300
296
 
301
297
        default:
322
318
                g_value_set_string (value, priv->summary);
323
319
                break;
324
320
 
 
321
        case PROP_APP_NAME:
 
322
                g_value_set_string (value, priv->app_name);
 
323
                break;
 
324
 
325
325
        case PROP_BODY:
326
326
                g_value_set_string (value, priv->body);
327
327
                break;
330
330
                g_value_set_string (value, priv->icon_name);
331
331
                break;
332
332
 
333
 
        case PROP_ATTACH_WIDGET:
334
 
                g_value_set_object (value, priv->attached_widget);
335
 
                break;
336
 
 
337
 
        case PROP_STATUS_ICON:
338
 
                g_value_set_object (value, priv->status_icon);
339
 
                break;
340
 
 
341
333
        case PROP_CLOSED_REASON:
342
334
                g_value_set_int (value, priv->closed_reason);
343
335
                break;
349
341
}
350
342
 
351
343
static void
352
 
_g_value_free (GValue *value)
353
 
{
354
 
        g_value_unset (value);
355
 
        g_free (value);
356
 
}
357
 
 
358
 
static void
359
344
destroy_pair (CallbackPair *pair)
360
345
{
361
346
        if (pair->user_data != NULL && pair->free_func != NULL) {
374
359
        obj->priv->hints = g_hash_table_new_full (g_str_hash,
375
360
                                                  g_str_equal,
376
361
                                                  g_free,
377
 
                                                  (GFreeFunc) _g_value_free);
 
362
                                                  (GDestroyNotify) g_variant_unref);
378
363
 
379
364
        obj->priv->action_map = g_hash_table_new_full (g_str_hash,
380
365
                                                       g_str_equal,
381
366
                                                       g_free,
382
 
                                                       (GFreeFunc) destroy_pair);
383
 
}
384
 
 
385
 
static void
386
 
on_proxy_destroy (DBusGProxy         *proxy,
387
 
                  NotifyNotification *notification)
388
 
{
389
 
        if (notification->priv->signals_registered) {
390
 
                dbus_g_proxy_disconnect_signal (proxy,
391
 
                                                "NotificationClosed",
392
 
                                                G_CALLBACK (_close_signal_handler),
393
 
                                                notification);
394
 
                dbus_g_proxy_disconnect_signal (proxy,
395
 
                                                "ActionInvoked",
396
 
                                                G_CALLBACK (_action_signal_handler),
397
 
                                                notification);
398
 
                notification->priv->signals_registered = FALSE;
399
 
        }
 
367
                                                       (GDestroyNotify) destroy_pair);
400
368
}
401
369
 
402
370
static void
404
372
{
405
373
        NotifyNotification        *obj = NOTIFY_NOTIFICATION (object);
406
374
        NotifyNotificationPrivate *priv = obj->priv;
407
 
        DBusGProxy                *proxy;
 
375
        GDBusProxy                *proxy;
408
376
 
409
377
        _notify_cache_remove_notification (obj);
410
378
 
 
379
        g_free (priv->app_name);
411
380
        g_free (priv->summary);
412
381
        g_free (priv->body);
413
382
        g_free (priv->icon_name);
423
392
        if (priv->hints != NULL)
424
393
                g_hash_table_destroy (priv->hints);
425
394
 
426
 
        if (priv->attached_widget != NULL)
427
 
                g_object_unref (G_OBJECT (priv->attached_widget));
428
 
 
429
 
        if (priv->status_icon != NULL)
430
 
                g_object_remove_weak_pointer (G_OBJECT (priv->status_icon),
431
 
                                              (gpointer) & priv->status_icon);
432
 
 
433
 
        proxy = _notify_get_g_proxy ();
434
 
        if (proxy != NULL && priv->signals_registered) {
435
 
                g_signal_handlers_disconnect_by_func (proxy,
436
 
                                                      G_CALLBACK (on_proxy_destroy),
437
 
                                                      object);
438
 
 
439
 
                dbus_g_proxy_disconnect_signal (proxy,
440
 
                                                "NotificationClosed",
441
 
                                                G_CALLBACK (_close_signal_handler),
442
 
                                                object);
443
 
                dbus_g_proxy_disconnect_signal (proxy,
444
 
                                                "ActionInvoked",
445
 
                                                G_CALLBACK (_action_signal_handler),
446
 
                                                object);
 
395
        proxy = _notify_get_proxy (NULL);
 
396
        if (proxy != NULL && priv->proxy_signal_handler != 0) {
 
397
                g_signal_handler_disconnect (proxy, priv->proxy_signal_handler);
447
398
        }
448
399
 
449
400
        g_free (obj->priv);
451
402
        G_OBJECT_CLASS (parent_class)->finalize (object);
452
403
}
453
404
 
454
 
static void
455
 
_notify_notification_update_applet_hints (NotifyNotification *n)
456
 
{
457
 
        NotifyNotificationPrivate *priv = n->priv;
458
 
        GdkScreen                 *screen = NULL;
459
 
        gint                       x, y;
460
 
 
461
 
        if (priv->status_icon != NULL) {
462
 
                GdkRectangle    rect;
463
 
                guint32         xid;
464
 
 
465
 
                xid = gtk_status_icon_get_x11_window_id (priv->status_icon);
466
 
                if (xid > 0) {
467
 
                        notify_notification_set_hint_uint32 (n, "window-xid", xid);
468
 
                }
469
 
 
470
 
                if (!gtk_status_icon_get_geometry (priv->status_icon,
471
 
                                                   &screen,
472
 
                                                   &rect,
473
 
                                                   NULL)) {
474
 
                        return;
475
 
                }
476
 
 
477
 
                x = rect.x + rect.width / 2;
478
 
                y = rect.y + rect.height / 2;
479
 
        } else if (priv->attached_widget != NULL) {
480
 
                GtkWidget    *widget = priv->attached_widget;
481
 
                GtkAllocation allocation;
482
 
 
483
 
                screen = gtk_widget_get_screen (widget);
484
 
 
485
 
                gdk_window_get_origin (gtk_widget_get_window (widget), &x, &y);
486
 
                gtk_widget_get_allocation (widget, &allocation);
487
 
 
488
 
                if (!gtk_widget_get_has_window (widget)) {
489
 
                        x += allocation.x;
490
 
                        y += allocation.y;
491
 
                }
492
 
 
493
 
                x += allocation.width / 2;
494
 
                y += allocation.height / 2;
495
 
        } else {
496
 
                return;
497
 
        }
498
 
 
499
 
        notify_notification_set_geometry_hints (n, screen, x, y);
500
 
}
501
 
 
502
405
/**
503
406
 * notify_notification_new:
504
407
 * @summary: The required summary text.
505
 
 * @body: The optional body text.
506
 
 * @icon: The optional icon theme icon name or filename.
507
 
 * @attach: The optional widget to attach to.
 
408
 * @body: (allow-none): The optional body text.
 
409
 * @icon: (allow-none): The optional icon theme icon name or filename.
508
410
 *
509
411
 * Creates a new #NotifyNotification. The summary text is required, but
510
412
 * all other parameters are optional.
514
416
NotifyNotification *
515
417
notify_notification_new (const char *summary,
516
418
                         const char *body,
517
 
                         const char *icon,
518
 
                         GtkWidget  *attach)
 
419
                         const char *icon)
519
420
{
520
 
        g_return_val_if_fail (attach == NULL || GTK_IS_WIDGET (attach), NULL);
521
 
 
522
421
        return g_object_new (NOTIFY_TYPE_NOTIFICATION,
523
422
                             "summary", summary,
524
423
                             "body", body,
525
424
                             "icon-name", icon,
526
 
                             "attach-widget", attach,
527
 
                             NULL);
528
 
}
529
 
 
530
 
/**
531
 
 * notify_notification_new_with_status_icon:
532
 
 * @summary: The required summary text.
533
 
 * @body: The optional body text.
534
 
 * @icon: The optional icon theme icon name or filename.
535
 
 * @status_icon: The required #GtkStatusIcon.
536
 
 *
537
 
 * Creates a new #NotifyNotification and attaches to a #GtkStatusIcon.
538
 
 * The summary text and @status_icon is required, but all other parameters
539
 
 * are optional.
540
 
 *
541
 
 * Returns: The new #NotifyNotification.
542
 
 *
543
 
 * Since: 0.4.1
544
 
 */
545
 
NotifyNotification *
546
 
notify_notification_new_with_status_icon (const char    *summary,
547
 
                                          const char    *message,
548
 
                                          const char    *icon,
549
 
                                          GtkStatusIcon *status_icon)
550
 
{
551
 
        g_return_val_if_fail (status_icon != NULL, NULL);
552
 
        g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
553
 
 
554
 
        return g_object_new (NOTIFY_TYPE_NOTIFICATION,
555
 
                             "summary", summary,
556
 
                             "body", message,
557
 
                             "icon-name", icon,
558
 
                             "status-icon", status_icon,
559
 
                             NULL);
560
 
}
561
 
 
562
 
/**
563
 
 * notify_notification_update:
564
 
 * @notification: The notification to update.
565
 
 * @summary: The new required summary text.
566
 
 * @body: The optional body text.
567
 
 * @icon: The optional icon theme icon name or filename.
568
 
 *
569
 
 * Updates the notification text and icon. This won't send the update out
570
 
 * and display it on the screen. For that, you will need to call
571
 
 * notify_notification_show().
572
 
 *
573
 
 * Returns: %TRUE, unless an invalid parameter was passed.
574
 
 */
575
 
gboolean
576
 
notify_notification_update (NotifyNotification *notification,
577
 
                            const char         *summary,
578
 
                            const char         *body,
579
 
                            const char         *icon)
580
 
{
581
 
        g_return_val_if_fail (notification != NULL, FALSE);
582
 
        g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
583
 
        g_return_val_if_fail (summary != NULL && *summary != '\0', FALSE);
 
425
                             NULL);
 
426
}
 
427
 
 
428
static void
 
429
notify_notification_update_internal (NotifyNotification *notification,
 
430
                                     const char         *app_name,
 
431
                                     const char         *summary,
 
432
                                     const char         *body,
 
433
                                     const char         *icon)
 
434
{
 
435
        if (notification->priv->app_name != app_name) {
 
436
                g_free (notification->priv->app_name);
 
437
                notification->priv->app_name = g_strdup (app_name);
 
438
                g_object_notify (G_OBJECT (notification), "app-name");
 
439
        }
584
440
 
585
441
        if (notification->priv->summary != summary) {
586
442
                g_free (notification->priv->summary);
603
459
        }
604
460
 
605
461
        notification->priv->updates_pending = TRUE;
 
462
}
 
463
 
 
464
/**
 
465
 * notify_notification_update:
 
466
 * @notification: The notification to update.
 
467
 * @summary: The new required summary text.
 
468
 * @body: (allow-none): The optional body text.
 
469
 * @icon: (allow-none): The optional icon theme icon name or filename.
 
470
 *
 
471
 * Updates the notification text and icon. This won't send the update out
 
472
 * and display it on the screen. For that, you will need to call
 
473
 * notify_notification_show().
 
474
 *
 
475
 * Returns: %TRUE, unless an invalid parameter was passed.
 
476
 */
 
477
gboolean
 
478
notify_notification_update (NotifyNotification *notification,
 
479
                            const char         *summary,
 
480
                            const char         *body,
 
481
                            const char         *icon)
 
482
{
 
483
        g_return_val_if_fail (notification != NULL, FALSE);
 
484
        g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
 
485
        g_return_val_if_fail (summary != NULL && *summary != '\0', FALSE);
 
486
 
 
487
        notify_notification_update_internal (notification,
 
488
                                             notification->priv->app_name,
 
489
                                             summary, body, icon);
606
490
 
607
491
        return TRUE;
608
492
}
609
493
 
610
 
/**
611
 
 * notify_notification_attach_to_widget:
612
 
 * @notification: The notification.
613
 
 * @attach: The widget to attach to, or %NULL.
614
 
 *
615
 
 * Attaches the notification to a widget. This will set hints on the
616
 
 * notification requesting that the notification point to the widget's
617
 
 * location. If @attach is %NULL, the widget will be unset.
618
 
 */
619
 
void
620
 
notify_notification_attach_to_widget (NotifyNotification *notification,
621
 
                                      GtkWidget          *attach)
622
 
{
623
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
624
 
 
625
 
        if (notification->priv->attached_widget == attach)
626
 
                return;
627
 
 
628
 
        if (notification->priv->attached_widget != NULL)
629
 
                g_object_unref (notification->priv->attached_widget);
630
 
 
631
 
        notification->priv->attached_widget =
632
 
                (attach != NULL ? g_object_ref (attach) : NULL);
633
 
 
634
 
        g_object_notify (G_OBJECT (notification), "attach-widget");
635
 
}
636
 
 
637
 
/**
638
 
 * notify_notification_attach_to_status_icon:
639
 
 * @notification: The notification.
640
 
 * @status_icon: The #GtkStatusIcon to attach to, or %NULL.
641
 
 *
642
 
 * Attaches the notification to a #GtkStatusIcon. This will set hints on the
643
 
 * notification requesting that the notification point to the status icon's
644
 
 * location. If @status_icon is %NULL, the status icon will be unset.
645
 
 *
646
 
 * Since: 0.4.1
647
 
 */
648
 
void
649
 
notify_notification_attach_to_status_icon (NotifyNotification *notification,
650
 
                                           GtkStatusIcon      *status_icon)
651
 
{
652
 
        NotifyNotificationPrivate *priv;
653
 
 
654
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
655
 
        g_return_if_fail (status_icon == NULL
656
 
                          || GTK_IS_STATUS_ICON (status_icon));
657
 
 
658
 
        priv = notification->priv;
659
 
 
660
 
        if (priv->status_icon == status_icon)
661
 
                return;
662
 
 
663
 
        if (priv->status_icon != NULL) {
664
 
                g_object_remove_weak_pointer (G_OBJECT (priv->status_icon),
665
 
                                              (gpointer) & priv->status_icon);
666
 
        }
667
 
 
668
 
        priv->status_icon = status_icon;
669
 
 
670
 
        if (priv->status_icon != NULL) {
671
 
                g_object_add_weak_pointer (G_OBJECT (priv->status_icon),
672
 
                                           (gpointer) & priv->status_icon);
673
 
        }
674
 
 
675
 
        g_object_notify (G_OBJECT (notification), "status-icon");
676
 
}
677
 
 
678
 
/**
679
 
 * notify_notification_set_geometry_hints:
680
 
 * @notification: The notification.
681
 
 * @screen: The #GdkScreen the notification should appear on.
682
 
 * @x: The X coordinate to point to.
683
 
 * @y: The Y coordinate to point to.
684
 
 *
685
 
 * Sets the geometry hints on the notification. This sets the screen
686
 
 * the notification should appear on and the X, Y coordinates it should
687
 
 * point to, if the particular notification supports X, Y hints.
688
 
 *
689
 
 * Since: 0.4.1
690
 
 */
691
 
void
692
 
notify_notification_set_geometry_hints (NotifyNotification *notification,
693
 
                                        GdkScreen          *screen,
694
 
                                        gint                x,
695
 
                                        gint                y)
696
 
{
697
 
        char *display_name;
698
 
 
699
 
        g_return_if_fail (notification != NULL);
700
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
701
 
        g_return_if_fail (screen != NULL);
702
 
        g_return_if_fail (GDK_IS_SCREEN (screen));
703
 
 
704
 
        notify_notification_set_hint_int32 (notification, "x", x);
705
 
        notify_notification_set_hint_int32 (notification, "y", y);
706
 
 
707
 
        display_name = gdk_screen_make_display_name (screen);
708
 
        notify_notification_set_hint_string (notification,
709
 
                                             "xdisplay",
710
 
                                             display_name);
711
 
        g_free (display_name);
712
 
}
713
 
 
714
494
static void
715
 
_close_signal_handler (DBusGProxy         *proxy,
716
 
                       guint32             id,
717
 
                       guint32             reason,
718
 
                       NotifyNotification *notification)
 
495
proxy_g_signal_cb (GDBusProxy *proxy,
 
496
                   const char *sender_name,
 
497
                   const char *signal_name,
 
498
                   GVariant   *parameters,
 
499
                   NotifyNotification *notification)
719
500
{
720
 
        if (id == notification->priv->id) {
 
501
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
 
502
 
 
503
        if (g_strcmp0 (signal_name, "NotificationClosed") == 0 &&
 
504
            g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) {
 
505
                guint32 id, reason;
 
506
 
 
507
                g_variant_get (parameters, "(uu)", &id, &reason);
 
508
                if (id != notification->priv->id)
 
509
                        return;
 
510
 
721
511
                g_object_ref (G_OBJECT (notification));
722
512
                notification->priv->closed_reason = reason;
723
513
                g_signal_emit (notification, signals[SIGNAL_CLOSED], 0);
724
514
                notification->priv->id = 0;
725
515
                g_object_unref (G_OBJECT (notification));
726
 
        }
727
 
}
728
 
 
729
 
static void
730
 
_action_signal_handler (DBusGProxy         *proxy,
731
 
                        guint32             id,
732
 
                        char               *action,
733
 
                        NotifyNotification *notification)
734
 
{
735
 
        CallbackPair *pair;
736
 
 
737
 
        g_return_if_fail (notification != NULL);
738
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
739
 
 
740
 
        if (id != notification->priv->id)
741
 
                return;
742
 
 
743
 
        pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map,
744
 
                                                     action);
745
 
 
746
 
        if (pair == NULL) {
747
 
                if (g_ascii_strcasecmp (action, "default")) {
748
 
                        g_warning ("Received unknown action %s", action);
 
516
        } else if (g_strcmp0 (signal_name, "ActionInvoked") == 0 &&
 
517
                   g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(us)"))) {
 
518
                guint32 id;
 
519
                const char *action;
 
520
                CallbackPair *pair;
 
521
 
 
522
                g_variant_get (parameters, "(u&s)", &id, &action);
 
523
 
 
524
                if (id != notification->priv->id)
 
525
                        return;
 
526
 
 
527
                pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map,
 
528
                                                            action);
 
529
 
 
530
                if (pair == NULL) {
 
531
                        if (g_ascii_strcasecmp (action, "default")) {
 
532
                                g_warning ("Received unknown action %s", action);
 
533
                        }
 
534
                } else {
 
535
                        pair->cb (notification, (char *) action, pair->user_data);
749
536
                }
750
 
        } else {
751
 
                pair->cb (notification, action, pair->user_data);
752
 
        }
753
 
}
754
 
 
755
 
static char  **
756
 
_gslist_to_string_array (GSList *list)
757
 
{
758
 
        GSList *l;
759
 
        GArray *a;
760
 
 
761
 
        a = g_array_sized_new (TRUE,
762
 
                               FALSE,
763
 
                               sizeof (char *),
764
 
                               g_slist_length (list));
765
 
 
766
 
        for (l = list; l != NULL; l = l->next) {
767
 
                g_array_append_val (a, l->data);
768
 
        }
769
 
 
770
 
        return (char **) g_array_free (a, FALSE);
 
537
        }
771
538
}
772
539
 
773
540
/**
785
552
                          GError            **error)
786
553
{
787
554
        NotifyNotificationPrivate *priv;
788
 
        GError                    *tmp_error = NULL;
789
 
        char                     **action_array;
790
 
        DBusGProxy                *proxy;
 
555
        GDBusProxy                *proxy;
 
556
        GVariantBuilder            actions_builder, hints_builder;
 
557
        GSList                    *l;
 
558
        GHashTableIter             iter;
 
559
        gpointer                   key, data;
 
560
        GVariant                  *result;
791
561
 
792
562
        g_return_val_if_fail (notification != NULL, FALSE);
793
563
        g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
794
564
        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
795
565
 
 
566
        if (!notify_is_initted ()) {
 
567
                g_warning ("you must call notify_init() before showing");
 
568
                g_assert_not_reached ();
 
569
        }
 
570
 
796
571
        priv = notification->priv;
797
 
        proxy = _notify_get_g_proxy ();
 
572
        proxy = _notify_get_proxy (error);
798
573
        if (proxy == NULL) {
799
 
                g_set_error (error, 0, 0, "Unable to connect to server");
800
574
                return FALSE;
801
575
        }
802
576
 
803
 
        if (!priv->signals_registered) {
804
 
                g_signal_connect (proxy,
805
 
                                  "destroy",
806
 
                                  G_CALLBACK (on_proxy_destroy),
807
 
                                  notification);
808
 
 
809
 
                dbus_g_proxy_connect_signal (proxy,
810
 
                                             "NotificationClosed",
811
 
                                             G_CALLBACK (_close_signal_handler),
812
 
                                             notification,
813
 
                                             NULL);
814
 
 
815
 
                dbus_g_proxy_connect_signal (proxy,
816
 
                                             "ActionInvoked",
817
 
                                             G_CALLBACK (_action_signal_handler),
818
 
                                             notification,
819
 
                                             NULL);
820
 
 
821
 
                priv->signals_registered = TRUE;
822
 
        }
823
 
 
824
 
        /* If attached to a widget or status icon, modify x and y in hints */
825
 
        _notify_notification_update_applet_hints (notification);
826
 
 
827
 
        action_array = _gslist_to_string_array (priv->actions);
 
577
        if (priv->proxy_signal_handler == 0) {
 
578
                priv->proxy_signal_handler = g_signal_connect (proxy,
 
579
                                                               "g-signal",
 
580
                                                               G_CALLBACK (proxy_g_signal_cb),
 
581
                                                               notification);
 
582
        }
 
583
 
 
584
        g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("as"));
 
585
        for (l = priv->actions; l != NULL; l = l->next) {
 
586
                g_variant_builder_add (&actions_builder, "s", l->data);
 
587
        }
 
588
 
 
589
        g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
 
590
        g_hash_table_iter_init (&iter, priv->hints);
 
591
        while (g_hash_table_iter_next (&iter, &key, &data)) {
 
592
                g_variant_builder_add (&hints_builder, "{sv}", key, data);
 
593
        }
828
594
 
829
595
        /* TODO: make this nonblocking */
830
 
        dbus_g_proxy_call (proxy,
831
 
                           "Notify",
832
 
                           &tmp_error,
833
 
                           G_TYPE_STRING, notify_get_app_name (),
834
 
                           G_TYPE_UINT, priv->id,
835
 
                           G_TYPE_STRING, priv->icon_name,
836
 
                           G_TYPE_STRING, priv->summary,
837
 
                           G_TYPE_STRING, priv->body,
838
 
                           G_TYPE_STRV, action_array,
839
 
                           dbus_g_type_get_map ("GHashTable",
840
 
                                                G_TYPE_STRING,
841
 
                                                G_TYPE_VALUE),
842
 
                           priv->hints,
843
 
                           G_TYPE_INT, priv->timeout,
844
 
                           G_TYPE_INVALID,
845
 
                           G_TYPE_UINT, &priv->id,
846
 
                           G_TYPE_INVALID);
847
 
 
848
 
        /* Don't free the elements because they are owned by priv->actions */
849
 
        g_free (action_array);
850
 
 
851
 
        if (tmp_error != NULL) {
852
 
                g_propagate_error (error, tmp_error);
853
 
                return FALSE;
854
 
        }
 
596
        result = g_dbus_proxy_call_sync (proxy,
 
597
                                         "Notify",
 
598
                                         g_variant_new ("(susssasa{sv}i)",
 
599
                                                        priv->app_name ? priv->app_name : notify_get_app_name (),
 
600
                                                        priv->id,
 
601
                                                        priv->icon_name ? priv->icon_name : "",
 
602
                                                        priv->summary ? priv->summary : "",
 
603
                                                        priv->body ? priv->body : "",
 
604
                                                        &actions_builder,
 
605
                                                        &hints_builder,
 
606
                                                        priv->timeout),
 
607
                                         G_DBUS_CALL_FLAGS_NONE,
 
608
                                         -1 /* FIXME ? */,
 
609
                                         NULL,
 
610
                                         error);
 
611
        if (result == NULL) {
 
612
                return FALSE;
 
613
        }
 
614
        if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(u)"))) {
 
615
                g_variant_unref (result);
 
616
                g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
 
617
                             "Unexpected reply type");
 
618
                return FALSE;
 
619
        }
 
620
 
 
621
        g_variant_get (result, "(u)", &priv->id);
 
622
        g_variant_unref (result);
855
623
 
856
624
        return TRUE;
857
625
}
899
667
        g_return_if_fail (notification != NULL);
900
668
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
901
669
 
902
 
        notify_notification_set_hint_string (notification,
903
 
                                             "category",
904
 
                                             category);
 
670
        if (category != NULL && category[0] != '\0') {
 
671
                notify_notification_set_hint_string (notification,
 
672
                                                     "category",
 
673
                                                     category);
 
674
        }
905
675
}
906
676
 
907
677
/**
925
695
                                           (guchar) urgency);
926
696
}
927
697
 
928
 
static void
929
 
_gvalue_array_append_int (GValueArray *array,
930
 
                          gint         i)
931
 
{
932
 
        GValue value = { 0 };
933
 
 
934
 
        g_value_init (&value, G_TYPE_INT);
935
 
        g_value_set_int (&value, i);
936
 
        g_value_array_append (array, &value);
937
 
        g_value_unset (&value);
938
 
}
939
 
 
940
 
static void
941
 
_gvalue_array_append_bool (GValueArray *array, gboolean b)
942
 
{
943
 
        GValue value = { 0 };
944
 
 
945
 
        g_value_init (&value, G_TYPE_BOOLEAN);
946
 
        g_value_set_boolean (&value, b);
947
 
        g_value_array_append (array, &value);
948
 
        g_value_unset (&value);
949
 
}
950
 
 
951
 
static void
952
 
_gvalue_array_append_byte_array (GValueArray *array,
953
 
                                 guchar      *bytes,
954
 
                                 gsize        len)
955
 
{
956
 
        GArray *byte_array;
957
 
        GValue  value = { 0 };
958
 
 
959
 
        byte_array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
960
 
        g_assert (byte_array != NULL);
961
 
        byte_array = g_array_append_vals (byte_array, bytes, len);
962
 
 
963
 
        g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
964
 
        g_value_take_boxed (&value, byte_array);
965
 
        g_value_array_append (array, &value);
966
 
        g_value_unset (&value);
967
 
}
968
 
 
969
698
/**
970
699
 * notify_notification_set_icon_from_pixbuf:
971
700
 * @notification: The notification.
974
703
 * Sets the icon in the notification from a #GdkPixbuf.
975
704
 * Deprecated: use notify_notification_set_image_from_pixbuf() instead.
976
705
 *
977
 
 * This will only work when libnotify is compiled against D-BUS 0.60 or
978
 
 * higher.
979
706
 */
980
707
void
981
708
notify_notification_set_icon_from_pixbuf (NotifyNotification *notification,
991
718
 *
992
719
 * Sets the image in the notification from a #GdkPixbuf.
993
720
 *
994
 
 * This will only work when libnotify is compiled against D-BUS 0.60 or
995
 
 * higher.
996
721
 */
997
722
void
998
723
notify_notification_set_image_from_pixbuf (NotifyNotification *notification,
1006
731
        guchar         *image;
1007
732
        gboolean        has_alpha;
1008
733
        gsize           image_len;
1009
 
        GValueArray    *image_struct;
1010
 
        GValue         *value;
 
734
        GVariant       *value;
1011
735
        const char     *hint_name;
1012
736
 
1013
 
        g_return_if_fail (notification != NULL);
1014
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
 
737
        g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
 
738
 
 
739
        if (_notify_check_spec_version(1, 2)) {
 
740
                hint_name = "image-data";
 
741
        } else if (_notify_check_spec_version(1, 1)) {
 
742
                hint_name = "image_data";
 
743
        } else {
 
744
                hint_name = "icon_data";
 
745
        }
 
746
 
 
747
        if (pixbuf == NULL) {
 
748
                notify_notification_set_hint (notification, hint_name, NULL);
 
749
                return;
 
750
        }
1015
751
 
1016
752
        g_object_get (pixbuf,
1017
753
                      "width", &width,
1025
761
        image_len = (height - 1) * rowstride + width *
1026
762
                ((n_channels * bits_per_sample + 7) / 8);
1027
763
 
1028
 
        image_struct = g_value_array_new (1);
1029
 
 
1030
 
        _gvalue_array_append_int (image_struct, width);
1031
 
        _gvalue_array_append_int (image_struct, height);
1032
 
        _gvalue_array_append_int (image_struct, rowstride);
1033
 
        _gvalue_array_append_bool (image_struct, has_alpha);
1034
 
        _gvalue_array_append_int (image_struct, bits_per_sample);
1035
 
        _gvalue_array_append_int (image_struct, n_channels);
1036
 
        _gvalue_array_append_byte_array (image_struct, image, image_len);
1037
 
 
1038
 
        value = g_new0 (GValue, 1);
1039
 
        g_value_init (value, G_TYPE_VALUE_ARRAY);
1040
 
        g_value_take_boxed (value, image_struct);
1041
 
 
1042
 
        if (_notify_check_spec_version(1, 1)) {
1043
 
                hint_name = "image_data";
 
764
        value = g_variant_new ("(iiibii@ay)",
 
765
                               width,
 
766
                               height,
 
767
                               rowstride,
 
768
                               has_alpha,
 
769
                               bits_per_sample,
 
770
                               n_channels,
 
771
                               g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
 
772
                                                        image,
 
773
                                                        image_len,
 
774
                                                        TRUE,
 
775
                                                        (GDestroyNotify) g_object_unref,
 
776
                                                        g_object_ref (pixbuf)));
 
777
        notify_notification_set_hint (notification, hint_name, value);
 
778
}
 
779
 
 
780
/**
 
781
 * notify_notification_set_hint:
 
782
 * @notification: a #NotifyNotification
 
783
 * @key: the hint key
 
784
 * @value: (allow-none): the hint value, or %NULL to unset the hint
 
785
 *
 
786
 * Sets a hint for @key with value @value. If @value is %NULL,
 
787
 * a previously set hint for @key is unset.
 
788
 *
 
789
 * If @value is floating, it is consumed.
 
790
 *
 
791
 * Since: 0.6
 
792
 */
 
793
void
 
794
notify_notification_set_hint (NotifyNotification *notification,
 
795
                              const char         *key,
 
796
                              GVariant           *value)
 
797
{
 
798
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
 
799
        g_return_if_fail (key != NULL && *key != '\0');
 
800
 
 
801
        if (value != NULL) {
 
802
                g_hash_table_insert (notification->priv->hints,
 
803
                                    g_strdup (key),
 
804
                                    g_variant_ref_sink (value));
1044
805
        } else {
1045
 
                hint_name = "icon_data";
 
806
                g_hash_table_remove (notification->priv->hints, key);
1046
807
        }
1047
 
 
1048
 
        g_hash_table_insert (notification->priv->hints,
1049
 
                             g_strdup (hint_name),
1050
 
                             value);
 
808
}
 
809
 
 
810
/**
 
811
 * notify_notification_set_app_name:
 
812
 * @notification: a #NotifyNotification
 
813
 * @app_name: the localised application name
 
814
 *
 
815
 * Sets the application name for the notification. If this function is
 
816
 * not called or if @app_name is %NULL, the application name will be
 
817
 * set from the value used in notify_init() or overridden with
 
818
 * notify_set_app_name().
 
819
 *
 
820
 * Since: 0.7.3
 
821
 */
 
822
void
 
823
notify_notification_set_app_name (NotifyNotification *notification,
 
824
                                  const char         *app_name)
 
825
{
 
826
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
 
827
 
 
828
        g_free (notification->priv->app_name);
 
829
        notification->priv->app_name = g_strdup (app_name);
 
830
 
 
831
        g_object_notify (G_OBJECT (notification), "app-name");
1051
832
}
1052
833
 
1053
834
/**
1057
838
 * @value: The hint's value.
1058
839
 *
1059
840
 * Sets a hint with a 32-bit integer value.
 
841
 *
 
842
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1060
843
 */
1061
844
void
1062
845
notify_notification_set_hint_int32 (NotifyNotification *notification,
1063
846
                                    const char         *key,
1064
847
                                    gint                value)
1065
848
{
1066
 
        GValue *hint_value;
1067
 
 
1068
 
        g_return_if_fail (notification != NULL);
1069
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1070
 
        g_return_if_fail (key != NULL && *key != '\0');
1071
 
 
1072
 
        hint_value = g_new0 (GValue, 1);
1073
 
        g_value_init (hint_value, G_TYPE_INT);
1074
 
        g_value_set_int (hint_value, value);
1075
 
        g_hash_table_insert (notification->priv->hints,
1076
 
                             g_strdup (key),
1077
 
                             hint_value);
 
849
        notify_notification_set_hint (notification, key,
 
850
                                      g_variant_new_int32 (value));
1078
851
}
1079
852
 
1080
853
 
1085
858
 * @value: The hint's value.
1086
859
 *
1087
860
 * Sets a hint with an unsigned 32-bit integer value.
 
861
 *
 
862
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1088
863
 */
1089
864
void
1090
865
notify_notification_set_hint_uint32 (NotifyNotification *notification,
1091
866
                                     const char         *key,
1092
867
                                     guint               value)
1093
868
{
1094
 
        GValue *hint_value;
1095
 
 
1096
 
        g_return_if_fail (notification != NULL);
1097
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1098
 
        g_return_if_fail (key != NULL && *key != '\0');
1099
 
 
1100
 
        hint_value = g_new0 (GValue, 1);
1101
 
        g_value_init (hint_value, G_TYPE_UINT);
1102
 
        g_value_set_uint (hint_value, value);
1103
 
        g_hash_table_insert (notification->priv->hints,
1104
 
                             g_strdup (key),
1105
 
                             hint_value);
 
869
        notify_notification_set_hint (notification, key,
 
870
                                      g_variant_new_uint32 (value));
1106
871
}
1107
872
 
1108
873
/**
1112
877
 * @value: The hint's value.
1113
878
 *
1114
879
 * Sets a hint with a double value.
 
880
 *
 
881
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1115
882
 */
1116
883
void
1117
884
notify_notification_set_hint_double (NotifyNotification *notification,
1118
885
                                     const char         *key,
1119
886
                                     gdouble             value)
1120
887
{
1121
 
        GValue *hint_value;
1122
 
 
1123
 
        g_return_if_fail (notification != NULL);
1124
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1125
 
        g_return_if_fail (key != NULL && *key != '\0');
1126
 
 
1127
 
        hint_value = g_new0 (GValue, 1);
1128
 
        g_value_init (hint_value, G_TYPE_FLOAT);
1129
 
        g_value_set_float (hint_value, value);
1130
 
        g_hash_table_insert (notification->priv->hints,
1131
 
                             g_strdup (key),
1132
 
                             hint_value);
 
888
        notify_notification_set_hint (notification, key,
 
889
                                      g_variant_new_double (value));
1133
890
}
1134
891
 
1135
892
/**
1139
896
 * @value: The hint's value.
1140
897
 *
1141
898
 * Sets a hint with a byte value.
 
899
 *
 
900
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1142
901
 */
1143
902
void
1144
903
notify_notification_set_hint_byte (NotifyNotification *notification,
1145
904
                                   const char         *key,
1146
905
                                   guchar              value)
1147
906
{
1148
 
        GValue *hint_value;
1149
 
 
1150
 
        g_return_if_fail (notification != NULL);
1151
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1152
 
        g_return_if_fail (key != NULL && *key != '\0');
1153
 
 
1154
 
        hint_value = g_new0 (GValue, 1);
1155
 
        g_value_init (hint_value, G_TYPE_UCHAR);
1156
 
        g_value_set_uchar (hint_value, value);
1157
 
 
1158
 
        g_hash_table_insert (notification->priv->hints,
1159
 
                             g_strdup (key),
1160
 
                             hint_value);
 
907
        notify_notification_set_hint (notification, key,
 
908
                                      g_variant_new_byte (value));
1161
909
}
1162
910
 
1163
911
/**
1169
917
 *
1170
918
 * Sets a hint with a byte array value. The length of @value must be passed
1171
919
 * as @len.
 
920
 *
 
921
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1172
922
 */
1173
923
void
1174
924
notify_notification_set_hint_byte_array (NotifyNotification *notification,
1176
926
                                         const guchar       *value,
1177
927
                                         gsize               len)
1178
928
{
1179
 
        GValue *hint_value;
1180
 
        GArray *byte_array;
1181
 
 
1182
 
        g_return_if_fail (notification != NULL);
1183
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1184
 
        g_return_if_fail (key != NULL && *key != '\0');
1185
 
        g_return_if_fail (value != NULL);
1186
 
        g_return_if_fail (len > 0);
1187
 
 
1188
 
        byte_array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), len);
1189
 
        byte_array = g_array_append_vals (byte_array, value, len);
1190
 
 
1191
 
        hint_value = g_new0 (GValue, 1);
1192
 
        g_value_init (hint_value, dbus_g_type_get_collection ("GArray",
1193
 
                                                              G_TYPE_UCHAR));
1194
 
        g_value_take_boxed (hint_value, byte_array);
1195
 
 
1196
 
        g_hash_table_insert (notification->priv->hints,
1197
 
                             g_strdup (key),
1198
 
                             hint_value);
 
929
        gpointer value_dup;
 
930
 
 
931
        g_return_if_fail (value != NULL || len == 0);
 
932
 
 
933
        value_dup = g_memdup (value, len);
 
934
        notify_notification_set_hint (notification, key,
 
935
                                      g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
 
936
                                                               value_dup,
 
937
                                                               len,
 
938
                                                               TRUE,
 
939
                                                               g_free,
 
940
                                                               value_dup));
1199
941
}
1200
942
 
1201
943
/**
1205
947
 * @value: The hint's value.
1206
948
 *
1207
949
 * Sets a hint with a string value.
 
950
 *
 
951
 * Deprecated: 0.6. Use notify_notification_set_hint() instead
1208
952
 */
1209
953
void
1210
954
notify_notification_set_hint_string (NotifyNotification *notification,
1211
955
                                     const char         *key,
1212
956
                                     const char         *value)
1213
957
{
1214
 
        GValue *hint_value;
1215
 
 
1216
 
        g_return_if_fail (notification != NULL);
1217
 
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1218
 
        g_return_if_fail (key != NULL && *key != '\0');
1219
 
 
1220
 
        hint_value = g_new0 (GValue, 1);
1221
 
        g_value_init (hint_value, G_TYPE_STRING);
1222
 
        g_value_set_string (hint_value, value);
1223
 
        g_hash_table_insert (notification->priv->hints,
1224
 
                             g_strdup (key),
1225
 
                             hint_value);
 
958
        if (value != NULL && value[0] != '\0') {
 
959
                notify_notification_set_hint (notification,
 
960
                                              key,
 
961
                                              g_variant_new_string (value));
 
962
        }
1226
963
}
1227
964
 
1228
965
static gboolean
1280
1017
 * @notification: The notification.
1281
1018
 * @action: The action ID.
1282
1019
 * @label: The human-readable action label.
1283
 
 * @callback: The action's callback function.
1284
 
 * @user_data: Optional custom data to pass to @callback.
1285
 
 * @free_func: An optional function to free @user_data when the notification
 
1020
 * @callback: (scope async): The action's callback function.
 
1021
 * @user_data: (allow-none): Optional custom data to pass to @callback.
 
1022
 * @free_func: (scope async) (allow-none): An optional function to free @user_data when the notification
1286
1023
 *             is destroyed.
1287
1024
 *
1288
1025
 * Adds an action to a notification. When the action is invoked, the
1300
1037
        NotifyNotificationPrivate *priv;
1301
1038
        CallbackPair              *pair;
1302
1039
 
1303
 
        g_return_if_fail (notification != NULL);
1304
1040
        g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
1305
1041
        g_return_if_fail (action != NULL && *action != '\0');
1306
1042
        g_return_if_fail (label != NULL && *label != '\0');
1337
1073
 * @notification: The notification.
1338
1074
 * @error: The returned error information.
1339
1075
 *
1340
 
 * Tells the notification server to hide the notification on the screen.
 
1076
 * Synchronously tells the notification server to hide the notification on the screen.
1341
1077
 *
1342
 
 * Returns: %TRUE if successful. On error, this will return %FALSE and set
1343
 
 *          @error.
 
1078
 * Returns: %TRUE on success, or %FALSE on error with @error filled in
1344
1079
 */
1345
1080
gboolean
1346
1081
notify_notification_close (NotifyNotification *notification,
1347
1082
                           GError            **error)
1348
1083
{
1349
1084
        NotifyNotificationPrivate *priv;
1350
 
        GError         *tmp_error = NULL;
1351
 
        DBusGProxy     *proxy;
 
1085
        GDBusProxy  *proxy;
 
1086
        GVariant   *result;
1352
1087
 
1353
 
        g_return_val_if_fail (notification != NULL, FALSE);
1354
1088
        g_return_val_if_fail (NOTIFY_IS_NOTIFICATION (notification), FALSE);
1355
1089
        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1356
1090
 
1357
1091
        priv = notification->priv;
1358
1092
 
1359
 
        proxy = _notify_get_g_proxy ();
 
1093
        proxy = _notify_get_proxy (error);
1360
1094
        if (proxy == NULL) {
1361
 
                g_set_error (error, 0, 0, "Unable to connect to server");
1362
 
                return FALSE;
1363
 
        }
1364
 
 
1365
 
        dbus_g_proxy_call (proxy,
1366
 
                           "CloseNotification",
1367
 
                           &tmp_error,
1368
 
                           G_TYPE_UINT,
1369
 
                           priv->id,
1370
 
                           G_TYPE_INVALID,
1371
 
                           G_TYPE_INVALID);
1372
 
 
1373
 
        if (tmp_error != NULL) {
1374
 
                g_propagate_error (error, tmp_error);
1375
 
                return FALSE;
1376
 
        }
 
1095
                return FALSE;
 
1096
        }
 
1097
 
 
1098
        /* FIXME: make this nonblocking! */
 
1099
        result = g_dbus_proxy_call_sync (proxy,
 
1100
                                         "CloseNotification",
 
1101
                                         g_variant_new ("(u)", priv->id),
 
1102
                                         G_DBUS_CALL_FLAGS_NONE,
 
1103
                                         -1 /* FIXME! */,
 
1104
                                         NULL,
 
1105
                                         error);
 
1106
        if (result == NULL) {
 
1107
                return FALSE;
 
1108
        }
 
1109
 
 
1110
        g_variant_unref (result);
1377
1111
 
1378
1112
        return TRUE;
1379
1113
}