From 8df2a1452cf48b724fd3f3e0b72e5175553febe5 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 6 Apr 2018 15:47:50 +0200 Subject: [PATCH] wayland: Notify actively of xwayland window/surface associations Instead of scheduling a meta_later, keep track of the unassociated windows, and look for matches as soon as the MetaWaylandSurface is created on our side. This will ensure the surface is given the Xwayland role before receiving the first wl_surface.commit. --- src/wayland/meta-wayland-private.h | 2 + src/wayland/meta-wayland-surface.c | 2 + src/wayland/meta-wayland.c | 62 ++++++++++++++++++++++++++ src/wayland/meta-wayland.h | 7 +++ src/wayland/meta-xwayland.c | 71 ++++-------------------------- src/wayland/meta-xwayland.h | 4 ++ 6 files changed, 85 insertions(+), 63 deletions(-) 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 */