summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNelson Benítez León <nbenitezl@gmail.com>2023-04-08 23:56:05 -0400
committerNelson Benítez León <nbenitezl@gmail.com>2023-04-09 17:24:28 -0400
commit9509db83e8582648e1e842d741c13c75acf4ed5a (patch)
treef12968bda5df63a848d5307161678bf3b0fafcc9
parent9608e4e503df28e31137f4841409876f5aaf1e0d (diff)
downloadgtk+-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.c74
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);