/* * GTK - The GIMP Toolkit * Copyright (C) 2008 Jaap Haitsma * * All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "config.h" #include #include "gtkshow.h" #include "gtkwindowprivate.h" #include "gtkmessagedialog.h" #include "gtkintl.h" typedef struct { GtkWindow *parent; GAppLaunchContext *context; char *uri; GTask *task; } GtkShowUriData; static void gtk_show_uri_data_free (GtkShowUriData *data) { if (data->parent) gtk_window_unexport_handle (data->parent); g_clear_object (&data->parent); g_clear_object (&data->context); g_free (data->uri); g_clear_object (&data->task); g_free (data); } static void launch_uri_done (GObject *source, GAsyncResult *result, gpointer user_data) { GtkShowUriData *data = user_data; GError *error = NULL; if (g_app_info_launch_default_for_uri_finish (result, &error)) g_task_return_boolean (data->task, TRUE); else g_task_return_error (data->task, error); gtk_show_uri_data_free (data); } static void window_handle_exported (GtkWindow *window, const char *handle, gpointer user_data) { GtkShowUriData *data = user_data; if (handle) g_app_launch_context_setenv (data->context, "PARENT_WINDOW_ID", handle); g_app_info_launch_default_for_uri_async (data->uri, data->context, g_task_get_cancellable (data->task), launch_uri_done, data); } /** * gtk_show_uri_full: * @parent: (nullable): parent window * @uri: the uri to show * @timestamp: timestamp from the event that triggered this call, or %GDK_CURRENT_TIME * @cancellable: (nullable): a `GCancellable` to cancel the launch * @callback: (scope async): a callback to call when the action is complete * @user_data: (closure callback): data to pass to @callback * * This function launches the default application for showing * a given uri. * * The @callback will be called when the launch is completed. * It should call gtk_show_uri_full_finish() to obtain the result. * * This is the recommended call to be used as it passes information * necessary for sandbox helpers to parent their dialogs properly. */ void gtk_show_uri_full (GtkWindow *parent, const char *uri, guint32 timestamp, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GtkShowUriData *data; GdkAppLaunchContext *context; GdkDisplay *display; g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); g_return_if_fail (uri != NULL); if (parent) display = gtk_widget_get_display (GTK_WIDGET (parent)); else display = gdk_display_get_default (); context = gdk_display_get_app_launch_context (display); gdk_app_launch_context_set_timestamp (context, timestamp); data = g_new0 (GtkShowUriData, 1); data->parent = parent ? g_object_ref (parent) : NULL; data->context = G_APP_LAUNCH_CONTEXT (context); data->uri = g_strdup (uri); data->task = g_task_new (parent, cancellable, callback, user_data); g_task_set_source_tag (data->task, gtk_show_uri); if (!parent || !gtk_window_export_handle (parent, window_handle_exported, data)) window_handle_exported (parent, NULL, data); } /** * gtk_show_uri_full_finish: * @parent: the `GtkWindow` passed to gtk_show_uri() * @result: `GAsyncResult` that was passed to @callback * @error: return location for an error * * Finishes the gtk_show_uri() call and returns the result * of the operation. * * Returns: %TRUE if the URI was shown successfully. * Otherwise, %FALSE is returned and @error is set */ gboolean gtk_show_uri_full_finish (GtkWindow *parent, GAsyncResult *result, GError **error) { g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), FALSE); g_return_val_if_fail (g_task_is_valid (result, parent), FALSE); g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == gtk_show_uri, FALSE); return g_task_propagate_boolean (G_TASK (result), error); } static void show_uri_done (GObject *object, GAsyncResult *result, gpointer data) { GtkWindow *parent = GTK_WINDOW (object); GError *error = NULL; if (!gtk_show_uri_full_finish (parent, result, &error)) { GtkWidget *dialog; dialog = gtk_message_dialog_new (parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", _("Could not show link")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message); g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL); gtk_window_present (GTK_WINDOW (dialog)); g_error_free (error); } } /** * gtk_show_uri: * @parent: (nullable): parent window * @uri: the uri to show * @timestamp: timestamp from the event that triggered this call, or %GDK_CURRENT_TIME * * This function launches the default application for showing * a given uri, or shows an error dialog if that fails. */ void gtk_show_uri (GtkWindow *parent, const char *uri, guint32 timestamp) { gtk_show_uri_full (parent, uri, timestamp, NULL, show_uri_done, NULL); }