267
262
priv->id = g_value_get_int (value);
266
notify_notification_update_internal (notification,
267
g_value_get_string (value),
270
273
case PROP_SUMMARY:
271
notify_notification_update (notification,
272
g_value_get_string (value),
274
notify_notification_update_internal (notification,
276
g_value_get_string (value),
278
notify_notification_update (notification,
280
g_value_get_string (value),
282
notify_notification_update_internal (notification,
285
g_value_get_string (value),
284
289
case PROP_ICON_NAME:
285
notify_notification_update (notification,
288
g_value_get_string (value));
291
case PROP_ATTACH_WIDGET:
292
notify_notification_attach_to_widget (notification,
293
g_value_get_object (value));
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,
294
g_value_get_string (value));
451
402
G_OBJECT_CLASS (parent_class)->finalize (object);
455
_notify_notification_update_applet_hints (NotifyNotification *n)
457
NotifyNotificationPrivate *priv = n->priv;
458
GdkScreen *screen = NULL;
461
if (priv->status_icon != NULL) {
465
xid = gtk_status_icon_get_x11_window_id (priv->status_icon);
467
notify_notification_set_hint_uint32 (n, "window-xid", xid);
470
if (!gtk_status_icon_get_geometry (priv->status_icon,
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;
483
screen = gtk_widget_get_screen (widget);
485
gdk_window_get_origin (gtk_widget_get_window (widget), &x, &y);
486
gtk_widget_get_allocation (widget, &allocation);
488
if (!gtk_widget_get_has_window (widget)) {
493
x += allocation.width / 2;
494
y += allocation.height / 2;
499
notify_notification_set_geometry_hints (n, screen, x, y);
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.
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,
520
g_return_val_if_fail (attach == NULL || GTK_IS_WIDGET (attach), NULL);
522
421
return g_object_new (NOTIFY_TYPE_NOTIFICATION,
523
422
"summary", summary,
525
424
"icon-name", icon,
526
"attach-widget", attach,
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.
537
* Creates a new #NotifyNotification and attaches to a #GtkStatusIcon.
538
* The summary text and @status_icon is required, but all other parameters
541
* Returns: The new #NotifyNotification.
546
notify_notification_new_with_status_icon (const char *summary,
549
GtkStatusIcon *status_icon)
551
g_return_val_if_fail (status_icon != NULL, NULL);
552
g_return_val_if_fail (GTK_IS_STATUS_ICON (status_icon), NULL);
554
return g_object_new (NOTIFY_TYPE_NOTIFICATION,
558
"status-icon", status_icon,
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.
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().
573
* Returns: %TRUE, unless an invalid parameter was passed.
576
notify_notification_update (NotifyNotification *notification,
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);
429
notify_notification_update_internal (NotifyNotification *notification,
430
const char *app_name,
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");
585
441
if (notification->priv->summary != summary) {
586
442
g_free (notification->priv->summary);
605
461
notification->priv->updates_pending = TRUE;
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.
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().
475
* Returns: %TRUE, unless an invalid parameter was passed.
478
notify_notification_update (NotifyNotification *notification,
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);
487
notify_notification_update_internal (notification,
488
notification->priv->app_name,
489
summary, body, icon);
611
* notify_notification_attach_to_widget:
612
* @notification: The notification.
613
* @attach: The widget to attach to, or %NULL.
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.
620
notify_notification_attach_to_widget (NotifyNotification *notification,
623
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
625
if (notification->priv->attached_widget == attach)
628
if (notification->priv->attached_widget != NULL)
629
g_object_unref (notification->priv->attached_widget);
631
notification->priv->attached_widget =
632
(attach != NULL ? g_object_ref (attach) : NULL);
634
g_object_notify (G_OBJECT (notification), "attach-widget");
638
* notify_notification_attach_to_status_icon:
639
* @notification: The notification.
640
* @status_icon: The #GtkStatusIcon to attach to, or %NULL.
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.
649
notify_notification_attach_to_status_icon (NotifyNotification *notification,
650
GtkStatusIcon *status_icon)
652
NotifyNotificationPrivate *priv;
654
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
655
g_return_if_fail (status_icon == NULL
656
|| GTK_IS_STATUS_ICON (status_icon));
658
priv = notification->priv;
660
if (priv->status_icon == status_icon)
663
if (priv->status_icon != NULL) {
664
g_object_remove_weak_pointer (G_OBJECT (priv->status_icon),
665
(gpointer) & priv->status_icon);
668
priv->status_icon = status_icon;
670
if (priv->status_icon != NULL) {
671
g_object_add_weak_pointer (G_OBJECT (priv->status_icon),
672
(gpointer) & priv->status_icon);
675
g_object_notify (G_OBJECT (notification), "status-icon");
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.
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.
692
notify_notification_set_geometry_hints (NotifyNotification *notification,
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));
704
notify_notification_set_hint_int32 (notification, "x", x);
705
notify_notification_set_hint_int32 (notification, "y", y);
707
display_name = gdk_screen_make_display_name (screen);
708
notify_notification_set_hint_string (notification,
711
g_free (display_name);
715
_close_signal_handler (DBusGProxy *proxy,
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)
720
if (id == notification->priv->id) {
501
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
503
if (g_strcmp0 (signal_name, "NotificationClosed") == 0 &&
504
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) {
507
g_variant_get (parameters, "(uu)", &id, &reason);
508
if (id != notification->priv->id)
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));
730
_action_signal_handler (DBusGProxy *proxy,
733
NotifyNotification *notification)
737
g_return_if_fail (notification != NULL);
738
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
740
if (id != notification->priv->id)
743
pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map,
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)"))) {
522
g_variant_get (parameters, "(u&s)", &id, &action);
524
if (id != notification->priv->id)
527
pair = (CallbackPair *) g_hash_table_lookup (notification->priv->action_map,
531
if (g_ascii_strcasecmp (action, "default")) {
532
g_warning ("Received unknown action %s", action);
535
pair->cb (notification, (char *) action, pair->user_data);
751
pair->cb (notification, action, pair->user_data);
756
_gslist_to_string_array (GSList *list)
761
a = g_array_sized_new (TRUE,
764
g_slist_length (list));
766
for (l = list; l != NULL; l = l->next) {
767
g_array_append_val (a, l->data);
770
return (char **) g_array_free (a, FALSE);
787
554
NotifyNotificationPrivate *priv;
788
GError *tmp_error = NULL;
556
GVariantBuilder actions_builder, hints_builder;
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);
566
if (!notify_is_initted ()) {
567
g_warning ("you must call notify_init() before showing");
568
g_assert_not_reached ();
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");
803
if (!priv->signals_registered) {
804
g_signal_connect (proxy,
806
G_CALLBACK (on_proxy_destroy),
809
dbus_g_proxy_connect_signal (proxy,
810
"NotificationClosed",
811
G_CALLBACK (_close_signal_handler),
815
dbus_g_proxy_connect_signal (proxy,
817
G_CALLBACK (_action_signal_handler),
821
priv->signals_registered = TRUE;
824
/* If attached to a widget or status icon, modify x and y in hints */
825
_notify_notification_update_applet_hints (notification);
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,
580
G_CALLBACK (proxy_g_signal_cb),
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);
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);
829
595
/* TODO: make this nonblocking */
830
dbus_g_proxy_call (proxy,
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",
843
G_TYPE_INT, priv->timeout,
845
G_TYPE_UINT, &priv->id,
848
/* Don't free the elements because they are owned by priv->actions */
849
g_free (action_array);
851
if (tmp_error != NULL) {
852
g_propagate_error (error, tmp_error);
596
result = g_dbus_proxy_call_sync (proxy,
598
g_variant_new ("(susssasa{sv}i)",
599
priv->app_name ? priv->app_name : notify_get_app_name (),
601
priv->icon_name ? priv->icon_name : "",
602
priv->summary ? priv->summary : "",
603
priv->body ? priv->body : "",
607
G_DBUS_CALL_FLAGS_NONE,
611
if (result == NULL) {
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");
621
g_variant_get (result, "(u)", &priv->id);
622
g_variant_unref (result);
925
695
(guchar) urgency);
929
_gvalue_array_append_int (GValueArray *array,
932
GValue value = { 0 };
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);
941
_gvalue_array_append_bool (GValueArray *array, gboolean b)
943
GValue value = { 0 };
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);
952
_gvalue_array_append_byte_array (GValueArray *array,
957
GValue value = { 0 };
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);
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);
970
699
* notify_notification_set_icon_from_pixbuf:
971
700
* @notification: The notification.
1025
761
image_len = (height - 1) * rowstride + width *
1026
762
((n_channels * bits_per_sample + 7) / 8);
1028
image_struct = g_value_array_new (1);
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);
1038
value = g_new0 (GValue, 1);
1039
g_value_init (value, G_TYPE_VALUE_ARRAY);
1040
g_value_take_boxed (value, image_struct);
1042
if (_notify_check_spec_version(1, 1)) {
1043
hint_name = "image_data";
764
value = g_variant_new ("(iiibii@ay)",
771
g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
775
(GDestroyNotify) g_object_unref,
776
g_object_ref (pixbuf)));
777
notify_notification_set_hint (notification, hint_name, value);
781
* notify_notification_set_hint:
782
* @notification: a #NotifyNotification
784
* @value: (allow-none): the hint value, or %NULL to unset the hint
786
* Sets a hint for @key with value @value. If @value is %NULL,
787
* a previously set hint for @key is unset.
789
* If @value is floating, it is consumed.
794
notify_notification_set_hint (NotifyNotification *notification,
798
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
799
g_return_if_fail (key != NULL && *key != '\0');
802
g_hash_table_insert (notification->priv->hints,
804
g_variant_ref_sink (value));
1045
hint_name = "icon_data";
806
g_hash_table_remove (notification->priv->hints, key);
1048
g_hash_table_insert (notification->priv->hints,
1049
g_strdup (hint_name),
811
* notify_notification_set_app_name:
812
* @notification: a #NotifyNotification
813
* @app_name: the localised application name
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().
823
notify_notification_set_app_name (NotifyNotification *notification,
824
const char *app_name)
826
g_return_if_fail (NOTIFY_IS_NOTIFICATION (notification));
828
g_free (notification->priv->app_name);
829
notification->priv->app_name = g_strdup (app_name);
831
g_object_notify (G_OBJECT (notification), "app-name");
1337
1073
* @notification: The notification.
1338
1074
* @error: The returned error information.
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.
1342
* Returns: %TRUE if successful. On error, this will return %FALSE and set
1078
* Returns: %TRUE on success, or %FALSE on error with @error filled in
1346
1081
notify_notification_close (NotifyNotification *notification,
1347
1082
GError **error)
1349
1084
NotifyNotificationPrivate *priv;
1350
GError *tmp_error = NULL;
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);
1357
1091
priv = notification->priv;
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");
1365
dbus_g_proxy_call (proxy,
1366
"CloseNotification",
1373
if (tmp_error != NULL) {
1374
g_propagate_error (error, tmp_error);
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,
1106
if (result == NULL) {
1110
g_variant_unref (result);