GPortalNotificationBackend: Implement it's own serialization method

The portal and GTK notifications will diverge, since they follow
different specs. For now it wasn't a problem since the portal was
strongly limited and essentially the same as the org.gtk.Notifications
interface. The serialization code is mostly the same as the already existing
serialization code.
This commit is contained in:
Julian Sparber 2024-05-02 12:50:46 +02:00
parent 4738951270
commit f5be07b755

View File

@ -23,6 +23,8 @@
#include "gnotificationbackend.h"
#include "giomodule-priv.h"
#include "gioenumtypes.h"
#include "gicon.h"
#include "gdbusconnection.h"
#include "gapplication.h"
#include "gnotification-private.h"
@ -46,6 +48,110 @@ G_DEFINE_TYPE_WITH_CODE (GPortalNotificationBackend, g_portal_notification_backe
g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME,
g_define_type_id, "portal", 110))
static GVariant *
serialize_buttons (GNotification *notification)
{
GVariantBuilder builder;
guint n_buttons;
guint i;
n_buttons = g_notification_get_n_buttons (notification);
if (n_buttons == 0)
return NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
for (i = 0; i < n_buttons; i++)
{
gchar *label;
gchar *action_name;
GVariant *target = NULL;
g_notification_get_button (notification, i, &label, &action_name, &target);
g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_take_string (label));
g_variant_builder_add (&builder, "{sv}", "action", g_variant_new_take_string (action_name));
if (target)
{
g_variant_builder_add (&builder, "{sv}", "target", target);
g_clear_pointer (&target, g_variant_unref);
}
g_variant_builder_close (&builder);
}
return g_variant_builder_end (&builder);
}
static GVariant *
serialize_priority (GNotification *notification)
{
GEnumClass *enum_class;
GEnumValue *value;
GVariant *nick;
enum_class = g_type_class_ref (G_TYPE_NOTIFICATION_PRIORITY);
value = g_enum_get_value (enum_class, g_notification_get_priority (notification));
g_assert (value != NULL);
nick = g_variant_new_string (value->value_nick);
g_type_class_unref (enum_class);
return nick;
}
static GVariant *
serialize_notification (GNotification *notification)
{
GVariantBuilder builder;
const gchar *body;
GIcon *icon;
gchar *default_action = NULL;
GVariant *default_action_target = NULL;
GVariant *buttons = NULL;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "title", g_variant_new_string (g_notification_get_title (notification)));
if ((body = g_notification_get_body (notification)))
g_variant_builder_add (&builder, "{sv}", "body", g_variant_new_string (body));
if ((icon = g_notification_get_icon (notification)))
{
GVariant *serialized_icon = NULL;
if ((serialized_icon = g_icon_serialize (icon)))
{
g_variant_builder_add (&builder, "{sv}", "icon", serialized_icon);
g_clear_object (&icon);
}
}
g_variant_builder_add (&builder, "{sv}", "priority", serialize_priority (notification));
if (g_notification_get_default_action (notification, &default_action, &default_action_target))
{
g_variant_builder_add (&builder, "{sv}", "default-action",
g_variant_new_take_string (g_steal_pointer (&default_action)));
if (default_action_target)
{
g_variant_builder_add (&builder, "{sv}", "default-action-target",
default_action_target);
g_clear_pointer (&default_action_target, g_variant_unref);
}
}
if ((buttons = serialize_buttons (notification)))
g_variant_builder_add (&builder, "{sv}", "buttons", buttons);
return g_variant_builder_end (&builder);
}
static gboolean
g_portal_notification_backend_is_supported (void)
{
@ -64,7 +170,7 @@ g_portal_notification_backend_send_notification (GNotificationBackend *backend,
"AddNotification",
g_variant_new ("(s@a{sv})",
id,
g_notification_serialize (notification)),
serialize_notification (notification)),
G_VARIANT_TYPE_UNIT,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}