unicode: Simplify width table generation
[glib.git] / gio / gnotification.c
blobe15da5e2a6faafa4086cedaf7f31df0900664c11
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, see <http://www.gnu.org/licenses/>.
17 * Authors: Lars Uebernickel <lars@uebernic.de>
20 #include "config.h"
22 #include "gnotification-private.h"
23 #include "gdbusutils.h"
24 #include "gicon.h"
25 #include "gaction.h"
27 /**
28 * SECTION:gnotification
29 * @short_description: User Notifications (pop up messages)
30 * @include: gio/gio.h
32 * #GNotification is a mechanism for creating a notification to be shown
33 * to the user -- typically as a pop-up notification presented by the
34 * desktop environment shell.
36 * The key difference between #GNotification and other similar APIs is
37 * that, if supported by the desktop environment, notifications sent
38 * with #GNotification will persist after the application has exited,
39 * and even across system reboots.
41 * Since the user may click on a notification while the application is
42 * not running, applications using #GNotification should be able to be
43 * started as a D-Bus service, using #GApplication.
45 * User interaction with a notification (either the default action, or
46 * buttons) must be associated with actions on the application (ie:
47 * "app." actions). It is not possible to route user interaction
48 * through the notification itself, because the object will not exist if
49 * the application is autostarted as a result of a notification being
50 * clicked.
52 * A notification can be sent with g_application_send_notification().
54 * Since: 2.40
55 **/
57 /**
58 * GNotification:
60 * This structure type is private and should only be accessed using the
61 * public APIs.
63 * Since: 2.40
64 **/
66 typedef GObjectClass GNotificationClass;
68 struct _GNotification
70 GObject parent;
72 gchar *title;
73 gchar *body;
74 GIcon *icon;
75 gboolean urgent;
76 GPtrArray *buttons;
77 gchar *default_action;
78 GVariant *default_action_target;
81 typedef struct
83 gchar *label;
84 gchar *action_name;
85 GVariant *target;
86 } Button;
88 G_DEFINE_TYPE (GNotification, g_notification, G_TYPE_OBJECT);
90 static void
91 button_free (gpointer data)
93 Button *button = data;
95 g_free (button->label);
96 g_free (button->action_name);
97 if (button->target)
98 g_variant_unref (button->target);
100 g_slice_free (Button, button);
103 static void
104 g_notification_dispose (GObject *object)
106 GNotification *notification = G_NOTIFICATION (object);
108 g_clear_object (&notification->icon);
110 G_OBJECT_CLASS (g_notification_parent_class)->dispose (object);
113 static void
114 g_notification_finalize (GObject *object)
116 GNotification *notification = G_NOTIFICATION (object);
118 g_free (notification->title);
119 g_free (notification->body);
120 g_free (notification->default_action);
121 if (notification->default_action_target)
122 g_variant_unref (notification->default_action_target);
123 g_ptr_array_free (notification->buttons, TRUE);
125 G_OBJECT_CLASS (g_notification_parent_class)->finalize (object);
128 static void
129 g_notification_class_init (GNotificationClass *klass)
131 GObjectClass *object_class = G_OBJECT_CLASS (klass);
133 object_class->dispose = g_notification_dispose;
134 object_class->finalize = g_notification_finalize;
137 static void
138 g_notification_init (GNotification *notification)
140 notification->buttons = g_ptr_array_new_full (2, button_free);
144 * g_notification_new:
145 * @title: the title of the notification
147 * Creates a new #GNotification with @title as its title.
149 * After populating @notification with more details, it can be sent to
150 * the desktop shell with g_application_send_notification(). Changing
151 * any properties after this call will not have any effect until
152 * resending @notification.
154 * Returns: a new #GNotification instance
156 * Since: 2.40
158 GNotification *
159 g_notification_new (const gchar *title)
161 GNotification *notification;
163 g_return_val_if_fail (title != NULL, NULL);
165 notification = g_object_new (G_TYPE_NOTIFICATION, NULL);
166 notification->title = g_strdup (title);
168 return notification;
171 /*< private >
172 * g_notification_get_title:
173 * @notification: a #GNotification
175 * Gets the title of @notification.
177 * Returns: the title of @notification
179 * Since: 2.40
181 const gchar *
182 g_notification_get_title (GNotification *notification)
184 g_return_val_if_fail (G_IS_NOTIFICATION (notification), NULL);
186 return notification->title;
190 * g_notification_set_title:
191 * @notification: a #GNotification
192 * @title: the new title for @notification
194 * Sets the title of @notification to @title.
196 * Since: 2.40
198 void
199 g_notification_set_title (GNotification *notification,
200 const gchar *title)
202 g_return_if_fail (G_IS_NOTIFICATION (notification));
203 g_return_if_fail (title != NULL);
205 g_free (notification->title);
207 notification->title = g_strdup (title);
210 /*< private >
211 * g_notification_get_body:
212 * @notification: a #GNotification
214 * Gets the current body of @notification.
216 * Returns: (allow-none): the body of @notification
218 * Since: 2.40
220 const gchar *
221 g_notification_get_body (GNotification *notification)
223 g_return_val_if_fail (G_IS_NOTIFICATION (notification), NULL);
225 return notification->body;
229 * g_notification_set_body:
230 * @notification: a #GNotification
231 * @body: (allow-none): the new body for @notification, or %NULL
233 * Sets the body of @notification to @body.
235 * Since: 2.40
237 void
238 g_notification_set_body (GNotification *notification,
239 const gchar *body)
241 g_return_if_fail (G_IS_NOTIFICATION (notification));
242 g_return_if_fail (body != NULL);
244 g_free (notification->body);
246 notification->body = g_strdup (body);
249 /*< private >
250 * g_notification_get_icon:
251 * @notification: a #GNotification
253 * Gets the icon currently set on @notification.
255 * Returns: (transfer none): the icon associated with @notification
257 * Since: 2.40
259 GIcon *
260 g_notification_get_icon (GNotification *notification)
262 g_return_val_if_fail (G_IS_NOTIFICATION (notification), NULL);
264 return notification->icon;
268 * g_notification_set_icon:
269 * @notification: a #GNotification
270 * @icon: the icon to be shown in @notification, as a #GIcon
272 * Sets the icon of @notification to @icon.
274 * Since: 2.40
276 void
277 g_notification_set_icon (GNotification *notification,
278 GIcon *icon)
280 g_return_if_fail (G_IS_NOTIFICATION (notification));
282 if (notification->icon)
283 g_object_unref (notification->icon);
285 notification->icon = g_object_ref (icon);
288 /*< private >
289 * g_notification_get_urgent:
290 * @notification: a #GNotification
292 * Returns %TRUE if @notification is marked as urgent.
294 * Since: 2.40
296 gboolean
297 g_notification_get_urgent (GNotification *notification)
299 g_return_val_if_fail (G_IS_NOTIFICATION (notification), FALSE);
301 return notification->urgent;
305 * g_notification_set_urgent:
306 * @notification: a #GNotification
307 * @urgent: %TRUE if @notification is urgent
309 * Sets or unsets whether @notification is marked as urgent.
311 * Since: 2.40
313 void
314 g_notification_set_urgent (GNotification *notification,
315 gboolean urgent)
317 g_return_if_fail (G_IS_NOTIFICATION (notification));
319 notification->urgent = urgent;
323 * g_notification_add_button:
324 * @notification: a #GNotification
325 * @label: label of the button
326 * @detailed_action: a detailed action name
328 * Adds a button to @notification that activates the action in
329 * @detailed_action when clicked. That action must be an
330 * application-wide action (starting with "app."). If @detailed_action
331 * contains a target, the action will be activated with that target as
332 * its parameter.
334 * See g_action_parse_detailed_name() for a description of the format
335 * for @detailed_action.
337 * Since: 2.40
339 void
340 g_notification_add_button (GNotification *notification,
341 const gchar *label,
342 const gchar *detailed_action)
344 gchar *action;
345 GVariant *target;
346 GError *error = NULL;
348 g_return_if_fail (detailed_action != NULL);
350 if (!g_action_parse_detailed_name (detailed_action, &action, &target, &error))
352 g_warning ("%s: %s", G_STRFUNC, error->message);
353 g_error_free (error);
354 return;
357 g_notification_add_button_with_target_value (notification, label, action, target);
359 g_free (action);
360 if (target)
361 g_variant_unref (target);
365 * g_notification_add_button_with_target: (skip)
366 * @notification: a #GNotification
367 * @label: label of the button
368 * @action: an action name
369 * @target_format: (allow-none): a #GVariant format string, or %NULL
370 * @...: positional parameters, as determined by @target_format
372 * Adds a button to @notification that activates @action when clicked.
373 * @action must be an application-wide action (it must start with "app.").
375 * If @target_format is given, it is used to collect remaining
376 * positional parameters into a #GVariant instance, similar to
377 * g_variant_new(). @action will be activated with that #GVariant as its
378 * parameter.
380 * Since: 2.40
382 void
383 g_notification_add_button_with_target (GNotification *notification,
384 const gchar *label,
385 const gchar *action,
386 const gchar *target_format,
387 ...)
389 va_list args;
390 GVariant *target = NULL;
392 if (target_format)
394 va_start (args, target_format);
395 target = g_variant_new_va (target_format, NULL, &args);
396 va_end (args);
399 g_notification_add_button_with_target_value (notification, label, action, target);
403 * g_notification_add_button_with_target_value: (rename-to g_notification_add_button_with_target)
404 * @notification: a #GNotification
405 * @label: label of the button
406 * @action: an action name
407 * @target: (allow-none): a #GVariant to use as @action's parameter, or %NULL
409 * Adds a button to @notification that activates @action when clicked.
410 * @action must be an application-wide action (it must start with "app.").
412 * If @target is non-%NULL, @action will be activated with @target as
413 * its parameter.
415 * Since: 2.40
417 void
418 g_notification_add_button_with_target_value (GNotification *notification,
419 const gchar *label,
420 const gchar *action,
421 GVariant *target)
423 Button *button;
425 g_return_if_fail (G_IS_NOTIFICATION (notification));
426 g_return_if_fail (label != NULL);
427 g_return_if_fail (action != NULL && g_action_name_is_valid (action));
429 if (!g_str_has_prefix (action, "app."))
431 g_warning ("%s: action '%s' does not start with 'app.'."
432 "This is unlikely to work properly.", G_STRFUNC, action);
435 button = g_slice_new0 (Button);
436 button->label = g_strdup (label);
437 button->action_name = g_strdup (action);
439 if (target)
440 button->target = g_variant_ref_sink (target);
442 g_ptr_array_add (notification->buttons, button);
445 /*< private >
446 * g_notification_get_n_buttons:
447 * @notification: a #GNotification
449 * Returns: the amount of buttons added to @notification.
451 guint
452 g_notification_get_n_buttons (GNotification *notification)
454 return notification->buttons->len;
457 /*< private >
458 * g_notification_get_button:
459 * @notification: a #GNotification
460 * @index: index of the button
461 * @label: (): return location for the button's label
462 * @action: (): return location for the button's associated action
463 * @target: (): return location for the target @action should be
464 * activated with
466 * Returns a description of a button that was added to @notification
467 * with g_notification_add_button().
469 * @index must be smaller than the value returned by
470 * g_notification_get_n_buttons().
472 void
473 g_notification_get_button (GNotification *notification,
474 gint index,
475 gchar **label,
476 gchar **action,
477 GVariant **target)
479 Button *button;
481 button = g_ptr_array_index (notification->buttons, index);
483 if (label)
484 *label = g_strdup (button->label);
486 if (action)
487 *action = g_strdup (button->action_name);
489 if (target)
490 *target = button->target ? g_variant_ref (button->target) : NULL;
493 /*< private >
494 * g_notification_get_button_with_action:
495 * @notification: a #GNotification
496 * @action: an action name
498 * Returns the index of the button in @notification that is associated
499 * with @action, or -1 if no such button exists.
501 gint
502 g_notification_get_button_with_action (GNotification *notification,
503 const gchar *action)
505 guint i;
507 for (i = 0; i < notification->buttons->len; i++)
509 Button *button;
511 button = g_ptr_array_index (notification->buttons, i);
512 if (g_str_equal (action, button->action_name))
513 return i;
516 return -1;
520 /*< private >
521 * g_notification_get_default_action:
522 * @notification: a #GNotification
523 * @action: (allow-none): return location for the default action
524 * @target: (allow-none): return location for the target of the default action
526 * Gets the action and target for the default action of @notification.
528 * Returns: %TRUE if @notification has a default action
530 gboolean
531 g_notification_get_default_action (GNotification *notification,
532 gchar **action,
533 GVariant **target)
535 if (notification->default_action == NULL)
536 return FALSE;
538 if (action)
539 *action = g_strdup (notification->default_action);
541 if (target)
543 if (notification->default_action_target)
544 *target = g_variant_ref (notification->default_action_target);
545 else
546 *target = NULL;
549 return TRUE;
553 * g_notification_set_default_action:
554 * @notification: a #GNotification
555 * @detailed_action: a detailed action name
557 * Sets the default action of @notification to @detailed_action. This
558 * action is activated when the notification is clicked on.
560 * The action in @detailed_action must be an application-wide action (it
561 * must start with "app."). If @detailed_action contains a target, the
562 * given action will be activated with that target as its parameter.
563 * See g_action_parse_detailed_name() for a description of the format
564 * for @detailed_action.
566 * When no default action is set, the application that the notification
567 * was sent on is activated.
569 * Since: 2.40
571 void
572 g_notification_set_default_action (GNotification *notification,
573 const gchar *detailed_action)
575 gchar *action;
576 GVariant *target;
577 GError *error = NULL;
579 if (!g_action_parse_detailed_name (detailed_action, &action, &target, &error))
581 g_warning ("%s: %s", G_STRFUNC, error->message);
582 g_error_free (error);
583 return;
586 g_notification_set_default_action_and_target_value (notification, action, target);
588 g_free (action);
589 if (target)
590 g_variant_unref (target);
594 * g_notification_set_default_action_and_target: (skip)
595 * @notification: a #GNotification
596 * @action: an action name
597 * @target_format: (allow-none): a #GVariant format string, or %NULL
598 * @...: positional parameters, as determined by @target_format
600 * Sets the default action of @notification to @action. This action is
601 * activated when the notification is clicked on. It must be an
602 * application-wide action (it must start with "app.").
604 * If @target_format is given, it is used to collect remaining
605 * positional parameters into a #GVariant instance, similar to
606 * g_variant_new(). @action will be activated with that #GVariant as its
607 * parameter.
609 * When no default action is set, the application that the notification
610 * was sent on is activated.
612 * Since: 2.40
614 void
615 g_notification_set_default_action_and_target (GNotification *notification,
616 const gchar *action,
617 const gchar *target_format,
618 ...)
620 va_list args;
621 GVariant *target = NULL;
623 if (target_format)
625 va_start (args, target_format);
626 target = g_variant_new_va (target_format, NULL, &args);
627 va_end (args);
630 g_notification_set_default_action_and_target_value (notification, action, target);
634 * g_notification_set_default_action_and_target_value: (rename-to g_notification_set_default_action_and_target)
635 * @notification: a #GNotification
636 * @action: an action name
637 * @target: (allow-none): a #GVariant to use as @action's parameter, or %NULL
639 * Sets the default action of @notification to @action. This action is
640 * activated when the notification is clicked on. It must be an
641 * application-wide action (start with "app.").
643 * If @target is non-%NULL, @action will be activated with @target as
644 * its parameter.
646 * When no default action is set, the application that the notification
647 * was sent on is activated.
649 * Since: 2.40
651 void
652 g_notification_set_default_action_and_target_value (GNotification *notification,
653 const gchar *action,
654 GVariant *target)
656 g_return_if_fail (G_IS_NOTIFICATION (notification));
657 g_return_if_fail (action != NULL && g_action_name_is_valid (action));
659 if (!g_str_has_prefix (action, "app."))
661 g_warning ("%s: action '%s' does not start with 'app.'."
662 "This is unlikely to work properly.", G_STRFUNC, action);
665 g_free (notification->default_action);
666 g_clear_pointer (&notification->default_action_target, g_variant_unref);
668 notification->default_action = g_strdup (action);
670 if (target)
671 notification->default_action_target = g_variant_ref_sink (target);
674 static GVariant *
675 g_notification_serialize_button (Button *button)
677 GVariantBuilder builder;
679 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
681 g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (button->label));
682 g_variant_builder_add (&builder, "{sv}", "action", g_variant_new_string (button->action_name));
684 if (button->target)
685 g_variant_builder_add (&builder, "{sv}", "target", button->target);
687 return g_variant_builder_end (&builder);
690 /*< private >
691 * g_notification_serialize:
693 * Serializes @notification into an floating variant of type a{sv}.
695 * Returns: the serialized @notification as a floating variant.
697 GVariant *
698 g_notification_serialize (GNotification *notification)
700 GVariantBuilder builder;
702 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
704 if (notification->title)
705 g_variant_builder_add (&builder, "{sv}", "title", g_variant_new_string (notification->title));
707 if (notification->body)
708 g_variant_builder_add (&builder, "{sv}", "body", g_variant_new_string (notification->body));
710 if (notification->icon)
712 GVariant *serialized_icon;
714 if ((serialized_icon = g_icon_serialize (notification->icon)))
716 g_variant_builder_add (&builder, "{sv}", "icon", serialized_icon);
717 g_variant_unref (serialized_icon);
721 g_variant_builder_add (&builder, "{sv}", "urgent", g_variant_new_boolean (notification->urgent));
723 if (notification->default_action)
725 g_variant_builder_add (&builder, "{sv}", "default-action",
726 g_variant_new_string (notification->default_action));
728 if (notification->default_action_target)
729 g_variant_builder_add (&builder, "{sv}", "default-action-target",
730 notification->default_action_target);
733 if (notification->buttons->len > 0)
735 GVariantBuilder actions_builder;
736 guint i;
738 g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
740 for (i = 0; i < notification->buttons->len; i++)
742 Button *button = g_ptr_array_index (notification->buttons, i);
743 g_variant_builder_add (&actions_builder, "@a{sv}", g_notification_serialize_button (button));
746 g_variant_builder_add (&builder, "{sv}", "buttons", g_variant_builder_end (&actions_builder));
749 return g_variant_builder_end (&builder);