diff options
author | Nelson Benítez León <nbenitezl@gmail.com> | 2023-04-08 23:56:05 -0400 |
---|---|---|
committer | Nelson Benítez León <nbenitezl@gmail.com> | 2023-04-09 17:24:28 -0400 |
commit | 9509db83e8582648e1e842d741c13c75acf4ed5a (patch) | |
tree | f12968bda5df63a848d5307161678bf3b0fafcc9 | |
parent | 9608e4e503df28e31137f4841409876f5aaf1e0d (diff) | |
download | gtk+-retry_when_dbus_openuri_fails.tar.gz |
gtk_uri_launcher_launch(): retry if DBus portal method failsretry_when_dbus_openuri_fails
gtk_uri_launcher_launch() has two code paths for lauching an uri,
one is using the Freedesktop.Desktop portal (OpenURI method)
and second one which does not use DBus and instead calls
gtk_show_uri_full() (this is used in Windows platform).
There may be partial Freedesktop.Desktop portal implementations which
lack the OpenURI method, in that cases clicking a GtkLinkButton will
do nothing.
We remedy that by detecting when the DBus method call failed, and
in that case try again by using the second approach (which does not
use DBus).
Fixes #5733
-rw-r--r-- | gtk/gtkurilauncher.c | 74 |
1 files changed, 64 insertions, 10 deletions
diff --git a/gtk/gtkurilauncher.c b/gtk/gtkurilauncher.c index bf6e2e260b..a72306161e 100644 --- a/gtk/gtkurilauncher.c +++ b/gtk/gtkurilauncher.c @@ -213,20 +213,64 @@ gtk_uri_launcher_set_uri (GtkUriLauncher *self, /* {{{ Async implementation */ #ifndef G_OS_WIN32 +static void show_uri_done (GObject *source, + GAsyncResult *result, + gpointer data); + +typedef struct { + GtkUriLauncher *launcher; + GtkWindow *window; + GCancellable *cancellable; + GTask *task; + GAsyncReadyCallback orig_callback; + gpointer orig_callback_data; +} CallbackData; + +static void +free_callback_data (CallbackData *data) +{ + g_clear_object (&data->launcher); + g_clear_object (&data->task); + g_clear_object (&data->window); + g_clear_object (&data->cancellable); + g_free (data); +} + +static gboolean +show_uri_in_idle (CallbackData *cbdata) +{ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + gtk_show_uri_full (cbdata->window, cbdata->launcher->uri, GDK_CURRENT_TIME, + cbdata->cancellable, show_uri_done, cbdata->task); +G_GNUC_END_IGNORE_DEPRECATIONS + free_callback_data (cbdata); + + return FALSE; +} + static void open_done (GObject *source, GAsyncResult *result, gpointer data) { - GTask *task = G_TASK (data); + CallbackData *cbdata = (CallbackData *) data; GError *error = NULL; - if (!gtk_openuri_portal_open_uri_finish (result, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - - g_object_unref (task); + if (!gtk_openuri_portal_open_uri_finish (result, &error)) { + /* DBus method failed or is not implemented, + * try again without using portal - Issue #5733 */ + GTask *task; + task = g_task_new (cbdata->launcher, cbdata->cancellable, + cbdata->orig_callback, cbdata->orig_callback_data); + g_task_set_check_cancellable (task, FALSE); + g_task_set_source_tag (task, open_done); + g_clear_object (&cbdata->task); + cbdata->task = g_object_ref (task); + g_idle_add (G_SOURCE_FUNC (show_uri_in_idle), cbdata); + } else { + g_task_return_boolean (cbdata->task, TRUE); + free_callback_data (cbdata); + } } #endif @@ -300,9 +344,19 @@ gtk_uri_launcher_launch (GtkUriLauncher *self, } #ifndef G_OS_WIN32 - if (gtk_openuri_portal_is_available ()) - gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task); - else + if (gtk_openuri_portal_is_available ()) { + CallbackData *callback_data; + + callback_data = g_new (CallbackData, 1); + callback_data->launcher = g_object_ref (self); + callback_data->task = g_object_ref (task); + callback_data->window = parent ? g_object_ref (parent) : NULL; + callback_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + callback_data->orig_callback = callback; + callback_data->orig_callback_data = user_data; + + gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, callback_data); + } else #endif G_GNUC_BEGIN_IGNORE_DEPRECATIONS gtk_show_uri_full (parent, self->uri, GDK_CURRENT_TIME, cancellable, show_uri_done, task); |