Skip to content

Commit

Permalink
Restore ability to call g_object_new (XDP_TYPE_PORTAL, ...)
Browse files Browse the repository at this point in the history
Calling `g_object_new()` for an XdpPortal used to work before 0.7,
but no longer sets up the GDBusConnection, making most method calls
fail with `assertion 'G_IS_DBUS_CONNECTION (connection)' failed`.
This makes #119 an incompatible change.

In particular, the GTK 4 test app calls `new Xdp.Portal()`, which
is a JavaScript binding for `g_object_new()` and fails in this way.
GObject documentation suggests that bindings should automatically
detect types that implement GInitable and call GInitable.init in the
higher-level language's constructor, but it seems that neither gjs nor
pygobject actually does this.

Mostly preserve previous functionality by moving the actual
initialization back to the GObject instance init function, and making
the GInitable init function just report a pre-existing error if any.

Signed-off-by: Simon McVittie <[email protected]>
  • Loading branch information
smcv committed Sep 8, 2023
1 parent fcfd10a commit f68e30a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 14 deletions.
1 change: 1 addition & 0 deletions libportal/portal-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
struct _XdpPortal {
GObject parent_instance;

GError *init_error;
GDBusConnection *bus;
char *sender;

Expand Down
39 changes: 25 additions & 14 deletions libportal/portal.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ xdp_portal_finalize (GObject *object)
{
XdpPortal *portal = XDP_PORTAL (object);

g_clear_error (&portal->init_error);

/* inhibit */
if (portal->inhibit_handles)
g_hash_table_unref (portal->inhibit_handles);
Expand Down Expand Up @@ -293,30 +295,44 @@ create_bus_from_address (const char *address,
return g_steal_pointer (&bus);
}

static gboolean
xdp_portal_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **out_error)
/* Historically, g_object_new() on an XdpPortal initialized it. We follow
* that here by doing the actual initialization early, and only dealing
* with the result in initable_init(). */
static void
xdp_portal_init (XdpPortal *portal)
{
int i;

XdpPortal *portal = (XdpPortal*) initable;

/* g_bus_get_sync() returns a singleton. In the test suite we may restart
* the session bus, so we have to manually connect to the new bus */
if (getenv ("LIBPORTAL_TEST_SUITE"))
portal->bus = create_bus_from_address (getenv ("DBUS_SESSION_BUS_ADDRESS"), out_error);
portal->bus = create_bus_from_address (getenv ("DBUS_SESSION_BUS_ADDRESS"), &portal->init_error);
else
portal->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, out_error);
portal->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &portal->init_error);

if (portal->bus == NULL)
return FALSE;
return;

portal->sender = g_strdup (g_dbus_connection_get_unique_name (portal->bus) + 1);
for (i = 0; portal->sender[i]; i++)
if (portal->sender[i] == '.')
portal->sender[i] = '_';
}

static gboolean
xdp_portal_initable_init (GInitable *initable,
GCancellable *cancellable,
GError **out_error)
{
XdpPortal *portal = (XdpPortal*) initable;

if (portal->init_error != NULL)
{
g_propagate_error (out_error, g_error_copy (portal->init_error));
return FALSE;
}

g_assert (portal->bus != NULL);
return TRUE;
}

Expand All @@ -326,11 +342,6 @@ xdp_portal_initable_iface_init (GInitableIface *iface)
iface->init = xdp_portal_initable_init;
}

static void
xdp_portal_init (XdpPortal *portal)
{
}

/**
* xdp_portal_initable_new:
* @error: A GError location to store the error occurring, or NULL to ignore.
Expand Down

0 comments on commit f68e30a

Please sign in to comment.