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.
This commit is contained in:
Carlos Garnacho 2018-04-06 15:47:50 +02:00
parent b12c92e206
commit 8df2a1452c
6 changed files with 85 additions and 63 deletions

View File

@ -72,6 +72,8 @@ struct _MetaWaylandCompositor
MetaWaylandSeat *seat; MetaWaylandSeat *seat;
MetaWaylandTabletManager *tablet_manager; MetaWaylandTabletManager *tablet_manager;
GHashTable *scheduled_surface_associations;
}; };
#endif /* META_WAYLAND_PRIVATE_H */ #endif /* META_WAYLAND_PRIVATE_H */

View File

@ -1322,6 +1322,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL); surface->outputs_to_destroy_notify_id = g_hash_table_new (NULL, NULL);
surface->shortcut_inhibited_seats = 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; return surface;
} }

View File

@ -46,6 +46,7 @@
#include "meta-wayland-inhibit-shortcuts.h" #include "meta-wayland-inhibit-shortcuts.h"
#include "meta-wayland-inhibit-shortcuts-dialog.h" #include "meta-wayland-inhibit-shortcuts-dialog.h"
#include "meta-xwayland-grab-keyboard.h" #include "meta-xwayland-grab-keyboard.h"
#include "meta-xwayland.h"
static MetaWaylandCompositor _meta_wayland_compositor; static MetaWaylandCompositor _meta_wayland_compositor;
static char *_display_name_override; static char *_display_name_override;
@ -306,6 +307,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
{ {
memset (compositor, 0, sizeof (MetaWaylandCompositor)); memset (compositor, 0, sizeof (MetaWaylandCompositor));
wl_list_init (&compositor->frame_callbacks); wl_list_init (&compositor->frame_callbacks);
compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL);
} }
void void
@ -482,3 +485,62 @@ meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor)
{ {
wl_display_flush_clients (compositor->wayland_display); 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);
}
}

View File

@ -65,5 +65,12 @@ gboolean meta_wayland_compositor_is_shortcuts_inhibited (MetaWayl
void meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor); 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 #endif

View File

@ -60,8 +60,8 @@ G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
meta_wayland_surface_role_xwayland, meta_wayland_surface_role_xwayland,
META_TYPE_WAYLAND_ACTOR_SURFACE) META_TYPE_WAYLAND_ACTOR_SURFACE)
static void void
associate_window_with_surface (MetaWindow *window, meta_xwayland_associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface) MetaWaylandSurface *surface)
{ {
MetaDisplay *display = window->display; MetaDisplay *display = window->display;
@ -110,58 +110,13 @@ associate_window_with_surface_id (MetaXWaylandManager *manager,
if (resource) if (resource)
{ {
MetaWaylandSurface *surface = wl_resource_get_user_data (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; return TRUE;
} }
else else
return FALSE; 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 void
meta_xwayland_handle_wl_surface_id (MetaWindow *window, meta_xwayland_handle_wl_surface_id (MetaWindow *window,
guint32 surface_id) 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)) if (!associate_window_with_surface_id (manager, window, surface_id))
{ {
/* No surface ID yet... it should arrive after the next /* No surface ID yet, schedule this association for whenever the
* iteration through the loop, so queue a later and see * surface is made known.
* what happens.
*/ */
AssociateWindowWithSurfaceOp *op = g_new0 (AssociateWindowWithSurfaceOp, 1); meta_wayland_compositor_schedule_surface_association (compositor,
op->manager = manager; surface_id, window);
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);
} }
} }

View File

@ -41,4 +41,8 @@ void
meta_xwayland_handle_xwayland_grab (MetaWindow *window, meta_xwayland_handle_xwayland_grab (MetaWindow *window,
gboolean allow); gboolean allow);
void
meta_xwayland_associate_window_with_surface (MetaWindow *window,
MetaWaylandSurface *surface);
#endif /* META_XWAYLAND_H */ #endif /* META_XWAYLAND_H */