GSeekable: document seek-past-end semantics
[glib.git] / gio / gnotification.c
blob4add2325dab0b5275fdbd90fc186729c30c8dbbc
1 /*
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 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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Authors: Lars Uebernickel <lars@uebernic.de>
22 #include "config.h"
24 #include "gnotification-private.h"
25 #include "gdbusutils.h"
26 #include "gicon.h"
27 #include "gaction.h"
29 /**
30 * SECTION:gnotification
31 * @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
51 * clicked.
53 * A notification can be sent with g_application_send_notification().
55 * Since: 2.40
56 **/
58 /**
59 * GNotification:
61 * This structure type is private and should only be accessed using the
62 * public APIs.
64 * Since: 2.40
65 **/
67 typedef GObjectClass GNotificationClass;
69 struct _GNotification
71 GObject parent;
73 gchar *title;
74 gchar *body;
75 GIcon *icon;
76 gboolean urgent;
77 GPtrArray *buttons;
78 gchar *default_action;
79 GVariant *default_action_target;
82 typedef struct
84 gchar *label;
85 gchar *action_name;
86 GVariant *target;
87 } Button;
89 G_DEFINE_TYPE (GNotification, g_notification, G_TYPE_OBJECT);
91 static void
92 button_free (gpointer data)
94 Button *button = data;
96 g_free (button->label);
97 g_free (button->action_name);
98 if (button->target)
99 g_variant_unref (button->target);
101 g_slice_free (Button, button);
104 static void
105 g_notification_dispose (GObject *object)
107 GNotification *notification = G_NOTIFICATION (object);
109 g_clear_object (&notification->icon);
111 G_OBJECT_CLASS (g_notification_parent_class)->dispose (object);
114 static void
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);
129 static void
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;
138 static void
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
157 * Since: 2.40
159 GNotification *
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);
169 return notification;
172 /*< private >
173 * g_notification_get_title:
174 * @notification: a #GNotification
176 * Gets the title of @notification.
178 * Returns: the title of @notification
180 * Since: 2.40
182 const gchar *
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.
197 * Since: 2.40
199 void
200 g_notification_set_title (GNotification *notification,
201 const gchar *title)
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);
211 /*< private >
212 * g_notification_get_body:
213 * @notification: a #GNotification
215 * Gets the current body of @notification.
217 * Returns: (allow-none): the body of @notification
219 * Since: 2.40
221 const gchar *
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: (allow-none): the new body for @notification, or %NULL
234 * Sets the body of @notification to @body.
236 * Since: 2.40
238 void
239 g_notification_set_body (GNotification *notification,
240 const gchar *body)
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);
250 /*< private >
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
258 * Since: 2.40
260 GIcon *
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.
275 * Since: 2.40
277 void
278 g_notification_set_icon (GNotification *notification,
279 GIcon *icon)
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);
289 /*< private >
290 * g_notification_get_urgent:
291 * @notification: a #GNotification
293 * Returns %TRUE if @notification is marked as urgent.
295 * Since: 2.40
297 gboolean
298 g_notification_get_urgent (GNotification *notification)
300 g_return_val_if_fail (G_IS_NOTIFICATION (notification), FALSE);
302 return notification->urgent;
306 * g_notification_set_urgent:
307 * @notification: a #GNotification
308 * @urgent: %TRUE if @notification is urgent
310 * Sets or unsets whether @notification is marked as urgent.
312 * Since: 2.40
314 void
315 g_notification_set_urgent (GNotification *notification,
316 gboolean urgent)
318 g_return_if_fail (G_IS_NOTIFICATION (notification));
320 notification->urgent = urgent;
324 * g_notification_add_button:
325 * @notification: a #GNotification
326 * @label: label of the button
327 * @detailed_action: a detailed action name
329 * Adds a button to @notification that activates the action in
330 * @detailed_action when clicked. That action must be an
331 * application-wide action (starting with "app."). If @detailed_action
332 * contains a target, the action will be activated with that target as
333 * its parameter.
335 * See g_action_parse_detailed_name() for a description of the format
336 * for @detailed_action.
338 * Since: 2.40
340 void
341 g_notification_add_button (GNotification *notification,
342 const gchar *label,
343 const gchar *detailed_action)
345 gchar *action;
346 GVariant *target;
347 GError *error = NULL;
349 g_return_if_fail (detailed_action != NULL);
351 if (!g_action_parse_detailed_name (detailed_action, &action, &target, &error))
353 g_warning ("%s: %s", G_STRFUNC, error->message);
354 g_error_free (error);
355 return;
358 g_notification_add_button_with_target_value (notification, label, action, target);
360 g_free (action);
361 if (target)
362 g_variant_unref (target);
366 * g_notification_add_button_with_target: (skip)
367 * @notification: a #GNotification
368 * @label: label of the button
369 * @action: an action name
370 * @target_format: (allow-none): a GVariant format string, or %NULL
371 * @...: positional parameters, as determined by @format_string
373 * Adds a button to @notification that activates @action when clicked.
374 * @action must be an application-wide action (it must start with "app.").
376 * If @target_format is given, it is used to collect remaining
377 * positional parameters into a GVariant instance, similar to
378 * g_variant_new(). @action will be activated with that GVariant as its
379 * parameter.
381 * Since: 2.40
383 void
384 g_notification_add_button_with_target (GNotification *notification,
385 const gchar *label,
386 const gchar *action,
387 const gchar *target_format,
388 ...)
390 va_list args;
391 GVariant *target = NULL;
393 if (target_format)
395 va_start (args, target_format);
396 target = g_variant_new_va (target_format, NULL, &args);
397 va_end (args);
400 g_notification_add_button_with_target_value (notification, label, action, target);
404 * g_notification_add_button_with_target_value: (rename-to g_notification_add_button_with_target)
405 * @notification: a #GNotification
406 * @label: label of the button
407 * @action: an action name
408 * @target: (allow-none): a GVariant to use as @action's parameter, or %NULL
410 * Adds a button to @notification that activates @action when clicked.
411 * @action must be an application-wide action (it must start with "app.").
413 * If @target is non-%NULL, @action will be activated with @target as
414 * its parameter.
416 * Since: 2.40
418 void
419 g_notification_add_button_with_target_value (GNotification *notification,
420 const gchar *label,
421 const gchar *action,
422 GVariant *target)
424 Button *button;
426 g_return_if_fail (G_IS_NOTIFICATION (notification));
427 g_return_if_fail (label != NULL);
428 g_return_if_fail (action != NULL && g_action_name_is_valid (action));
430 if (!g_str_has_prefix (action, "app."))
432 g_warning ("%s: action '%s' does not start with 'app.'."
433 "This is unlikely to work properly.", G_STRFUNC, action);
436 button = g_slice_new0 (Button);
437 button->label = g_strdup (label);
438 button->action_name = g_strdup (action);
440 if (target)
441 button->target = g_variant_ref_sink (target);
443 g_ptr_array_add (notification->buttons, button);
446 /*< private >
447 * g_notification_get_n_buttons:
448 * @notification: a #GNotification
450 * Returns: the amount of buttons added to @notification.
452 guint
453 g_notification_get_n_buttons (GNotification *notification)
455 return notification->buttons->len;
458 /*< private >
459 * g_notification_get_button:
460 * @notification: a #GNotification
461 * @index: index of the button
462 * @label: (): return location for the button's label
463 * @action: (): return location for the button's associated action
464 * @target: (): return location for the target @action should be
465 * activated with
467 * Returns a description of a button that was added to @notification
468 * with g_notification_add_button().
470 * @index must be smaller than the value returned by
471 * g_notification_get_n_buttons().
473 void
474 g_notification_get_button (GNotification *notification,
475 gint index,
476 gchar **label,
477 gchar **action,
478 GVariant **target)
480 Button *button;
482 button = g_ptr_array_index (notification->buttons, index);
484 if (label)
485 *label = g_strdup (button->label);
487 if (action)
488 *action = g_strdup (button->action_name);
490 if (target)
491 *target = button->target ? g_variant_ref (button->target) : NULL;
494 /*< private >
495 * g_notification_get_button_with_action:
496 * @notification: a #GNotification
497 * @action: an action name
499 * Returns the index of the button in @notification that is associated
500 * with @action, or -1 if no such button exists.
502 gint
503 g_notification_get_button_with_action (GNotification *notification,
504 const gchar *action)
506 guint i;
508 for (i = 0; i < notification->buttons->len; i++)
510 Button *button;
512 button = g_ptr_array_index (notification->buttons, i);
513 if (g_str_equal (action, button->action_name))
514 return i;
517 return -1;
521 /*< private >
522 * g_notification_get_default_action:
523 * @notification: a #GNotification
524 * @action: (allow-none): return location for the default action
525 * @target: (allow-none): return location for the target of the default action
527 * Gets the action and target for the default action of @notification.
529 * Returns: %TRUE if @notification has a default action
531 gboolean
532 g_notification_get_default_action (GNotification *notification,
533 gchar **action,
534 GVariant **target)
536 if (notification->default_action == NULL)
537 return FALSE;
539 if (action)
540 *action = g_strdup (notification->default_action);
542 if (target)
544 if (notification->default_action_target)
545 *target = g_variant_ref (notification->default_action_target);
546 else
547 *target = NULL;
550 return TRUE;
554 * g_notification_set_default_action:
555 * @notification: a #GNotification
556 * @detailed_action: a detailed action name
558 * Sets the default action of @notification to @detailed_action. This
559 * action is activated when the notification is clicked on.
561 * The action in @detailed_action must be an application-wide action (it
562 * must start with "app."). If @detailed_action contains a target, the
563 * given action will be activated with that target as its parameter.
564 * See g_action_parse_detailed_name() for a description of the format
565 * for @detailed_action.
567 * When no default action is set, the application that the notification
568 * was sent on is activated.
570 * Since: 2.40
572 void
573 g_notification_set_default_action (GNotification *notification,
574 const gchar *detailed_action)
576 gchar *action;
577 GVariant *target;
578 GError *error = NULL;
580 if (!g_action_parse_detailed_name (detailed_action, &action, &target, &error))
582 g_warning ("%s: %s", G_STRFUNC, error->message);
583 g_error_free (error);
584 return;
587 g_notification_set_default_action_and_target_value (notification, action, target);
589 g_free (action);
590 if (target)
591 g_variant_unref (target);
595 * g_notification_set_default_action_and_target: (skip)
596 * @notification: a #GNotification
597 * @action: an action name
598 * @target_format: (allow-none): a GVariant format string, or %NULL
599 * @...: positional parameters, as determined by @format_string
601 * Sets the default action of @notification to @action. This action is
602 * activated when the notification is clicked on. It must be an
603 * application-wide action (it must start with "app.").
605 * If @target_format is given, it is used to collect remaining
606 * positional parameters into a GVariant instance, similar to
607 * g_variant_new(). @action will be activated with that GVariant as its
608 * parameter.
610 * When no default action is set, the application that the notification
611 * was sent on is activated.
613 * Since: 2.40
615 void
616 g_notification_set_default_action_and_target (GNotification *notification,
617 const gchar *action,
618 const gchar *target_format,
619 ...)
621 va_list args;
622 GVariant *target = NULL;
624 if (target_format)
626 va_start (args, target_format);
627 target = g_variant_new_va (target_format, NULL, &args);
628 va_end (args);
631 g_notification_set_default_action_and_target_value (notification, action, target);
635 * g_notification_set_default_action_and_target_value: (rename-to g_notification_set_default_action_and_target)
636 * @notification: a #GNotification
637 * @action: an action name
638 * @target: (allow-none): a GVariant to use as @action's parameter, or %NULL
640 * Sets the default action of @notification to @action. This action is
641 * activated when the notification is clicked on. It must be an
642 * application-wide action (start with "app.").
644 * If @target_format is given, it is used to collect remaining
645 * positional parameters into a GVariant instance, similar to
646 * g_variant_new().
648 * If @target is non-%NULL, @action will be activated with @target as
649 * its parameter.
651 * When no default action is set, the application that the notification
652 * was sent on is activated.
654 * Since: 2.40
656 void
657 g_notification_set_default_action_and_target_value (GNotification *notification,
658 const gchar *action,
659 GVariant *target)
661 g_return_if_fail (G_IS_NOTIFICATION (notification));
662 g_return_if_fail (action != NULL && g_action_name_is_valid (action));
664 if (!g_str_has_prefix (action, "app."))
666 g_warning ("%s: action '%s' does not start with 'app.'."
667 "This is unlikely to work properly.", G_STRFUNC, action);
670 g_free (notification->default_action);
671 g_clear_pointer (&notification->default_action_target, g_variant_unref);
673 notification->default_action = g_strdup (action);
675 if (target)
676 notification->default_action_target = g_variant_ref_sink (target);
679 static GVariant *
680 g_notification_serialize_button (Button *button)
682 GVariantBuilder builder;
684 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
686 g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (button->label));
687 g_variant_builder_add (&builder, "{sv}", "action", g_variant_new_string (button->action_name));
689 if (button->target)
690 g_variant_builder_add (&builder, "{sv}", "target", button->target);
692 return g_variant_builder_end (&builder);
695 /*< private >
696 * g_notification_serialize:
698 * Serializes @notification into an floating variant of type a{sv}.
700 * Returns: the serialized @notification as a floating variant.
702 GVariant *
703 g_notification_serialize (GNotification *notification)
705 GVariantBuilder builder;
707 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
709 if (notification->title)
710 g_variant_builder_add (&builder, "{sv}", "title", g_variant_new_string (notification->title));
712 if (notification->body)
713 g_variant_builder_add (&builder, "{sv}", "body", g_variant_new_string (notification->body));
715 if (notification->icon)
717 GVariant *serialized_icon;
719 if ((serialized_icon = g_icon_serialize (notification->icon)))
721 g_variant_builder_add (&builder, "{sv}", "icon", serialized_icon);
722 g_variant_unref (serialized_icon);
726 g_variant_builder_add (&builder, "{sv}", "urgent", g_variant_new_boolean (notification->urgent));
728 if (notification->default_action)
730 g_variant_builder_add (&builder, "{sv}", "default-action",
731 g_variant_new_string (notification->default_action));
733 if (notification->default_action_target)
734 g_variant_builder_add (&builder, "{sv}", "default-action-target",
735 notification->default_action_target);
738 if (notification->buttons->len > 0)
740 GVariantBuilder actions_builder;
741 guint i;
743 g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
745 for (i = 0; i < notification->buttons->len; i++)
747 Button *button = g_ptr_array_index (notification->buttons, i);
748 g_variant_builder_add (&actions_builder, "@a{sv}", g_notification_serialize_button (button));
751 g_variant_builder_add (&builder, "{sv}", "buttons", g_variant_builder_end (&actions_builder));
754 return g_variant_builder_end (&builder);