2 * Copyright © 2013 Lars Uebernickel
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Authors: Lars Uebernickel <lars@uebernic.de>
22 #include "gnotification-private.h"
23 #include "gdbusutils.h"
26 #include "gioenumtypes.h"
29 * SECTION:gnotification
30 * @short_description: User Notifications (pop up messages)
33 * #GNotification is a mechanism for creating a notification to be shown
34 * to the user -- typically as a pop-up notification presented by the
35 * desktop environment shell.
37 * The key difference between #GNotification and other similar APIs is
38 * that, if supported by the desktop environment, notifications sent
39 * with #GNotification will persist after the application has exited,
40 * and even across system reboots.
42 * Since the user may click on a notification while the application is
43 * not running, applications using #GNotification should be able to be
44 * started as a D-Bus service, using #GApplication.
46 * User interaction with a notification (either the default action, or
47 * buttons) must be associated with actions on the application (ie:
48 * "app." actions). It is not possible to route user interaction
49 * through the notification itself, because the object will not exist if
50 * the application is autostarted as a result of a notification being
53 * A notification can be sent with g_application_send_notification().
61 * This structure type is private and should only be accessed using the
67 typedef GObjectClass GNotificationClass
;
76 GNotificationPriority priority
;
78 gchar
*default_action
;
79 GVariant
*default_action_target
;
89 G_DEFINE_TYPE (GNotification
, g_notification
, G_TYPE_OBJECT
)
92 button_free (gpointer data
)
94 Button
*button
= data
;
96 g_free (button
->label
);
97 g_free (button
->action_name
);
99 g_variant_unref (button
->target
);
101 g_slice_free (Button
, button
);
105 g_notification_dispose (GObject
*object
)
107 GNotification
*notification
= G_NOTIFICATION (object
);
109 g_clear_object (¬ification
->icon
);
111 G_OBJECT_CLASS (g_notification_parent_class
)->dispose (object
);
115 g_notification_finalize (GObject
*object
)
117 GNotification
*notification
= G_NOTIFICATION (object
);
119 g_free (notification
->title
);
120 g_free (notification
->body
);
121 g_free (notification
->default_action
);
122 if (notification
->default_action_target
)
123 g_variant_unref (notification
->default_action_target
);
124 g_ptr_array_free (notification
->buttons
, TRUE
);
126 G_OBJECT_CLASS (g_notification_parent_class
)->finalize (object
);
130 g_notification_class_init (GNotificationClass
*klass
)
132 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
134 object_class
->dispose
= g_notification_dispose
;
135 object_class
->finalize
= g_notification_finalize
;
139 g_notification_init (GNotification
*notification
)
141 notification
->buttons
= g_ptr_array_new_full (2, button_free
);
145 * g_notification_new:
146 * @title: the title of the notification
148 * Creates a new #GNotification with @title as its title.
150 * After populating @notification with more details, it can be sent to
151 * the desktop shell with g_application_send_notification(). Changing
152 * any properties after this call will not have any effect until
153 * resending @notification.
155 * Returns: a new #GNotification instance
160 g_notification_new (const gchar
*title
)
162 GNotification
*notification
;
164 g_return_val_if_fail (title
!= NULL
, NULL
);
166 notification
= g_object_new (G_TYPE_NOTIFICATION
, NULL
);
167 notification
->title
= g_strdup (title
);
173 * g_notification_get_title:
174 * @notification: a #GNotification
176 * Gets the title of @notification.
178 * Returns: the title of @notification
183 g_notification_get_title (GNotification
*notification
)
185 g_return_val_if_fail (G_IS_NOTIFICATION (notification
), NULL
);
187 return notification
->title
;
191 * g_notification_set_title:
192 * @notification: a #GNotification
193 * @title: the new title for @notification
195 * Sets the title of @notification to @title.
200 g_notification_set_title (GNotification
*notification
,
203 g_return_if_fail (G_IS_NOTIFICATION (notification
));
204 g_return_if_fail (title
!= NULL
);
206 g_free (notification
->title
);
208 notification
->title
= g_strdup (title
);
212 * g_notification_get_body:
213 * @notification: a #GNotification
215 * Gets the current body of @notification.
217 * Returns: (nullable): the body of @notification
222 g_notification_get_body (GNotification
*notification
)
224 g_return_val_if_fail (G_IS_NOTIFICATION (notification
), NULL
);
226 return notification
->body
;
230 * g_notification_set_body:
231 * @notification: a #GNotification
232 * @body: (nullable): the new body for @notification, or %NULL
234 * Sets the body of @notification to @body.
239 g_notification_set_body (GNotification
*notification
,
242 g_return_if_fail (G_IS_NOTIFICATION (notification
));
243 g_return_if_fail (body
!= NULL
);
245 g_free (notification
->body
);
247 notification
->body
= g_strdup (body
);
251 * g_notification_get_icon:
252 * @notification: a #GNotification
254 * Gets the icon currently set on @notification.
256 * Returns: (transfer none): the icon associated with @notification
261 g_notification_get_icon (GNotification
*notification
)
263 g_return_val_if_fail (G_IS_NOTIFICATION (notification
), NULL
);
265 return notification
->icon
;
269 * g_notification_set_icon:
270 * @notification: a #GNotification
271 * @icon: the icon to be shown in @notification, as a #GIcon
273 * Sets the icon of @notification to @icon.
278 g_notification_set_icon (GNotification
*notification
,
281 g_return_if_fail (G_IS_NOTIFICATION (notification
));
283 if (notification
->icon
)
284 g_object_unref (notification
->icon
);
286 notification
->icon
= g_object_ref (icon
);
290 * g_notification_get_priority:
291 * @notification: a #GNotification
293 * Returns the priority of @notification
297 GNotificationPriority
298 g_notification_get_priority (GNotification
*notification
)
300 g_return_val_if_fail (G_IS_NOTIFICATION (notification
), G_NOTIFICATION_PRIORITY_NORMAL
);
302 return notification
->priority
;
306 * g_notification_set_urgent:
307 * @notification: a #GNotification
308 * @urgent: %TRUE if @notification is urgent
310 * Deprecated in favor of g_notification_set_priority().
313 * Deprecated: 2.42: Since 2.42, this has been deprecated in favour of
314 * g_notification_set_priority().
317 g_notification_set_urgent (GNotification
*notification
,
320 g_return_if_fail (G_IS_NOTIFICATION (notification
));
322 notification
->priority
= urgent
?
323 G_NOTIFICATION_PRIORITY_URGENT
:
324 G_NOTIFICATION_PRIORITY_NORMAL
;
328 * g_notification_set_priority:
329 * @notification: a #GNotification
330 * @priority: a #GNotificationPriority
332 * Sets the priority of @notification to @priority. See
333 * #GNotificationPriority for possible values.
336 g_notification_set_priority (GNotification
*notification
,
337 GNotificationPriority priority
)
339 g_return_if_fail (G_IS_NOTIFICATION (notification
));
341 notification
->priority
= priority
;
345 * g_notification_add_button:
346 * @notification: a #GNotification
347 * @label: label of the button
348 * @detailed_action: a detailed action name
350 * Adds a button to @notification that activates the action in
351 * @detailed_action when clicked. That action must be an
352 * application-wide action (starting with "app."). If @detailed_action
353 * contains a target, the action will be activated with that target as
356 * See g_action_parse_detailed_name() for a description of the format
357 * for @detailed_action.
362 g_notification_add_button (GNotification
*notification
,
364 const gchar
*detailed_action
)
368 GError
*error
= NULL
;
370 g_return_if_fail (detailed_action
!= NULL
);
372 if (!g_action_parse_detailed_name (detailed_action
, &action
, &target
, &error
))
374 g_warning ("%s: %s", G_STRFUNC
, error
->message
);
375 g_error_free (error
);
379 g_notification_add_button_with_target_value (notification
, label
, action
, target
);
383 g_variant_unref (target
);
387 * g_notification_add_button_with_target: (skip)
388 * @notification: a #GNotification
389 * @label: label of the button
390 * @action: an action name
391 * @target_format: (nullable): a #GVariant format string, or %NULL
392 * @...: positional parameters, as determined by @target_format
394 * Adds a button to @notification that activates @action when clicked.
395 * @action must be an application-wide action (it must start with "app.").
397 * If @target_format is given, it is used to collect remaining
398 * positional parameters into a #GVariant instance, similar to
399 * g_variant_new(). @action will be activated with that #GVariant as its
405 g_notification_add_button_with_target (GNotification
*notification
,
408 const gchar
*target_format
,
412 GVariant
*target
= NULL
;
416 va_start (args
, target_format
);
417 target
= g_variant_new_va (target_format
, NULL
, &args
);
421 g_notification_add_button_with_target_value (notification
, label
, action
, target
);
425 * g_notification_add_button_with_target_value: (rename-to g_notification_add_button_with_target)
426 * @notification: a #GNotification
427 * @label: label of the button
428 * @action: an action name
429 * @target: (nullable): a #GVariant to use as @action's parameter, or %NULL
431 * Adds a button to @notification that activates @action when clicked.
432 * @action must be an application-wide action (it must start with "app.").
434 * If @target is non-%NULL, @action will be activated with @target as
440 g_notification_add_button_with_target_value (GNotification
*notification
,
447 g_return_if_fail (G_IS_NOTIFICATION (notification
));
448 g_return_if_fail (label
!= NULL
);
449 g_return_if_fail (action
!= NULL
&& g_action_name_is_valid (action
));
451 if (!g_str_has_prefix (action
, "app."))
453 g_warning ("%s: action '%s' does not start with 'app.'."
454 "This is unlikely to work properly.", G_STRFUNC
, action
);
457 button
= g_slice_new0 (Button
);
458 button
->label
= g_strdup (label
);
459 button
->action_name
= g_strdup (action
);
462 button
->target
= g_variant_ref_sink (target
);
464 g_ptr_array_add (notification
->buttons
, button
);
468 * g_notification_get_n_buttons:
469 * @notification: a #GNotification
471 * Returns: the amount of buttons added to @notification.
474 g_notification_get_n_buttons (GNotification
*notification
)
476 return notification
->buttons
->len
;
480 * g_notification_get_button:
481 * @notification: a #GNotification
482 * @index: index of the button
483 * @label: (): return location for the button's label
484 * @action: (): return location for the button's associated action
485 * @target: (): return location for the target @action should be
488 * Returns a description of a button that was added to @notification
489 * with g_notification_add_button().
491 * @index must be smaller than the value returned by
492 * g_notification_get_n_buttons().
495 g_notification_get_button (GNotification
*notification
,
503 button
= g_ptr_array_index (notification
->buttons
, index
);
506 *label
= g_strdup (button
->label
);
509 *action
= g_strdup (button
->action_name
);
512 *target
= button
->target
? g_variant_ref (button
->target
) : NULL
;
516 * g_notification_get_button_with_action:
517 * @notification: a #GNotification
518 * @action: an action name
520 * Returns the index of the button in @notification that is associated
521 * with @action, or -1 if no such button exists.
524 g_notification_get_button_with_action (GNotification
*notification
,
529 for (i
= 0; i
< notification
->buttons
->len
; i
++)
533 button
= g_ptr_array_index (notification
->buttons
, i
);
534 if (g_str_equal (action
, button
->action_name
))
543 * g_notification_get_default_action:
544 * @notification: a #GNotification
545 * @action: (nullable): return location for the default action
546 * @target: (nullable): return location for the target of the default action
548 * Gets the action and target for the default action of @notification.
550 * Returns: %TRUE if @notification has a default action
553 g_notification_get_default_action (GNotification
*notification
,
557 if (notification
->default_action
== NULL
)
561 *action
= g_strdup (notification
->default_action
);
565 if (notification
->default_action_target
)
566 *target
= g_variant_ref (notification
->default_action_target
);
575 * g_notification_set_default_action:
576 * @notification: a #GNotification
577 * @detailed_action: a detailed action name
579 * Sets the default action of @notification to @detailed_action. This
580 * action is activated when the notification is clicked on.
582 * The action in @detailed_action must be an application-wide action (it
583 * must start with "app."). If @detailed_action contains a target, the
584 * given action will be activated with that target as its parameter.
585 * See g_action_parse_detailed_name() for a description of the format
586 * for @detailed_action.
588 * When no default action is set, the application that the notification
589 * was sent on is activated.
594 g_notification_set_default_action (GNotification
*notification
,
595 const gchar
*detailed_action
)
599 GError
*error
= NULL
;
601 if (!g_action_parse_detailed_name (detailed_action
, &action
, &target
, &error
))
603 g_warning ("%s: %s", G_STRFUNC
, error
->message
);
604 g_error_free (error
);
608 g_notification_set_default_action_and_target_value (notification
, action
, target
);
612 g_variant_unref (target
);
616 * g_notification_set_default_action_and_target: (skip)
617 * @notification: a #GNotification
618 * @action: an action name
619 * @target_format: (nullable): a #GVariant format string, or %NULL
620 * @...: positional parameters, as determined by @target_format
622 * Sets the default action of @notification to @action. This action is
623 * activated when the notification is clicked on. It must be an
624 * application-wide action (it must start with "app.").
626 * If @target_format is given, it is used to collect remaining
627 * positional parameters into a #GVariant instance, similar to
628 * g_variant_new(). @action will be activated with that #GVariant as its
631 * When no default action is set, the application that the notification
632 * was sent on is activated.
637 g_notification_set_default_action_and_target (GNotification
*notification
,
639 const gchar
*target_format
,
643 GVariant
*target
= NULL
;
647 va_start (args
, target_format
);
648 target
= g_variant_new_va (target_format
, NULL
, &args
);
652 g_notification_set_default_action_and_target_value (notification
, action
, target
);
656 * g_notification_set_default_action_and_target_value: (rename-to g_notification_set_default_action_and_target)
657 * @notification: a #GNotification
658 * @action: an action name
659 * @target: (nullable): a #GVariant to use as @action's parameter, or %NULL
661 * Sets the default action of @notification to @action. This action is
662 * activated when the notification is clicked on. It must be an
663 * application-wide action (start with "app.").
665 * If @target is non-%NULL, @action will be activated with @target as
668 * When no default action is set, the application that the notification
669 * was sent on is activated.
674 g_notification_set_default_action_and_target_value (GNotification
*notification
,
678 g_return_if_fail (G_IS_NOTIFICATION (notification
));
679 g_return_if_fail (action
!= NULL
&& g_action_name_is_valid (action
));
681 if (!g_str_has_prefix (action
, "app."))
683 g_warning ("%s: action '%s' does not start with 'app.'."
684 "This is unlikely to work properly.", G_STRFUNC
, action
);
687 g_free (notification
->default_action
);
688 g_clear_pointer (¬ification
->default_action_target
, g_variant_unref
);
690 notification
->default_action
= g_strdup (action
);
693 notification
->default_action_target
= g_variant_ref_sink (target
);
697 g_notification_serialize_button (Button
*button
)
699 GVariantBuilder builder
;
701 g_variant_builder_init (&builder
, G_VARIANT_TYPE ("a{sv}"));
703 g_variant_builder_add (&builder
, "{sv}", "label", g_variant_new_string (button
->label
));
704 g_variant_builder_add (&builder
, "{sv}", "action", g_variant_new_string (button
->action_name
));
707 g_variant_builder_add (&builder
, "{sv}", "target", button
->target
);
709 return g_variant_builder_end (&builder
);
713 g_notification_get_priority_nick (GNotification
*notification
)
715 GEnumClass
*enum_class
;
719 enum_class
= g_type_class_ref (G_TYPE_NOTIFICATION_PRIORITY
);
720 value
= g_enum_get_value (enum_class
, g_notification_get_priority (notification
));
721 g_assert (value
!= NULL
);
722 nick
= g_variant_new_string (value
->value_nick
);
723 g_type_class_unref (enum_class
);
729 * g_notification_serialize:
731 * Serializes @notification into an floating variant of type a{sv}.
733 * Returns: the serialized @notification as a floating variant.
736 g_notification_serialize (GNotification
*notification
)
738 GVariantBuilder builder
;
740 g_variant_builder_init (&builder
, G_VARIANT_TYPE ("a{sv}"));
742 if (notification
->title
)
743 g_variant_builder_add (&builder
, "{sv}", "title", g_variant_new_string (notification
->title
));
745 if (notification
->body
)
746 g_variant_builder_add (&builder
, "{sv}", "body", g_variant_new_string (notification
->body
));
748 if (notification
->icon
)
750 GVariant
*serialized_icon
;
752 if ((serialized_icon
= g_icon_serialize (notification
->icon
)))
754 g_variant_builder_add (&builder
, "{sv}", "icon", serialized_icon
);
755 g_variant_unref (serialized_icon
);
759 g_variant_builder_add (&builder
, "{sv}", "priority", g_notification_get_priority_nick (notification
));
761 if (notification
->default_action
)
763 g_variant_builder_add (&builder
, "{sv}", "default-action",
764 g_variant_new_string (notification
->default_action
));
766 if (notification
->default_action_target
)
767 g_variant_builder_add (&builder
, "{sv}", "default-action-target",
768 notification
->default_action_target
);
771 if (notification
->buttons
->len
> 0)
773 GVariantBuilder actions_builder
;
776 g_variant_builder_init (&actions_builder
, G_VARIANT_TYPE ("aa{sv}"));
778 for (i
= 0; i
< notification
->buttons
->len
; i
++)
780 Button
*button
= g_ptr_array_index (notification
->buttons
, i
);
781 g_variant_builder_add (&actions_builder
, "@a{sv}", g_notification_serialize_button (button
));
784 g_variant_builder_add (&builder
, "{sv}", "buttons", g_variant_builder_end (&actions_builder
));
787 return g_variant_builder_end (&builder
);