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:
*
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;
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);
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 = {
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 = {
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
{
return g_task_propagate_pointer (G_TASK (result), error);
}
+static void
+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;
- g_clear_pointer (&wayland_toplevel->xdg_exported_v2, zxdg_exported_v2_destroy);
- g_clear_pointer (&wayland_toplevel->xdg_exported, zxdg_exported_v1_destroy);
+ if (exported->handle && strcmp (exported->handle, handle) == 0)
+ {
+ wayland_toplevel->exported = g_list_delete_link (wayland_toplevel->exported, l);
+ destroy_exported (exported);
+ return;
+ }
+ }
+
+ g_warn_if_reached ();
}
static gboolean
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);
+ }
}
/* }}} */
* 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;