MetaWaylandPointerConstraints: Handle delayed window surface association

For Xwayland, a newly created wl_surface and X11 Window pair may not be
immediately associated, but Xwayland may still request a pointer
constraint on some of its wl_surface's. Handle the situation by
postponing maybe enabling the constraint until the window and surface
has been associated.

https://bugzilla.gnome.org/show_bug.cgi?id=771050
This commit is contained in:
Jonas Ådahl 2016-04-01 21:04:22 +08:00
parent fccdd00f74
commit 262b52da50

View File

@ -34,6 +34,7 @@
#include "meta-wayland-pointer.h" #include "meta-wayland-pointer.h"
#include "meta-wayland-surface.h" #include "meta-wayland-surface.h"
#include "meta-wayland-region.h" #include "meta-wayland-region.h"
#include "meta-xwayland.h"
#include "meta-pointer-lock-wayland.h" #include "meta-pointer-lock-wayland.h"
#include "meta-pointer-confinement-wayland.h" #include "meta-pointer-confinement-wayland.h"
#include "window-private.h" #include "window-private.h"
@ -67,8 +68,13 @@ struct _MetaWaylandPointerConstraint
typedef struct _MetaWaylandSurfacePointerConstraintsData typedef struct _MetaWaylandSurfacePointerConstraintsData
{ {
MetaWaylandSurface *surface;
GList *pointer_constraints; GList *pointer_constraints;
MetaWindow *window; MetaWindow *window;
gulong window_associated_handler_id;
gulong appears_changed_handler_id; gulong appears_changed_handler_id;
gulong raised_handler_id; gulong raised_handler_id;
} MetaWaylandSurfacePointerConstraintsData; } MetaWaylandSurfacePointerConstraintsData;
@ -96,6 +102,9 @@ static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface;
static void static void
meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint); meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint);
static void
meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint);
static void static void
meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window); meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window);
@ -133,16 +142,11 @@ window_raised (MetaWindow *window)
meta_wayland_pointer_constraint_maybe_enable_for_window (window); meta_wayland_pointer_constraint_maybe_enable_for_window (window);
} }
static MetaWaylandSurfacePointerConstraintsData * static void
surface_constraint_data_new (MetaWaylandSurface *surface) connect_window (MetaWaylandSurfacePointerConstraintsData *data,
MetaWindow *window)
{ {
MetaWaylandSurfacePointerConstraintsData *data; data->window = window;
data = g_new0 (MetaWaylandSurfacePointerConstraintsData, 1);
if (surface->window)
{
data->window = surface->window;
g_object_add_weak_pointer (G_OBJECT (data->window), g_object_add_weak_pointer (G_OBJECT (data->window),
(gpointer *) &data->window); (gpointer *) &data->window);
data->appears_changed_handler_id = data->appears_changed_handler_id =
@ -151,6 +155,40 @@ surface_constraint_data_new (MetaWaylandSurface *surface)
data->raised_handler_id = data->raised_handler_id =
g_signal_connect (data->window, "raised", g_signal_connect (data->window, "raised",
G_CALLBACK (window_raised), NULL); G_CALLBACK (window_raised), NULL);
}
static void
window_associated (MetaWaylandSurfaceRole *surface_role,
MetaWaylandSurfacePointerConstraintsData *data)
{
MetaWaylandSurface *surface = data->surface;
connect_window (data, surface->window);
g_signal_handler_disconnect (surface, data->window_associated_handler_id);
data->window_associated_handler_id = 0;
meta_wayland_pointer_constraint_maybe_enable_for_window (surface->window);
}
static MetaWaylandSurfacePointerConstraintsData *
surface_constraint_data_new (MetaWaylandSurface *surface)
{
MetaWaylandSurfacePointerConstraintsData *data;
data = g_new0 (MetaWaylandSurfacePointerConstraintsData, 1);
data->surface = surface;
if (surface->window)
{
connect_window (data, surface->window);
}
else if (meta_xwayland_is_xwayland_surface (surface))
{
data->window_associated_handler_id =
g_signal_connect (surface->role, "window-associated",
G_CALLBACK (window_associated),
data);
} }
else else
{ {
@ -173,12 +211,24 @@ surface_constraint_data_free (MetaWaylandSurfacePointerConstraintsData *data)
g_object_remove_weak_pointer (G_OBJECT (data->window), g_object_remove_weak_pointer (G_OBJECT (data->window),
(gpointer *) &data->window); (gpointer *) &data->window);
} }
else
{
g_signal_handler_disconnect (data->surface->role,
data->window_associated_handler_id);
}
g_list_free_full (data->pointer_constraints, g_list_free_full (data->pointer_constraints,
(GDestroyNotify) meta_wayland_pointer_constraint_destroy); (GDestroyNotify) meta_wayland_pointer_constraint_destroy);
g_free (data); g_free (data);
} }
static void
constrained_surface_destroyed (MetaWaylandSurface *surface,
MetaWaylandSurfacePointerConstraintsData *data)
{
surface_constraint_data_free (data);
}
static MetaWaylandSurfacePointerConstraintsData * static MetaWaylandSurfacePointerConstraintsData *
ensure_surface_constraints_data (MetaWaylandSurface *surface) ensure_surface_constraints_data (MetaWaylandSurface *surface)
{ {
@ -188,10 +238,11 @@ ensure_surface_constraints_data (MetaWaylandSurface *surface)
if (!data) if (!data)
{ {
data = surface_constraint_data_new (surface); data = surface_constraint_data_new (surface);
g_object_set_qdata_full (G_OBJECT (surface), g_object_set_qdata (G_OBJECT (surface),
quark_surface_pointer_constraints_data, quark_surface_pointer_constraints_data,
data, data);
(GDestroyNotify) surface_constraint_data_free); g_signal_connect (surface, "destroy",
G_CALLBACK (constrained_surface_destroyed), data);
} }
return data; return data;
@ -387,7 +438,11 @@ meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *cons
if (!constraint->surface->window) if (!constraint->surface->window)
{ {
g_warn_if_reached (); /*
* Locks from Xwayland may come before we have had the opportunity to
* associate the X11 Window with the wl_surface.
*/
g_warn_if_fail (meta_xwayland_is_xwayland_surface (constraint->surface));
return; return;
} }
@ -454,6 +509,12 @@ meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window)
MetaWaylandSurfacePointerConstraintsData *surface_data; MetaWaylandSurfacePointerConstraintsData *surface_data;
GList *l; GList *l;
if (!surface)
{
g_warn_if_fail (window->client_type == META_WINDOW_CLIENT_TYPE_X11);
return;
}
surface_data = get_surface_constraints_data (surface); surface_data = get_surface_constraints_data (surface);
if (!surface_data) if (!surface_data)
return; return;