diff --git a/gio/gcocoanotificationbackend.m b/gio/gcocoanotificationbackend.m index 15c4433f4..512780583 100644 --- a/gio/gcocoanotificationbackend.m +++ b/gio/gcocoanotificationbackend.m @@ -175,7 +175,7 @@ add_actions_to_notification (NSUserNotification *userNotification, if (n_buttons) { - g_notification_get_button (notification, 0, &label, &action, &target); + g_notification_get_button (notification, 0, &label, NULL, &action, &target); if (label) { NSString *str_label = nsstring_from_cstr (label); diff --git a/gio/gfdonotificationbackend.c b/gio/gfdonotificationbackend.c index e396e97d1..703f50993 100644 --- a/gio/gfdonotificationbackend.c +++ b/gio/gfdonotificationbackend.c @@ -307,7 +307,7 @@ call_notify (GDBusConnection *con, GVariant *target; gchar *detailed_name; - g_notification_get_button (notification, i, &label, &action, &target); + g_notification_get_button (notification, i, &label, NULL, &action, &target); detailed_name = g_action_print_detailed_name (action, target); /* Actions named 'default' collide with libnotify's naming of the diff --git a/gio/gnotification-private.h b/gio/gnotification-private.h index d6f07bd33..d6e80b1d7 100644 --- a/gio/gnotification-private.h +++ b/gio/gnotification-private.h @@ -48,6 +48,7 @@ guint g_notification_get_n_buttons (GNotifi void g_notification_get_button (GNotification *notification, gint index, gchar **label, + gchar **purpose, gchar **action, GVariant **target); diff --git a/gio/gnotification.c b/gio/gnotification.c index 68c0dfb6a..cd1df1572 100644 --- a/gio/gnotification.c +++ b/gio/gnotification.c @@ -101,6 +101,7 @@ struct _GNotification typedef struct { gchar *label; + gchar *purpose; gchar *action_name; GVariant *target; } Button; @@ -112,10 +113,10 @@ button_free (gpointer data) { Button *button = data; - g_free (button->label); - g_free (button->action_name); - if (button->target) - g_variant_unref (button->target); + g_clear_pointer (&button->label, g_free); + g_clear_pointer (&button->action_name, g_free); + g_clear_pointer (&button->purpose, g_free); + g_clear_pointer (&button->target, g_variant_unref); g_slice_free (Button, button); } @@ -620,12 +621,11 @@ g_notification_add_button (GNotification *notification, if (!g_action_parse_detailed_name (detailed_action, &action, &target, &error)) { g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); return; } - g_notification_add_button_with_target_value (notification, label, action, target); + g_notification_add_button_with_purpose_and_target_value (notification, label, NULL, action, target); g_free (action); if (target) @@ -667,7 +667,7 @@ g_notification_add_button_with_target (GNotification *notification, va_end (args); } - g_notification_add_button_with_target_value (notification, label, action, target); + g_notification_add_button_with_purpose_and_target_value (notification, label, NULL, action, target); } /** @@ -690,11 +690,48 @@ g_notification_add_button_with_target_value (GNotification *notification, const gchar *label, const gchar *action, GVariant *target) +{ + g_notification_add_button_with_purpose_and_target_value (notification, label, NULL, action, target); +} + +/** + * g_notification_add_button_with_purpose_and_target_value: (rename-to g_notification_add_button_with_purpose_and_target) + * @notification: a [class@Gio.Notification] + * @label: (nullable): label of the button + * @purpose: (nullable): purpose of the button + * @action: an action name + * @target: (nullable): a [type@GLib.Variant] to use as @action's parameter, or %NULL + * + * Adds a button to @notification that activates @action when clicked. + * @action must be an application-wide action (it must start with `app.`). + * + * If @target is non-%NULL, @action will be activated with @target as + * its parameter. + * + * Standardized purposes are: + * + * - [const@Gio.NOTIFICATION_BUTTON_PURPOSE_CALL_ACCEPT] + * - [const@Gio.NOTIFICATION_BUTTON_PURPOSE_CALL_DECLINE] + * - [const@Gio.NOTIFICATION_BUTTON_PURPOSE_CALL_HANG_UP] + * - [const@Gio.NOTIFICATION_BUTTON_PURPOSE_CALL_ENABLE_SPEAKERPHONE] + * - [const@Gio.NOTIFICATION_BUTTON_PURPOSE_CALL_DISABLE_SPEAKERPHONE] + * + * It's possible to specify custom purposes but they should use `x-vendor.` + * as prefix, where vendor is the platform implementing the purpose. + * + * Since: 2.85 + */ +void +g_notification_add_button_with_purpose_and_target_value (GNotification *notification, + const gchar *label, + const gchar *purpose, + const gchar *action, + GVariant *target) { Button *button; g_return_if_fail (G_IS_NOTIFICATION (notification)); - g_return_if_fail (label != NULL); + g_return_if_fail (label != NULL || purpose != NULL); g_return_if_fail (action != NULL && g_action_name_is_valid (action)); if (!g_str_has_prefix (action, "app.")) @@ -704,7 +741,12 @@ g_notification_add_button_with_target_value (GNotification *notification, } button = g_slice_new0 (Button); - button->label = g_strdup (label); + if (label) + button->label = g_strdup (label); + + if (purpose) + button->purpose = g_strdup (purpose); + button->action_name = g_strdup (action); if (target) @@ -730,6 +772,7 @@ g_notification_get_n_buttons (GNotification *notification) * @notification: a #GNotification * @index: index of the button * @label: (): return location for the button's label + * @purpose: (): return location for the button's purpose * @action: (): return location for the button's associated action * @target: (): return location for the target @action should be * activated with @@ -744,6 +787,7 @@ void g_notification_get_button (GNotification *notification, gint index, gchar **label, + gchar **purpose, gchar **action, GVariant **target) { @@ -754,6 +798,9 @@ g_notification_get_button (GNotification *notification, if (label) *label = g_strdup (button->label); + if (purpose) + *purpose = g_strdup (button->purpose); + if (action) *action = g_strdup (button->action_name); diff --git a/gio/gnotification.h b/gio/gnotification.h index 533c45da7..9f5128463 100644 --- a/gio/gnotification.h +++ b/gio/gnotification.h @@ -95,6 +95,13 @@ void g_notification_add_button_with_target_value (GNotifi const gchar *action, GVariant *target); +GIO_AVAILABLE_IN_2_85 +void g_notification_add_button_with_purpose_and_target_value (GNotification *notification, + const gchar *label, + const gchar *purpose, + const gchar *action, + GVariant *target); + GIO_AVAILABLE_IN_2_40 void g_notification_set_default_action (GNotification *notification, const gchar *detailed_action); @@ -115,7 +122,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended for instant messaging apps displaying notifications for received messages. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_IM_RECEIVED "im.received" @@ -124,7 +131,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended for alarm clock apps when an alarm is ringing. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_ALARM_RINGING "alarm.ringing" @@ -133,7 +140,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended for call apps to notify the user about an incoming call. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CALL_INCOMING "call.incoming" @@ -142,7 +149,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended for call apps to notify the user about an ongoing call. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CALL_OUTGOING "call.ongoing" @@ -151,7 +158,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended for call apps to notify the user about a missed call. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CALL_UNANSWERED "call.unanswered" @@ -160,7 +167,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended to be used to notify the user about extreme weather conditions. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_WEATHER_WARNING_EXTREME "weather.warning.extreme" @@ -169,7 +176,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended to be used to notify users about severe danger warnings broadcasted by the cell network. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CELLBROADCAST_DANGER_SEVERE "cellbroadcast.danger.extreme" @@ -178,7 +185,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended to be used to notify users about amber alerts broadcasted by the cell network. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CELLBROADCAST_AMBER_ALERT "cellbroadcast.amber-alert" @@ -187,7 +194,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended to be used to notify users about tests broadcasted by the cell network. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_CELLBROADCAST_TEST "cellbroadcast.test" @@ -196,7 +203,7 @@ void g_notification_set_default_action_and_target_value (GNotifi * * Intended to be used to indicate that the system is low on battery. * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_OS_BATTERY_LOW "os.battery.low" @@ -206,10 +213,55 @@ void g_notification_set_default_action_and_target_value (GNotifi * Intended to be used by browsers to mark notifications sent by websites via * the [Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API). * - * Since: 2.84 + * Since: 2.85 */ #define G_NOTIFICATION_CATEGORY_BROWSER_WEB_NOTIFICATION "browser.web-notification" +/** + * G_NOTIFICATION_BUTTON_PURPOSE_CALL_ACCEPT: + * + * Purpose for a button that accepts an incoming call. + * + * Since: 2.85 + */ +#define G_NOTIFICATION_BUTTON_PURPOSE_CALL_ACCEPT "call.accept" + +/** + * G_NOTIFICATION_BUTTON_PURPOSE_CALL_DECLINE: + * + * Purpose for a button that declines an incoming call. + * + * Since: 2.85 + */ +#define G_NOTIFICATION_BUTTON_PURPOSE_CALL_DECLINE "call.decline" + +/** + * G_NOTIFICATION_BUTTON_PURPOSE_CALL_HANG_UP: + * + * Purpose for a button that hangs up an ongoing call. + * + * Since: 2.85 + */ +#define G_NOTIFICATION_BUTTON_PURPOSE_CALL_HANG_UP "call.hang-up" + +/** + * G_NOTIFICATION_BUTTON_PURPOSE_CALL_ENABLE_SPEAKERPHONE: + * + * Purpose for a button that enables the speakerphone for an ongoing call. + * + * Since: 2.85 + */ +#define G_NOTIFICATION_BUTTON_PURPOSE_CALL_ENABLE_SPEAKERPHONE "call.enable-speakerphone" + +/** + * G_NOTIFICATION_BUTTON_PURPOSE_CALL_DISABLE_SPEAKERPHONE: + * + * Purpose for a button that disables the speakerphone for an ongoing call. + * + * Since: 2.85 + */ +#define G_NOTIFICATION_BUTTON_PURPOSE_CALL_DISABLE_SPEAKERPHONE "call.disable-speakerphone" + G_END_DECLS #endif diff --git a/gio/gportalnotificationbackend.c b/gio/gportalnotificationbackend.c index 0c579adb1..189084e0f 100644 --- a/gio/gportalnotificationbackend.c +++ b/gio/gportalnotificationbackend.c @@ -726,7 +726,7 @@ serialize_buttons (GNotification *notification) gchar *action_name; GVariant *target = NULL; - g_notification_get_button (notification, i, &label, &action_name, &target); + g_notification_get_button (notification, i, &label, NULL, &action_name, &target); g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}")); diff --git a/gio/tests/gnotification.c b/gio/tests/gnotification.c index 117b0de6a..dbc63e523 100644 --- a/gio/tests/gnotification.c +++ b/gio/tests/gnotification.c @@ -183,6 +183,7 @@ struct _GNotification typedef struct { gchar *label; + gchar *purpose; gchar *action_name; GVariant *target; } Button; @@ -235,6 +236,11 @@ test_properties (void) g_notification_set_category (n, "cate.gory"); g_notification_set_display_hint_flags (n, G_NOTIFICATION_DISPLAY_HINT_TRANSIENT); g_notification_add_button (n, "label1", "app.action1::target1"); + g_notification_add_button_with_purpose_and_target_value (n, + "label", + "x-gnome.purpose", + "app.action2", + g_variant_new_string("bla")); g_notification_set_default_action (n, "app.action2::target2"); rn = (struct _GNotification *)n; @@ -251,12 +257,18 @@ test_properties (void) g_assert_cmpstr (rn->category, ==, "cate.gory"); g_assert_true (rn->display_hint == G_NOTIFICATION_DISPLAY_HINT_TRANSIENT); - g_assert_cmpint (rn->buttons->len, ==, 1); + g_assert_cmpint (rn->buttons->len, ==, 2); b = (Button*)rn->buttons->pdata[0]; g_assert_cmpstr (b->label, ==, "label1"); g_assert_cmpstr (b->action_name, ==, "app.action1"); g_assert_cmpstr (g_variant_get_string (b->target, NULL), ==, "target1"); + b = (Button*)rn->buttons->pdata[1]; + g_assert_cmpstr (b->label, ==, "label"); + g_assert_cmpstr (b->purpose, ==, "x-gnome.purpose"); + g_assert_cmpstr (b->action_name, ==, "app.action2"); + g_assert_cmpstr (g_variant_get_string (b->target, NULL), ==, "bla"); + g_assert_cmpstr (rn->default_action, ==, "app.action2"); g_assert_cmpstr (g_variant_get_string (rn->default_action_target, NULL), ==, "target2");