diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index 8ff853687..bfb27cdf6 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -72,6 +72,8 @@ struct _MetaWaylandCompositor MetaWaylandSeat *seat; MetaWaylandTabletManager *tablet_manager; + + GHashTable *scheduled_surface_associations; }; #endif /* META_WAYLAND_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 41ad8bc2b..604d47e96 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1322,6 +1322,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor, surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL); surface->shortcut_inhibited_seats = g_hash_table_new (NULL, NULL); + meta_wayland_compositor_notify_surface_id (compositor, id, surface); + return surface; } diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index bab6b4ac4..63326fd9b 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -46,6 +46,7 @@ #include "meta-wayland-inhibit-shortcuts.h" #include "meta-wayland-inhibit-shortcuts-dialog.h" #include "meta-xwayland-grab-keyboard.h" +#include "meta-xwayland.h" static MetaWaylandCompositor _meta_wayland_compositor; static char *_display_name_override; @@ -306,6 +307,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor) { memset (compositor, 0, sizeof (MetaWaylandCompositor)); wl_list_init (&compositor->frame_callbacks); + + compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL); } void @@ -482,3 +485,62 @@ meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor) { wl_display_flush_clients (compositor->wayland_display); } + +static void on_scheduled_association_unmanaged (MetaWindow *window, + gpointer user_data); + +static void +meta_wayland_compositor_remove_surface_association (MetaWaylandCompositor *compositor, + int id) +{ + MetaWindow *window; + + window = g_hash_table_lookup (compositor->scheduled_surface_associations, + GINT_TO_POINTER (id)); + if (window) + { + g_signal_handlers_disconnect_by_func (window, + on_scheduled_association_unmanaged, + GINT_TO_POINTER (id)); + g_hash_table_remove (compositor->scheduled_surface_associations, + GINT_TO_POINTER (id)); + } +} + +static void +on_scheduled_association_unmanaged (MetaWindow *window, + gpointer user_data) +{ + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + + meta_wayland_compositor_remove_surface_association (compositor, + GPOINTER_TO_INT (user_data)); +} + +void +meta_wayland_compositor_schedule_surface_association (MetaWaylandCompositor *compositor, + int id, + MetaWindow *window) +{ + g_signal_connect (window, "unmanaged", + G_CALLBACK (on_scheduled_association_unmanaged), + GINT_TO_POINTER (id)); + g_hash_table_insert (compositor->scheduled_surface_associations, + GINT_TO_POINTER (id), window); +} + +void +meta_wayland_compositor_notify_surface_id (MetaWaylandCompositor *compositor, + int id, + MetaWaylandSurface *surface) +{ + MetaWindow *window; + + window = g_hash_table_lookup (compositor->scheduled_surface_associations, + GINT_TO_POINTER (id)); + if (window) + { + meta_xwayland_associate_window_with_surface (window, surface); + meta_wayland_compositor_remove_surface_association (compositor, id); + } +} diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h index d5795c1c2..1391bcd20 100644 --- a/src/wayland/meta-wayland.h +++ b/src/wayland/meta-wayland.h @@ -65,5 +65,12 @@ gboolean meta_wayland_compositor_is_shortcuts_inhibited (MetaWayl void meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor); +void meta_wayland_compositor_schedule_surface_association (MetaWaylandCompositor *compositor, + int id, + MetaWindow *window); +void meta_wayland_compositor_notify_surface_id (MetaWaylandCompositor *compositor, + int id, + MetaWaylandSurface *surface); + #endif diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index c3baaff05..955c57262 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -60,9 +60,9 @@ G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland, meta_wayland_surface_role_xwayland, META_TYPE_WAYLAND_ACTOR_SURFACE) -static void -associate_window_with_surface (MetaWindow *window, - MetaWaylandSurface *surface) +void +meta_xwayland_associate_window_with_surface (MetaWindow *window, + MetaWaylandSurface *surface) { MetaDisplay *display = window->display; @@ -110,58 +110,13 @@ associate_window_with_surface_id (MetaXWaylandManager *manager, if (resource) { MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - associate_window_with_surface (window, surface); + meta_xwayland_associate_window_with_surface (window, surface); return TRUE; } else return FALSE; } -typedef struct { - MetaXWaylandManager *manager; - MetaWindow *window; - guint32 surface_id; - guint later_id; -} AssociateWindowWithSurfaceOp; - -static void associate_window_with_surface_window_unmanaged (MetaWindow *window, - AssociateWindowWithSurfaceOp *op); -static void -associate_window_with_surface_op_free (AssociateWindowWithSurfaceOp *op) -{ - if (op->later_id != 0) - meta_later_remove (op->later_id); - g_signal_handlers_disconnect_by_func (op->window, - (gpointer) associate_window_with_surface_window_unmanaged, - op); - g_free (op); -} - -static void -associate_window_with_surface_window_unmanaged (MetaWindow *window, - AssociateWindowWithSurfaceOp *op) -{ - associate_window_with_surface_op_free (op); -} - -static gboolean -associate_window_with_surface_later (gpointer user_data) -{ - AssociateWindowWithSurfaceOp *op = user_data; - - op->later_id = 0; - - if (!associate_window_with_surface_id (op->manager, op->window, op->surface_id)) - { - /* Not here? Oh well... nothing we can do */ - g_warning ("Unknown surface ID %d (from window %s)", op->surface_id, op->window->desc); - } - - associate_window_with_surface_op_free (op); - - return G_SOURCE_REMOVE; -} - void meta_xwayland_handle_wl_surface_id (MetaWindow *window, guint32 surface_id) @@ -171,21 +126,11 @@ meta_xwayland_handle_wl_surface_id (MetaWindow *window, if (!associate_window_with_surface_id (manager, window, surface_id)) { - /* No surface ID yet... it should arrive after the next - * iteration through the loop, so queue a later and see - * what happens. + /* No surface ID yet, schedule this association for whenever the + * surface is made known. */ - AssociateWindowWithSurfaceOp *op = g_new0 (AssociateWindowWithSurfaceOp, 1); - op->manager = manager; - op->window = window; - op->surface_id = surface_id; - op->later_id = meta_later_add (META_LATER_BEFORE_REDRAW, - associate_window_with_surface_later, - op, - NULL); - - g_signal_connect (op->window, "unmanaged", - G_CALLBACK (associate_window_with_surface_window_unmanaged), op); + meta_wayland_compositor_schedule_surface_association (compositor, + surface_id, window); } } diff --git a/src/wayland/meta-xwayland.h b/src/wayland/meta-xwayland.h index 5c404a921..6812ce72b 100644 --- a/src/wayland/meta-xwayland.h +++ b/src/wayland/meta-xwayland.h @@ -41,4 +41,8 @@ void meta_xwayland_handle_xwayland_grab (MetaWindow *window, gboolean allow); +void +meta_xwayland_associate_window_with_surface (MetaWindow *window, + MetaWaylandSurface *surface); + #endif /* META_XWAYLAND_H */