diff options
-rw-r--r-- | gdk/gdktoplevel.c | 11 | ||||
-rw-r--r-- | gdk/gdktoplevelprivate.h | 6 | ||||
-rw-r--r-- | gdk/wayland/gdksurface-wayland.c | 5 | ||||
-rw-r--r-- | gdk/wayland/gdktoplevel-wayland-private.h | 1 | ||||
-rw-r--r-- | gdk/wayland/gdktoplevel-wayland.c | 160 | ||||
-rw-r--r-- | gdk/wayland/gdkwaylandtoplevel.h | 6 | ||||
-rw-r--r-- | gdk/x11/gdksurface-x11.c | 3 | ||||
-rw-r--r-- | gtk/deprecated/gtkshow.c | 11 | ||||
-rw-r--r-- | gtk/gtkfilechoosernativeportal.c | 8 | ||||
-rw-r--r-- | gtk/gtkopenuriportal.c | 8 | ||||
-rw-r--r-- | gtk/gtkprintoperation-portal.c | 8 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 16 | ||||
-rw-r--r-- | gtk/gtkwindowprivate.h | 3 | ||||
-rw-r--r-- | tests/meson.build | 1 | ||||
-rw-r--r-- | tests/testfilelauncher.c | 47 |
15 files changed, 242 insertions, 52 deletions
diff --git a/gdk/gdktoplevel.c b/gdk/gdktoplevel.c index 5a5c9e4d0f..6a1667768a 100644 --- a/gdk/gdktoplevel.c +++ b/gdk/gdktoplevel.c @@ -135,7 +135,8 @@ gdk_toplevel_default_export_handle_finish (GdkToplevel *toplevel, } static void -gdk_toplevel_default_unexport_handle (GdkToplevel *toplevel) +gdk_toplevel_default_unexport_handle (GdkToplevel *toplevel, + const char *handle) { } @@ -791,7 +792,7 @@ gdk_toplevel_export_handle (GdkToplevel *toplevel, * @result: the `GAsyncResult` * @error: return location for an error * - * Finishes the [method@Gdk.Toplevel.export_handle] cal and + * Finishes the [method@Gdk.Toplevel.export_handle] call and * returns the resulting handle. * * Returns: (nullable) (transfer full): the exported handle, @@ -810,6 +811,7 @@ gdk_toplevel_export_handle_finish (GdkToplevel *toplevel, /*< private > * gdk_toplevel_unexport_handle: * @toplevel: a `GdkToplevel` + * @handle: the handle to unexport * * Destroys the handle that was obtained with [method@Gdk.Toplevel.export_handle]. * @@ -819,7 +821,8 @@ gdk_toplevel_export_handle_finish (GdkToplevel *toplevel, * Since: 4.10 */ void -gdk_toplevel_unexport_handle (GdkToplevel *toplevel) +gdk_toplevel_unexport_handle (GdkToplevel *toplevel, + const char *handle) { - GDK_TOPLEVEL_GET_IFACE (toplevel)->unexport_handle (toplevel); + GDK_TOPLEVEL_GET_IFACE (toplevel)->unexport_handle (toplevel, handle); } diff --git a/gdk/gdktoplevelprivate.h b/gdk/gdktoplevelprivate.h index 8f0f8d6f8e..6fb6d40835 100644 --- a/gdk/gdktoplevelprivate.h +++ b/gdk/gdktoplevelprivate.h @@ -49,7 +49,8 @@ struct _GdkToplevelInterface GAsyncResult *result, GError **error); - void (* unexport_handle) (GdkToplevel *toplevel); + void (* unexport_handle) (GdkToplevel *toplevel, + const char *handle); }; typedef enum @@ -82,7 +83,8 @@ char *gdk_toplevel_export_handle_finish (GdkToplevel *toplevel, GAsyncResult *result, GError **error); -void gdk_toplevel_unexport_handle (GdkToplevel *toplevel); +void gdk_toplevel_unexport_handle (GdkToplevel *toplevel, + const char *handle); G_END_DECLS diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 5663a42d38..9d92737f83 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -1148,7 +1148,10 @@ gdk_wayland_surface_destroy (GdkSurface *surface, gdk_wayland_surface_hide_surface (surface); - gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE(surface)); + if (GDK_IS_TOPLEVEL (surface)) + gdk_wayland_toplevel_destroy (GDK_TOPLEVEL (surface)); + + gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE (surface)); frame_clock = gdk_surface_get_frame_clock (surface); g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_before_paint, surface); diff --git a/gdk/wayland/gdktoplevel-wayland-private.h b/gdk/wayland/gdktoplevel-wayland-private.h index 9b06101371..bd0836c0a0 100644 --- a/gdk/wayland/gdktoplevel-wayland-private.h +++ b/gdk/wayland/gdktoplevel-wayland-private.h @@ -39,3 +39,4 @@ void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel); gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel); void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel); +void gdk_wayland_toplevel_destroy (GdkToplevel *toplevel); diff --git a/gdk/wayland/gdktoplevel-wayland.c b/gdk/wayland/gdktoplevel-wayland.c index 022e341dd7..efe9ef86ce 100644 --- a/gdk/wayland/gdktoplevel-wayland.c +++ b/gdk/wayland/gdktoplevel-wayland.c @@ -54,11 +54,16 @@ static void gdk_wayland_toplevel_sync_parent (GdkWaylandToplevel *to static void gdk_wayland_toplevel_sync_parent_of_imported (GdkWaylandToplevel *toplevel); static void gdk_wayland_surface_create_xdg_toplevel (GdkWaylandToplevel *toplevel); static void gdk_wayland_toplevel_sync_title (GdkWaylandToplevel *toplevel); -static gboolean gdk_wayland_toplevel_is_exported (GdkWaylandToplevel *toplevel); static void unset_transient_for_exported (GdkWaylandToplevel *toplevel); /* {{{ GdkWaylandToplevel definition */ +typedef struct { + struct zxdg_exported_v1 *xdg_exported; + struct zxdg_exported_v2 *xdg_exported_v2; + char *handle; +} GdkWaylandExported; + /** * GdkWaylandToplevel: * @@ -83,8 +88,7 @@ struct _GdkWaylandToplevel GdkWaylandToplevel *transient_for; struct org_kde_kwin_server_decoration *server_decoration; - struct zxdg_exported_v1 *xdg_exported; - struct zxdg_exported_v2 *xdg_exported_v2; + GList *exported; struct { int width; @@ -103,12 +107,6 @@ struct _GdkWaylandToplevel } next_layout; struct { - GdkWaylandToplevelExported callback; - gpointer user_data; - GDestroyNotify destroy_func; - } exported; - - struct { gboolean was_set; char *application_id; @@ -1280,9 +1278,6 @@ gdk_wayland_toplevel_finalize (GObject *object) display_wayland->toplevels = g_list_remove (display_wayland->toplevels, self); - if (gdk_wayland_toplevel_is_exported (self)) - gdk_wayland_toplevel_unexport_handle (GDK_TOPLEVEL (self)); - g_free (self->application.application_id); g_free (self->application.app_menu_path); g_free (self->application.menubar_path); @@ -1747,8 +1742,12 @@ xdg_exported_handle_v1 (void *data, struct zxdg_exported_v1 *zxdg_exported_v1, const char *handle) { - g_task_return_pointer (G_TASK (data), g_strdup (handle), g_free); - g_object_unref (data); + GTask *task = G_TASK (data); + GdkWaylandExported *exported = (GdkWaylandExported *)g_task_get_task_data (task); + + exported->handle = g_strdup (handle); + g_task_return_pointer (task, g_strdup (handle), g_free); + g_object_unref (task); } static const struct zxdg_exported_v1_listener xdg_exported_listener_v1 = { @@ -1760,8 +1759,12 @@ xdg_exported_handle_v2 (void *data, struct zxdg_exported_v2 *zxdg_exported_v2, const char *handle) { - g_task_return_pointer (G_TASK (data), g_strdup (handle), g_free); - g_object_unref (data); + GTask *task = G_TASK (data); + GdkWaylandExported *exported = (GdkWaylandExported *)g_task_get_task_data (task); + + exported->handle = g_strdup (handle); + g_task_return_pointer (task, g_strdup (handle), g_free); + g_object_unref (task); } static const struct zxdg_exported_v2_listener xdg_exported_listener_v2 = { @@ -1784,19 +1787,27 @@ gdk_wayland_toplevel_real_export_handle (GdkToplevel *toplevel, if (display_wayland->xdg_exporter_v2) { - wayland_toplevel->xdg_exported_v2 = + GdkWaylandExported *exported = g_new0 (GdkWaylandExported, 1); + exported->xdg_exported_v2 = zxdg_exporter_v2_export_toplevel (display_wayland->xdg_exporter_v2, gdk_wayland_surface_get_wl_surface (surface)); - zxdg_exported_v2_add_listener (wayland_toplevel->xdg_exported_v2, + zxdg_exported_v2_add_listener (exported->xdg_exported_v2, &xdg_exported_listener_v2, task); + + wayland_toplevel->exported = g_list_prepend (wayland_toplevel->exported, exported); + g_task_set_task_data (task, exported, NULL); } else if (display_wayland->xdg_exporter) { - wayland_toplevel->xdg_exported = + GdkWaylandExported *exported = g_new0 (GdkWaylandExported, 1); + exported->xdg_exported = zxdg_exporter_v1_export (display_wayland->xdg_exporter, gdk_wayland_surface_get_wl_surface (surface)); - zxdg_exported_v1_add_listener (wayland_toplevel->xdg_exported, + zxdg_exported_v1_add_listener (exported->xdg_exported, &xdg_exported_listener_v1, task); + + wayland_toplevel->exported = g_list_prepend (wayland_toplevel->exported, exported); + g_task_set_task_data (task, exported, NULL); } else { @@ -1815,15 +1826,36 @@ gdk_wayland_toplevel_real_export_handle_finish (GdkToplevel *toplevel, } static void -gdk_wayland_toplevel_real_unexport_handle (GdkToplevel *toplevel) +destroy_exported (GdkWaylandExported *exported) +{ + g_clear_pointer (&exported->handle, g_free); + g_clear_pointer (&exported->xdg_exported_v2, zxdg_exported_v2_destroy); + g_clear_pointer (&exported->xdg_exported, zxdg_exported_v1_destroy); + g_free (exported); +} + +static void +gdk_wayland_toplevel_real_unexport_handle (GdkToplevel *toplevel, + const char *handle) { GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel); g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel)); - g_return_if_fail (wayland_toplevel->xdg_exported_v2 || wayland_toplevel->xdg_exported); + g_return_if_fail (handle != NULL); + + for (GList *l = wayland_toplevel->exported; l; l = l->next) + { + GdkWaylandExported *exported = l->data; + + if (exported->handle && strcmp (exported->handle, handle) == 0) + { + wayland_toplevel->exported = g_list_delete_link (wayland_toplevel->exported, l); + destroy_exported (exported); + return; + } + } - g_clear_pointer (&wayland_toplevel->xdg_exported_v2, zxdg_exported_v2_destroy); - g_clear_pointer (&wayland_toplevel->xdg_exported, zxdg_exported_v1_destroy); + g_warn_if_reached (); } static gboolean @@ -2255,6 +2287,32 @@ gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel, maybe_set_gtk_surface_dbus_properties (wayland_toplevel); } +void +gdk_wayland_toplevel_destroy (GdkToplevel *toplevel) +{ + GdkWaylandToplevel *self = GDK_WAYLAND_TOPLEVEL (toplevel); + + while (self->exported) + { + GdkWaylandExported *exported = self->exported->data; + self->exported = g_list_delete_link (self->exported, self->exported); + if (exported->handle == NULL) + { + GTask *task; + + if (exported->xdg_exported_v2) + task = G_TASK (wl_proxy_get_user_data ((struct wl_proxy *) exported->xdg_exported_v2)); + else + task = G_TASK (wl_proxy_get_user_data ((struct wl_proxy *) exported->xdg_exported)); + + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Surface was destroyed"); + g_object_unref (task); + } + + destroy_exported (exported); + } +} + /* }}} */ /* {{{ Toplevel API */ @@ -2397,12 +2455,6 @@ gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel) * marking surfaces as transient for out-of-process surfaces. */ -static gboolean -gdk_wayland_toplevel_is_exported (GdkWaylandToplevel *toplevel) -{ - return toplevel->xdg_exported != NULL || toplevel->xdg_exported_v2 != NULL; -} - typedef struct { GdkWaylandToplevelExported callback; gpointer user_data; @@ -2450,6 +2502,12 @@ export_handle_done (GObject *source, * from another surface as transient for this one, see * [method@GdkWayland.WaylandToplevel.set_transient_for_exported]. * + * Before 4.12, this API could not safely be used multiple times, + * since there was no reference counting for handles. Starting with + * 4.12, every call to this function obtains a new handle, and every + * call to [method@GdkWayland.WaylandToplevel.drop_exported_handle] drops + * just the handle that it is given. + * * Note that this API depends on an unstable Wayland protocol, * and thus may require changes in the future. * @@ -2486,15 +2544,53 @@ gdk_wayland_toplevel_export_handle (GdkToplevel *toplevel, * It is an error to call this function on a surface that * does not have a handle. * + * Since 4.12, this function does nothing. Use + * [method@GdkWayland.WaylandToplevel.drop_exported_handle] instead to drop a + * handle that was obtained with [method@GdkWayland.WaylandToplevel.export_handle]. + * * Note that this API depends on an unstable Wayland protocol, * and thus may require changes in the future. + * + * Deprecated: 4.12: Use [method@GdkWayland.WaylandToplevel.drop_exported_handle] + * instead, this function does nothing */ void gdk_wayland_toplevel_unexport_handle (GdkToplevel *toplevel) { - g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel)); + GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel); + + if (wayland_toplevel->exported != NULL && + wayland_toplevel->exported->next == NULL) + { + GdkWaylandExported *exported = wayland_toplevel->exported->data; - gdk_toplevel_unexport_handle (toplevel); + if (exported->handle) + { + gdk_toplevel_unexport_handle (toplevel, exported->handle); + return; + } + } + + g_warning ("Use gdk_wayland_toplevel_drop_exported_handle()"); +} + +/** + * gdk_wayland_toplevel_drop_exported_handle: + * @toplevel: (type GdkWaylandToplevel): the `GdkToplevel` that was exported + * @handle: the handle to drop + * + * Destroy a handle that was obtained with gdk_wayland_toplevel_export_handle(). + * + * Note that this API depends on an unstable Wayland protocol, + * and thus may require changes in the future. + * + * Since: 4.12 + */ +void +gdk_wayland_toplevel_drop_exported_handle (GdkToplevel *toplevel, + const char *handle) +{ + gdk_toplevel_unexport_handle (toplevel, handle); } static void diff --git a/gdk/wayland/gdkwaylandtoplevel.h b/gdk/wayland/gdkwaylandtoplevel.h index 36410b3054..0240f9d19f 100644 --- a/gdk/wayland/gdkwaylandtoplevel.h +++ b/gdk/wayland/gdkwaylandtoplevel.h @@ -52,9 +52,13 @@ gboolean gdk_wayland_toplevel_export_handle (GdkToplevel gpointer user_data, GDestroyNotify destroy_func); -GDK_AVAILABLE_IN_ALL +GDK_DEPRECATED_IN_4_12_FOR(gdk_wayland_toplevel_drop_exported_handle) void gdk_wayland_toplevel_unexport_handle (GdkToplevel *toplevel); +GDK_AVAILABLE_IN_4_12 +void gdk_wayland_toplevel_drop_exported_handle (GdkToplevel *toplevel, + const char *handle); + GDK_AVAILABLE_IN_ALL gboolean gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel, const char *parent_handle_str); diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c index db8a8770ed..468ee941b6 100644 --- a/gdk/x11/gdksurface-x11.c +++ b/gdk/x11/gdksurface-x11.c @@ -5318,7 +5318,8 @@ gdk_x11_toplevel_export_handle_finish (GdkToplevel *toplevel, } static void -gdk_x11_toplevel_unexport_handle (GdkToplevel *toplevel) +gdk_x11_toplevel_unexport_handle (GdkToplevel *toplevel, + const char *handle) { } diff --git a/gtk/deprecated/gtkshow.c b/gtk/deprecated/gtkshow.c index cd37905cf0..3c3b9616cd 100644 --- a/gtk/deprecated/gtkshow.c +++ b/gtk/deprecated/gtkshow.c @@ -31,6 +31,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS typedef struct { GtkWindow *parent; + char *handle; GAppLaunchContext *context; char *uri; GTask *task; @@ -39,9 +40,10 @@ typedef struct { static void gtk_show_uri_data_free (GtkShowUriData *data) { - if (data->parent) - gtk_window_unexport_handle (data->parent); + if (data->parent && data->handle) + gtk_window_unexport_handle (data->parent, data->handle); g_clear_object (&data->parent); + g_free (data->handle); g_clear_object (&data->context); g_free (data->uri); g_clear_object (&data->task); @@ -72,7 +74,10 @@ window_handle_exported (GtkWindow *window, GtkShowUriData *data = user_data; if (handle) - g_app_launch_context_setenv (data->context, "PARENT_WINDOW_ID", handle); + { + g_app_launch_context_setenv (data->context, "PARENT_WINDOW_ID", handle); + data->handle = g_strdup (handle); + } g_app_info_launch_default_for_uri_async (data->uri, data->context, diff --git a/gtk/gtkfilechoosernativeportal.c b/gtk/gtkfilechoosernativeportal.c index 3d73fa6db9..4bb312d8fb 100644 --- a/gtk/gtkfilechoosernativeportal.c +++ b/gtk/gtkfilechoosernativeportal.c @@ -52,6 +52,7 @@ typedef struct { const char *method_name; + char *exported_handle; GtkWindow *exported_window; PortalErrorHandler error_handler; } FilechooserPortalData; @@ -79,7 +80,11 @@ filechooser_portal_data_clear (FilechooserPortalData *data) if (data->exported_window) { - gtk_window_unexport_handle (data->exported_window); + if (data->exported_handle) + { + gtk_window_unexport_handle (data->exported_window, data->exported_handle); + g_clear_pointer (&data->exported_handle, g_free); + } g_clear_object (&data->exported_window); } @@ -460,6 +465,7 @@ window_handle_exported (GtkWindow *window, gtk_grab_add (GTK_WIDGET (data->grab_widget)); } + data->exported_handle = g_strdup (handle_str); show_portal_file_chooser (self, handle_str); } diff --git a/gtk/gtkopenuriportal.c b/gtk/gtkopenuriportal.c index 1bec7a1cb0..67778affda 100644 --- a/gtk/gtkopenuriportal.c +++ b/gtk/gtkopenuriportal.c @@ -108,6 +108,7 @@ enum { typedef struct { GtkWindow *parent; + char *parent_handle; GFile *file; char *uri; gboolean open_folder; @@ -128,8 +129,9 @@ open_uri_data_free (OpenUriData *data) g_clear_object (&data->connection); if (data->cancel_handler) g_signal_handler_disconnect (data->cancellable, data->cancel_handler); - if (data->parent) - gtk_window_unexport_handle (data->parent); + if (data->parent && data->parent_handle) + gtk_window_unexport_handle (data->parent, data->parent_handle); + g_free (data->parent_handle); g_clear_object (&data->parent); g_clear_object (&data->file); g_free (data->uri); @@ -426,6 +428,8 @@ window_handle_exported (GtkWindow *window, GAppLaunchContext *context; char *activation_token = NULL; + data->parent_handle = g_strdup (handle); + if (window) display = gtk_widget_get_display (GTK_WIDGET (window)); else diff --git a/gtk/gtkprintoperation-portal.c b/gtk/gtkprintoperation-portal.c index 61e4071df4..d39ad1645c 100644 --- a/gtk/gtkprintoperation-portal.c +++ b/gtk/gtkprintoperation-portal.c @@ -48,6 +48,7 @@ typedef struct { GtkPrintOperationResult result; GtkPrintOperationPrintFunc print_cb; GtkWindow *parent; + char *handle; GMainLoop *loop; guint32 token; GDestroyNotify destroy; @@ -62,8 +63,9 @@ portal_data_free (gpointer data) { PortalData *portal = data; - if (portal->parent) - gtk_window_unexport_handle (portal->parent); + if (portal->parent && portal->handle) + gtk_window_unexport_handle (portal->parent, portal->handle); + g_free (portal->handle); g_object_unref (portal->op); g_object_unref (portal->proxy); if (portal->loop) @@ -547,6 +549,8 @@ window_handle_exported (GtkWindow *window, { PortalData *portal = user_data; + portal->handle = g_strdup (handle_str); + g_dbus_proxy_call (portal->proxy, "PreparePrint", g_variant_new ("(ss@a{sv}@a{sv}@a{sv})", diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 42f1765cd0..4b67f2793b 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -6291,6 +6291,17 @@ prefix_handle (GdkDisplay *display, return NULL; } +static const char * +unprefix_handle (const char *handle) +{ + if (g_str_has_prefix (handle, "wayland:")) + return handle + strlen ("wayland:"); + else if (g_str_has_prefix (handle, "x11:")) + return handle + strlen ("x1!:"); + else + return handle; +} + static void export_handle_done (GObject *source, GAsyncResult *result, @@ -6336,11 +6347,12 @@ gtk_window_export_handle (GtkWindow *window, } void -gtk_window_unexport_handle (GtkWindow *window) +gtk_window_unexport_handle (GtkWindow *window, + const char *handle) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - gdk_toplevel_unexport_handle (GDK_TOPLEVEL (priv->surface)); + gdk_toplevel_unexport_handle (GDK_TOPLEVEL (priv->surface), unprefix_handle (handle)); } static GtkPointerFocus * diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h index d17ce474da..96d9dd110b 100644 --- a/gtk/gtkwindowprivate.h +++ b/gtk/gtkwindowprivate.h @@ -79,7 +79,8 @@ typedef void (*GtkWindowHandleExported) (GtkWindow *window, gboolean gtk_window_export_handle (GtkWindow *window, GtkWindowHandleExported callback, gpointer user_data); -void gtk_window_unexport_handle (GtkWindow *window); +void gtk_window_unexport_handle (GtkWindow *window, + const char *handle); GtkWidget * gtk_window_lookup_pointer_focus_widget (GtkWindow *window, GdkDevice *device, diff --git a/tests/meson.build b/tests/meson.build index c2d08c26de..c9c6e6a4cd 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,5 +1,6 @@ gtk_tests = [ # testname, optional extra sources + ['testfilelauncher'], ['input'], ['testpopup'], ['testupload'], diff --git a/tests/testfilelauncher.c b/tests/testfilelauncher.c new file mode 100644 index 0000000000..3a44037d51 --- /dev/null +++ b/tests/testfilelauncher.c @@ -0,0 +1,47 @@ +#include <gtk/gtk.h> + +static void +launched_cb (GObject *source, + GAsyncResult *result, + gpointer data) +{ + GtkFileLauncher *launcher = GTK_FILE_LAUNCHER (source); + GError *error = NULL; + + if (!gtk_file_launcher_launch_finish (launcher, result, &error)) + { + g_print ("Launching failed: %s\n", error->message); + g_error_free (error); + } +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *window; + GtkFileLauncher *launcher; + + gtk_init (); + + window = gtk_window_new (); + + launcher = gtk_file_launcher_new (NULL); + + gtk_window_present (GTK_WINDOW (window)); + + for (int i = 1; i < argc; i++) + { + GFile *file = g_file_new_for_commandline_arg (argv[i]); + + g_print ("launching %s\n", argv[i]); + + gtk_file_launcher_set_file (launcher, file); + gtk_file_launcher_launch (launcher, GTK_WINDOW (window), NULL, launched_cb, NULL); + g_object_unref (file); + } + + while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0) + g_main_context_iteration (NULL, FALSE); + + return 0; +} |