mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
Implement support for the wp_pointer_constraints protocol
The wp_pointer_constraints protocol is a protocol which enables clients to manipulate the behavior of the pointer cursor associated with a seat. Currently available constraints are locking the pointer to a static position, and confining the pointer to a given region. Currently locking is fully implemented, and confining is implemented for rectangular confinement regions. What else is lacking is less troublesome semantics for enabling the lock or confinement; currently the only requirement implemented is that the window that appears focused is the one that may aquire the lock. This means that a pointer could be 'stolen' by creating a new window that receives active focus, or when using focus-follows-mouse, a pointer passes a window that has requested a lock. This semantics can be changed and the protocol itself allows any semantics as seems fit. https://bugzilla.gnome.org/show_bug.cgi?id=744104
This commit is contained in:
parent
e2efc85b08
commit
495c89401a
2
.gitignore
vendored
2
.gitignore
vendored
@ -70,6 +70,8 @@ src/pointer-gestures-unstable-v*-protocol.c
|
|||||||
src/pointer-gestures-unstable-v*-server-protocol.h
|
src/pointer-gestures-unstable-v*-server-protocol.h
|
||||||
src/relative-pointer-unstable-v*-protocol.c
|
src/relative-pointer-unstable-v*-protocol.c
|
||||||
src/relative-pointer-unstable-v*-server-protocol.h
|
src/relative-pointer-unstable-v*-server-protocol.h
|
||||||
|
src/pointer-constraints-unstable-v*-protocol.c
|
||||||
|
src/pointer-constraints-unstable-v*-server-protocol.h
|
||||||
src/meta/meta-version.h
|
src/meta/meta-version.h
|
||||||
doc/reference/*.args
|
doc/reference/*.args
|
||||||
doc/reference/*.bak
|
doc/reference/*.bak
|
||||||
|
@ -53,6 +53,8 @@ mutter_built_sources += \
|
|||||||
xdg-shell-unstable-v5-server-protocol.h \
|
xdg-shell-unstable-v5-server-protocol.h \
|
||||||
relative-pointer-unstable-v1-protocol.c \
|
relative-pointer-unstable-v1-protocol.c \
|
||||||
relative-pointer-unstable-v1-server-protocol.h \
|
relative-pointer-unstable-v1-server-protocol.h \
|
||||||
|
pointer-constraints-unstable-v1-protocol.c \
|
||||||
|
pointer-constraints-unstable-v1-server-protocol.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -86,6 +88,8 @@ libmutter_la_SOURCES = \
|
|||||||
backends/meta-monitor-manager-private.h \
|
backends/meta-monitor-manager-private.h \
|
||||||
backends/meta-monitor-manager-dummy.c \
|
backends/meta-monitor-manager-dummy.c \
|
||||||
backends/meta-monitor-manager-dummy.h \
|
backends/meta-monitor-manager-dummy.h \
|
||||||
|
backends/meta-pointer-constraint.c \
|
||||||
|
backends/meta-pointer-constraint.h \
|
||||||
backends/meta-stage.h \
|
backends/meta-stage.h \
|
||||||
backends/meta-stage.c \
|
backends/meta-stage.c \
|
||||||
backends/edid-parse.c \
|
backends/edid-parse.c \
|
||||||
@ -268,6 +272,12 @@ libmutter_la_SOURCES += \
|
|||||||
wayland/meta-wayland-keyboard.h \
|
wayland/meta-wayland-keyboard.h \
|
||||||
wayland/meta-wayland-pointer.c \
|
wayland/meta-wayland-pointer.c \
|
||||||
wayland/meta-wayland-pointer.h \
|
wayland/meta-wayland-pointer.h \
|
||||||
|
wayland/meta-wayland-pointer-constraints.c \
|
||||||
|
wayland/meta-wayland-pointer-constraints.h \
|
||||||
|
wayland/meta-pointer-lock-wayland.c \
|
||||||
|
wayland/meta-pointer-lock-wayland.h \
|
||||||
|
wayland/meta-pointer-confinement-wayland.c \
|
||||||
|
wayland/meta-pointer-confinement-wayland.h \
|
||||||
wayland/meta-wayland-popup.c \
|
wayland/meta-wayland-popup.c \
|
||||||
wayland/meta-wayland-popup.h \
|
wayland/meta-wayland-popup.h \
|
||||||
wayland/meta-wayland-seat.c \
|
wayland/meta-wayland-seat.c \
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
#include "meta-cursor-renderer.h"
|
#include "meta-cursor-renderer.h"
|
||||||
#include "meta-monitor-manager-private.h"
|
#include "meta-monitor-manager-private.h"
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
#define DEFAULT_XKB_RULES_FILE "evdev"
|
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||||
#define DEFAULT_XKB_MODEL "pc105+inet"
|
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||||
@ -51,6 +52,8 @@ struct _MetaBackend
|
|||||||
|
|
||||||
GHashTable *device_monitors;
|
GHashTable *device_monitors;
|
||||||
gint current_device_id;
|
gint current_device_id;
|
||||||
|
|
||||||
|
MetaPointerConstraint *client_pointer_constraint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaBackendClass
|
struct _MetaBackendClass
|
||||||
@ -124,4 +127,7 @@ gboolean meta_backend_get_relative_motion_deltas (MetaBackend *backend,
|
|||||||
double *dx_unaccel,
|
double *dx_unaccel,
|
||||||
double *dy_unaccel);
|
double *dy_unaccel);
|
||||||
|
|
||||||
|
void meta_backend_set_client_pointer_constraint (MetaBackend *backend,
|
||||||
|
MetaPointerConstraint *constraint);
|
||||||
|
|
||||||
#endif /* META_BACKEND_PRIVATE_H */
|
#endif /* META_BACKEND_PRIVATE_H */
|
||||||
|
@ -571,6 +571,17 @@ meta_backend_get_relative_motion_deltas (MetaBackend *backend,
|
|||||||
dx_unaccel, dy_unaccel);
|
dx_unaccel, dy_unaccel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_backend_set_client_pointer_constraint (MetaBackend *backend,
|
||||||
|
MetaPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
g_assert (!constraint || (constraint && !backend->client_pointer_constraint));
|
||||||
|
|
||||||
|
g_clear_object (&backend->client_pointer_constraint);
|
||||||
|
if (constraint)
|
||||||
|
backend->client_pointer_constraint = g_object_ref (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
static GType
|
static GType
|
||||||
get_backend_type (void)
|
get_backend_type (void)
|
||||||
{
|
{
|
||||||
|
57
src/backends/meta-pointer-constraint.c
Normal file
57
src/backends/meta-pointer-constraint.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaPointerConstraint, meta_pointer_constraint, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_constraint_init (MetaPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
META_POINTER_CONSTRAINT_GET_CLASS (constraint)->constrain (constraint,
|
||||||
|
device,
|
||||||
|
time,
|
||||||
|
prev_x, prev_y,
|
||||||
|
x, y);
|
||||||
|
}
|
60
src/backends/meta-pointer-constraint.h
Normal file
60
src/backends/meta-pointer-constraint.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_POINTER_CONSTRAINT_H
|
||||||
|
#define META_POINTER_CONSTRAINT_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define META_TYPE_POINTER_CONSTRAINT (meta_pointer_constraint_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraint, meta_pointer_constraint,
|
||||||
|
META, POINTER_CONSTRAINT, GObject);
|
||||||
|
|
||||||
|
struct _MetaPointerConstraintClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (*constrain) (MetaPointerConstraint *constraint,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y);
|
||||||
|
};
|
||||||
|
|
||||||
|
void meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* META_POINTER_CONSTRAINT_H */
|
@ -36,6 +36,7 @@
|
|||||||
#include "meta-monitor-manager-kms.h"
|
#include "meta-monitor-manager-kms.h"
|
||||||
#include "meta-cursor-renderer-native.h"
|
#include "meta-cursor-renderer-native.h"
|
||||||
#include "meta-launcher.h"
|
#include "meta-launcher.h"
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -139,6 +140,24 @@ constrain_to_barriers (ClutterInputDevice *device,
|
|||||||
new_x, new_y);
|
new_x, new_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
constrain_to_client_constraint (ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaPointerConstraint *constraint = backend->client_pointer_constraint;
|
||||||
|
|
||||||
|
if (!constraint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_pointer_constraint_constrain (constraint, device,
|
||||||
|
time, prev_x, prev_y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
|
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
|
||||||
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
|
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
|
||||||
@ -207,6 +226,9 @@ pointer_constrain_callback (ClutterInputDevice *device,
|
|||||||
/* Constrain to barriers */
|
/* Constrain to barriers */
|
||||||
constrain_to_barriers (device, time, new_x, new_y);
|
constrain_to_barriers (device, time, new_x, new_y);
|
||||||
|
|
||||||
|
/* Constrain to pointer lock */
|
||||||
|
constrain_to_client_constraint (device, time, prev_x, prev_y, new_x, new_y);
|
||||||
|
|
||||||
monitor_manager = meta_monitor_manager_get ();
|
monitor_manager = meta_monitor_manager_get ();
|
||||||
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
|
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
|
||||||
|
|
||||||
|
200
src/wayland/meta-pointer-confinement-wayland.c
Normal file
200
src/wayland/meta-pointer-confinement-wayland.c
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "wayland/meta-pointer-confinement-wayland.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "wayland/meta-wayland-seat.h"
|
||||||
|
#include "wayland/meta-wayland-pointer.h"
|
||||||
|
#include "wayland/meta-wayland-pointer-constraints.h"
|
||||||
|
#include "wayland/meta-wayland-surface.h"
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
#include "compositor/meta-surface-actor-wayland.h"
|
||||||
|
|
||||||
|
struct _MetaPointerConfinementWayland
|
||||||
|
{
|
||||||
|
MetaPointerConstraint parent;
|
||||||
|
|
||||||
|
MetaWaylandPointerConstraint *constraint;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaPointerConfinementWayland, meta_pointer_confinement_wayland,
|
||||||
|
META_TYPE_POINTER_CONSTRAINT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_confinement_wayland_constrain (MetaPointerConstraint *constraint,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
MetaPointerConfinementWayland *self =
|
||||||
|
META_POINTER_CONFINEMENT_WAYLAND (constraint);
|
||||||
|
MetaWaylandSurface *surface;
|
||||||
|
cairo_region_t *region;
|
||||||
|
cairo_rectangle_int_t extents;
|
||||||
|
float sx, sy;
|
||||||
|
float min_sx, max_sx;
|
||||||
|
float min_sy, max_sy;
|
||||||
|
|
||||||
|
region =
|
||||||
|
meta_wayland_pointer_constraint_calculate_effective_region (self->constraint);
|
||||||
|
cairo_region_get_extents (region, &extents);
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
min_sx = extents.x;
|
||||||
|
max_sx = extents.x + extents.width - 1;
|
||||||
|
max_sy = extents.y + extents.height - 1;
|
||||||
|
min_sy = extents.y;
|
||||||
|
|
||||||
|
surface = meta_wayland_pointer_constraint_get_surface (self->constraint);
|
||||||
|
meta_wayland_surface_get_relative_coordinates (surface, *x, *y, &sx, &sy);
|
||||||
|
|
||||||
|
if (sx < min_sx)
|
||||||
|
sx = min_sx;
|
||||||
|
else if (sx > max_sx)
|
||||||
|
sx = max_sx;
|
||||||
|
|
||||||
|
if (sy < min_sy)
|
||||||
|
sy = min_sy;
|
||||||
|
else if (sy > max_sy)
|
||||||
|
sy = max_sy;
|
||||||
|
|
||||||
|
meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_confinement_wayland_maybe_warp (MetaPointerConfinementWayland *self)
|
||||||
|
{
|
||||||
|
MetaWaylandSeat *seat;
|
||||||
|
MetaWaylandSurface *surface;
|
||||||
|
wl_fixed_t sx;
|
||||||
|
wl_fixed_t sy;
|
||||||
|
cairo_region_t *region;
|
||||||
|
|
||||||
|
seat = meta_wayland_pointer_constraint_get_seat (self->constraint);
|
||||||
|
surface = meta_wayland_pointer_constraint_get_surface (self->constraint);
|
||||||
|
meta_wayland_pointer_get_relative_coordinates (&seat->pointer,
|
||||||
|
surface,
|
||||||
|
&sx, &sy);
|
||||||
|
|
||||||
|
region =
|
||||||
|
meta_wayland_pointer_constraint_calculate_effective_region (self->constraint);
|
||||||
|
|
||||||
|
if (!cairo_region_contains_point (region,
|
||||||
|
wl_fixed_to_int (sx),
|
||||||
|
wl_fixed_to_int (sy)))
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t extents;
|
||||||
|
wl_fixed_t min_sx;
|
||||||
|
wl_fixed_t max_sx;
|
||||||
|
wl_fixed_t max_sy;
|
||||||
|
wl_fixed_t min_sy;
|
||||||
|
gboolean x_changed = TRUE, y_changed = TRUE;
|
||||||
|
|
||||||
|
cairo_region_get_extents (region, &extents);
|
||||||
|
|
||||||
|
min_sx = wl_fixed_from_int (extents.x);
|
||||||
|
max_sx = wl_fixed_from_int (extents.x + extents.width - 1);
|
||||||
|
max_sy = wl_fixed_from_int (extents.y + extents.height - 1);
|
||||||
|
min_sy = wl_fixed_from_int (extents.y);
|
||||||
|
|
||||||
|
if (sx < min_sx)
|
||||||
|
sx = min_sx;
|
||||||
|
else if (sx > max_sx)
|
||||||
|
sx = max_sx;
|
||||||
|
else
|
||||||
|
x_changed = FALSE;
|
||||||
|
|
||||||
|
if (sy < min_sy)
|
||||||
|
sy = min_sy;
|
||||||
|
else if (sy > max_sy)
|
||||||
|
sy = max_sy;
|
||||||
|
else
|
||||||
|
y_changed = FALSE;
|
||||||
|
|
||||||
|
if (x_changed || y_changed)
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
meta_wayland_surface_get_absolute_coordinates (surface,
|
||||||
|
wl_fixed_to_double (sx),
|
||||||
|
wl_fixed_to_double (sy),
|
||||||
|
&x, &y);
|
||||||
|
meta_backend_warp_pointer (meta_get_backend (), (int)x, (int)y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surface_actor_painting (MetaSurfaceActorWayland *surface_actor,
|
||||||
|
MetaPointerConfinementWayland *self)
|
||||||
|
{
|
||||||
|
meta_pointer_confinement_wayland_maybe_warp (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaPointerConstraint *
|
||||||
|
meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
MetaPointerConfinementWayland *confinement;
|
||||||
|
MetaWaylandSurface *surface;
|
||||||
|
|
||||||
|
object = g_object_new (META_TYPE_POINTER_CONFINEMENT_WAYLAND, NULL);
|
||||||
|
confinement = META_POINTER_CONFINEMENT_WAYLAND (object);
|
||||||
|
|
||||||
|
confinement->constraint = constraint;
|
||||||
|
|
||||||
|
surface = meta_wayland_pointer_constraint_get_surface (constraint);
|
||||||
|
g_signal_connect_object (surface->surface_actor,
|
||||||
|
"painting",
|
||||||
|
G_CALLBACK (surface_actor_painting),
|
||||||
|
confinement,
|
||||||
|
0);
|
||||||
|
|
||||||
|
return META_POINTER_CONSTRAINT (confinement);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_confinement_wayland_init (MetaPointerConfinementWayland *confinement_wayland)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_confinement_wayland_class_init (MetaPointerConfinementWaylandClass *klass)
|
||||||
|
{
|
||||||
|
MetaPointerConstraintClass *pointer_constraint_class =
|
||||||
|
META_POINTER_CONSTRAINT_CLASS (klass);
|
||||||
|
|
||||||
|
pointer_constraint_class->constrain = meta_pointer_confinement_wayland_constrain;
|
||||||
|
}
|
45
src/wayland/meta-pointer-confinement-wayland.h
Normal file
45
src/wayland/meta-pointer-confinement-wayland.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_POINTER_CONFINEMENT_WAYLAND_H
|
||||||
|
#define META_POINTER_CONFINEMENT_WAYLAND_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
#include "wayland/meta-wayland-pointer-constraints.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define META_TYPE_POINTER_CONFINEMENT_WAYLAND (meta_pointer_confinement_wayland_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaPointerConfinementWayland,
|
||||||
|
meta_pointer_confinement_wayland,
|
||||||
|
META, POINTER_CONFINEMENT_WAYLAND,
|
||||||
|
MetaPointerConstraint);
|
||||||
|
|
||||||
|
MetaPointerConstraint *meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* META_CONFINEMENT_WAYLAND_H */
|
72
src/wayland/meta-pointer-lock-wayland.c
Normal file
72
src/wayland/meta-pointer-lock-wayland.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "wayland/meta-pointer-lock-wayland.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
|
struct _MetaPointerLockWayland
|
||||||
|
{
|
||||||
|
MetaPointerConstraint parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland,
|
||||||
|
META_TYPE_POINTER_CONSTRAINT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_lock_wayland_constrain (MetaPointerConstraint *constraint,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
guint32 time,
|
||||||
|
float prev_x,
|
||||||
|
float prev_y,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
*x = prev_x;
|
||||||
|
*y = prev_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaPointerConstraint *
|
||||||
|
meta_pointer_lock_wayland_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (META_TYPE_POINTER_LOCK_WAYLAND, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_lock_wayland_init (MetaPointerLockWayland *lock_wayland)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_pointer_lock_wayland_class_init (MetaPointerLockWaylandClass *klass)
|
||||||
|
{
|
||||||
|
MetaPointerConstraintClass *pointer_constraint_class =
|
||||||
|
META_POINTER_CONSTRAINT_CLASS (klass);
|
||||||
|
|
||||||
|
pointer_constraint_class->constrain = meta_pointer_lock_wayland_constrain;
|
||||||
|
}
|
42
src/wayland/meta-pointer-lock-wayland.h
Normal file
42
src/wayland/meta-pointer-lock-wayland.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_POINTER_LOCK_WAYLAND_H
|
||||||
|
#define META_POINTER_LOCK_WAYLAND_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define META_TYPE_POINTER_LOCK_WAYLAND (meta_pointer_lock_wayland_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland,
|
||||||
|
META, POINTER_LOCK_WAYLAND, MetaPointerConstraint);
|
||||||
|
|
||||||
|
MetaPointerConstraint *meta_pointer_lock_wayland_new (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* META_LOCK_WAYLAND_H */
|
818
src/wayland/meta-wayland-pointer-constraints.c
Normal file
818
src/wayland/meta-wayland-pointer-constraints.c
Normal file
@ -0,0 +1,818 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "meta-wayland-pointer-constraints.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "meta/meta-backend.h"
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
|
#include "meta-wayland-seat.h"
|
||||||
|
#include "meta-wayland-pointer.h"
|
||||||
|
#include "meta-wayland-surface.h"
|
||||||
|
#include "meta-wayland-region.h"
|
||||||
|
#include "meta-pointer-lock-wayland.h"
|
||||||
|
#include "meta-pointer-confinement-wayland.h"
|
||||||
|
#include "window-private.h"
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/native/meta-backend-native.h"
|
||||||
|
#include "backends/meta-pointer-constraint.h"
|
||||||
|
|
||||||
|
#include "pointer-constraints-unstable-v1-server-protocol.h"
|
||||||
|
|
||||||
|
static GQuark quark_pending_constraint_state = 0;
|
||||||
|
|
||||||
|
struct _MetaWaylandPointerConstraint
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
MetaWaylandSurface *surface;
|
||||||
|
gboolean is_enabled;
|
||||||
|
cairo_region_t *region;
|
||||||
|
struct wl_resource *resource;
|
||||||
|
MetaWaylandPointerGrab grab;
|
||||||
|
MetaWaylandSeat *seat;
|
||||||
|
enum zwp_pointer_constraints_v1_lifetime lifetime;
|
||||||
|
|
||||||
|
gboolean hint_set;
|
||||||
|
wl_fixed_t x_hint;
|
||||||
|
wl_fixed_t y_hint;
|
||||||
|
|
||||||
|
MetaPointerConstraint *constraint;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint;
|
||||||
|
cairo_region_t *region;
|
||||||
|
gulong applied_handler_id;
|
||||||
|
} MetaWaylandPendingConstraintState;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GList *pending_constraint_states;
|
||||||
|
} MetaWaylandPendingConstraintStateContainer;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaWaylandPointerConstraint, meta_wayland_pointer_constraint,
|
||||||
|
G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static const struct zwp_locked_pointer_v1_interface locked_pointer_interface;
|
||||||
|
static const struct zwp_confined_pointer_v1_interface confined_pointer_interface;
|
||||||
|
static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface;
|
||||||
|
static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface;
|
||||||
|
|
||||||
|
static cairo_region_t *
|
||||||
|
create_infinite_constraint_region (void)
|
||||||
|
{
|
||||||
|
return cairo_region_create_rectangle (&(cairo_rectangle_int_t) {
|
||||||
|
.x = INT_MIN / 2,
|
||||||
|
.y = INT_MIN / 2,
|
||||||
|
.width = INT_MAX,
|
||||||
|
.height = INT_MAX,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandPointerConstraint *
|
||||||
|
meta_wayland_pointer_constraint_new (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandSeat *seat,
|
||||||
|
MetaWaylandRegion *region,
|
||||||
|
enum zwp_pointer_constraints_v1_lifetime lifetime,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
const MetaWaylandPointerGrabInterface *grab_interface)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint;
|
||||||
|
|
||||||
|
constraint = g_object_new (META_TYPE_WAYLAND_POINTER_CONSTRAINT, NULL);
|
||||||
|
if (!constraint)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
constraint->surface = surface;
|
||||||
|
constraint->seat = seat;
|
||||||
|
constraint->lifetime = lifetime;
|
||||||
|
constraint->resource = resource;
|
||||||
|
constraint->grab.interface = grab_interface;
|
||||||
|
|
||||||
|
if (region)
|
||||||
|
{
|
||||||
|
constraint->region =
|
||||||
|
cairo_region_copy (meta_wayland_region_peek_cairo_region (region));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
constraint->region = create_infinite_constraint_region ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_wayland_pointer_constraint_is_enabled (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
return constraint->is_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_notify_activated (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
struct wl_resource *resource = constraint->resource;
|
||||||
|
|
||||||
|
if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_locked_pointer_v1_interface,
|
||||||
|
&locked_pointer_interface))
|
||||||
|
{
|
||||||
|
zwp_locked_pointer_v1_send_locked (resource);
|
||||||
|
}
|
||||||
|
else if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_confined_pointer_v1_interface,
|
||||||
|
&confined_pointer_interface))
|
||||||
|
{
|
||||||
|
zwp_confined_pointer_v1_send_confined (resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_notify_deactivated (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
struct wl_resource *resource = constraint->resource;
|
||||||
|
|
||||||
|
if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_locked_pointer_v1_interface,
|
||||||
|
&locked_pointer_interface))
|
||||||
|
zwp_locked_pointer_v1_send_unlocked (resource);
|
||||||
|
else if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_confined_pointer_v1_interface,
|
||||||
|
&confined_pointer_interface))
|
||||||
|
zwp_confined_pointer_v1_send_unconfined (resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaPointerConstraint *
|
||||||
|
meta_wayland_pointer_constraint_create_pointer_constraint (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
struct wl_resource *resource = constraint->resource;
|
||||||
|
|
||||||
|
if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_locked_pointer_v1_interface,
|
||||||
|
&locked_pointer_interface))
|
||||||
|
{
|
||||||
|
return meta_pointer_lock_wayland_new ();
|
||||||
|
}
|
||||||
|
else if (wl_resource_instance_of (resource,
|
||||||
|
&zwp_confined_pointer_v1_interface,
|
||||||
|
&confined_pointer_interface))
|
||||||
|
{
|
||||||
|
return meta_pointer_confinement_wayland_new (constraint);
|
||||||
|
}
|
||||||
|
g_assert_not_reached ();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_enable (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
|
||||||
|
g_assert (!constraint->is_enabled);
|
||||||
|
|
||||||
|
constraint->is_enabled = TRUE;
|
||||||
|
meta_wayland_pointer_constraint_notify_activated (constraint);
|
||||||
|
meta_wayland_pointer_start_grab (&constraint->seat->pointer,
|
||||||
|
&constraint->grab);
|
||||||
|
|
||||||
|
constraint->constraint =
|
||||||
|
meta_wayland_pointer_constraint_create_pointer_constraint (constraint);
|
||||||
|
meta_backend_set_client_pointer_constraint (backend, constraint->constraint);
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (constraint->constraint),
|
||||||
|
(gpointer *) &constraint->constraint);
|
||||||
|
g_object_unref (constraint->constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_disable (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
meta_wayland_pointer_constraint_notify_deactivated (constraint);
|
||||||
|
meta_wayland_pointer_end_grab (constraint->grab.pointer);
|
||||||
|
meta_backend_set_client_pointer_constraint (meta_get_backend (), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
if (meta_wayland_pointer_constraint_is_enabled (constraint))
|
||||||
|
meta_wayland_pointer_constraint_disable (constraint);
|
||||||
|
|
||||||
|
wl_resource_set_user_data (constraint->resource, NULL);
|
||||||
|
cairo_region_destroy (constraint->region);
|
||||||
|
g_object_unref (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_within_constraint_region (MetaWaylandPointerConstraint *constraint,
|
||||||
|
wl_fixed_t sx,
|
||||||
|
wl_fixed_t sy)
|
||||||
|
{
|
||||||
|
cairo_region_t *region;
|
||||||
|
gboolean is_within;
|
||||||
|
|
||||||
|
region = meta_wayland_pointer_constraint_calculate_effective_region (constraint);
|
||||||
|
is_within = cairo_region_contains_point (constraint->region,
|
||||||
|
wl_fixed_to_int (sx),
|
||||||
|
wl_fixed_to_int (sy));
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
return is_within;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
MetaWaylandSeat *seat = constraint->seat;
|
||||||
|
wl_fixed_t sx, sy;
|
||||||
|
|
||||||
|
if (constraint->is_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (seat->keyboard.focus_surface != constraint->surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_wayland_pointer_get_relative_coordinates (&constraint->seat->pointer,
|
||||||
|
constraint->surface,
|
||||||
|
&sx, &sy);
|
||||||
|
if (!is_within_constraint_region (constraint, sx, sy))
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_enable (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_remove (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
MetaWaylandSurface *surface = constraint->surface;
|
||||||
|
|
||||||
|
meta_wayland_surface_remove_pointer_constraint (surface, constraint);
|
||||||
|
meta_wayland_pointer_constraint_destroy (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat,
|
||||||
|
MetaWindow *focus_window)
|
||||||
|
{
|
||||||
|
MetaWaylandPointer *pointer = &seat->pointer;
|
||||||
|
|
||||||
|
if ((pointer->grab->interface == &confined_pointer_grab_interface ||
|
||||||
|
pointer->grab->interface == &locked_pointer_grab_interface) &&
|
||||||
|
pointer->focus_surface &&
|
||||||
|
pointer->focus_surface->window != focus_window)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_container_of (pointer->grab, constraint, grab);
|
||||||
|
|
||||||
|
switch (constraint->lifetime)
|
||||||
|
{
|
||||||
|
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
|
||||||
|
meta_wayland_pointer_constraint_remove (constraint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
|
||||||
|
meta_wayland_pointer_constraint_disable (constraint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window)
|
||||||
|
{
|
||||||
|
MetaWaylandSurface *surface = window->surface;
|
||||||
|
GList *it;
|
||||||
|
|
||||||
|
for (it = surface->pointer_constraints; it; it = it->next)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint = it->data;
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_maybe_enable (constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWaylandSeat *
|
||||||
|
meta_wayland_pointer_constraint_get_seat (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
return constraint->seat;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_region_t *
|
||||||
|
meta_wayland_pointer_constraint_calculate_effective_region (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
cairo_region_t *region;
|
||||||
|
|
||||||
|
region = cairo_region_copy (constraint->surface->input_region);
|
||||||
|
cairo_region_intersect (region, constraint->region);
|
||||||
|
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_region_t *
|
||||||
|
meta_wayland_pointer_constraint_get_region (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
return constraint->region;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWaylandSurface *
|
||||||
|
meta_wayland_pointer_constraint_get_surface (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
return constraint->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_constraint_resource_destroyed (struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
if (!constraint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_remove (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_constraint_state_free (MetaWaylandPendingConstraintState *constraint_pending)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&constraint_pending->region, cairo_region_destroy);
|
||||||
|
if (constraint_pending->constraint)
|
||||||
|
g_object_remove_weak_pointer (G_OBJECT (constraint_pending->constraint),
|
||||||
|
(gpointer *) &constraint_pending->constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandPendingConstraintStateContainer *
|
||||||
|
get_pending_constraint_state_container (MetaWaylandPendingState *pending)
|
||||||
|
{
|
||||||
|
return g_object_get_qdata (G_OBJECT (pending),
|
||||||
|
quark_pending_constraint_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandPendingConstraintState *
|
||||||
|
get_pending_constraint_state (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingState *pending = constraint->surface->pending;
|
||||||
|
MetaWaylandPendingConstraintStateContainer *container;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
container = get_pending_constraint_state_container (pending);
|
||||||
|
for (l = container->pending_constraint_states; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingConstraintState *constraint_pending = l->data;
|
||||||
|
|
||||||
|
if (constraint_pending->constraint == constraint)
|
||||||
|
return constraint_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_constraint_state_container_free (MetaWaylandPendingConstraintStateContainer *container)
|
||||||
|
{
|
||||||
|
g_list_free_full (container->pending_constraint_states,
|
||||||
|
(GDestroyNotify) pending_constraint_state_free);
|
||||||
|
g_free (container);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandPendingConstraintStateContainer *
|
||||||
|
ensure_pending_constraint_state_container (MetaWaylandPendingState *pending)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingConstraintStateContainer *container;
|
||||||
|
|
||||||
|
container = get_pending_constraint_state_container (pending);
|
||||||
|
if (!container)
|
||||||
|
{
|
||||||
|
container = g_new0 (MetaWaylandPendingConstraintStateContainer, 1);
|
||||||
|
g_object_set_qdata_full (G_OBJECT (pending),
|
||||||
|
quark_pending_constraint_state,
|
||||||
|
container,
|
||||||
|
(GDestroyNotify) pending_constraint_state_container_free);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
remove_pending_constraint_state (MetaWaylandPointerConstraint *constraint,
|
||||||
|
MetaWaylandPendingState *pending)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingConstraintStateContainer *container;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
container = get_pending_constraint_state_container (pending);
|
||||||
|
for (l = container->pending_constraint_states; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingConstraintState *constraint_pending = l->data;
|
||||||
|
if (constraint_pending->constraint != constraint)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pending_constraint_state_free (l->data);
|
||||||
|
container->pending_constraint_states =
|
||||||
|
g_list_remove_link (container->pending_constraint_states, l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_constraint_state_applied (MetaWaylandPendingState *pending,
|
||||||
|
MetaWaylandPendingConstraintState *constraint_pending)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint = constraint_pending->constraint;
|
||||||
|
|
||||||
|
if (!constraint)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_clear_pointer (&constraint->region, cairo_region_destroy);
|
||||||
|
if (constraint_pending->region)
|
||||||
|
{
|
||||||
|
constraint->region = constraint_pending->region;
|
||||||
|
constraint_pending->region = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
constraint->region = create_infinite_constraint_region ();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_handler_disconnect (pending,
|
||||||
|
constraint_pending->applied_handler_id);
|
||||||
|
remove_pending_constraint_state (constraint, pending);
|
||||||
|
|
||||||
|
/* The pointer is potentially warped by the actor paint signal callback if
|
||||||
|
* the new region proved it necessary.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWaylandPendingConstraintState *
|
||||||
|
ensure_pending_constraint_state (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingState *pending = constraint->surface->pending;
|
||||||
|
MetaWaylandPendingConstraintStateContainer *container;
|
||||||
|
MetaWaylandPendingConstraintState *constraint_pending;
|
||||||
|
|
||||||
|
container = ensure_pending_constraint_state_container (pending);
|
||||||
|
constraint_pending = get_pending_constraint_state (constraint);
|
||||||
|
if (!constraint_pending)
|
||||||
|
{
|
||||||
|
constraint_pending = g_new0 (MetaWaylandPendingConstraintState, 1);
|
||||||
|
constraint_pending->constraint = constraint;
|
||||||
|
constraint_pending->applied_handler_id =
|
||||||
|
g_signal_connect (pending, "applied",
|
||||||
|
G_CALLBACK (pending_constraint_state_applied),
|
||||||
|
constraint_pending);
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (constraint),
|
||||||
|
(gpointer *) &constraint_pending->constraint);
|
||||||
|
|
||||||
|
container->pending_constraint_states =
|
||||||
|
g_list_append (container->pending_constraint_states,
|
||||||
|
constraint_pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
return constraint_pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_set_pending_region (MetaWaylandPointerConstraint *constraint,
|
||||||
|
MetaWaylandRegion *region)
|
||||||
|
{
|
||||||
|
MetaWaylandPendingConstraintState *constraint_pending;
|
||||||
|
|
||||||
|
constraint_pending = ensure_pending_constraint_state (constraint);
|
||||||
|
|
||||||
|
g_clear_pointer (&constraint_pending->region, cairo_region_destroy);
|
||||||
|
if (region)
|
||||||
|
{
|
||||||
|
constraint_pending->region =
|
||||||
|
cairo_region_copy (meta_wayland_region_peek_cairo_region (region));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_pointer_constraint (struct wl_resource *resource,
|
||||||
|
uint32_t id,
|
||||||
|
MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandSeat *seat,
|
||||||
|
MetaWaylandRegion *region,
|
||||||
|
enum zwp_pointer_constraints_v1_lifetime lifetime,
|
||||||
|
const struct wl_interface *interface,
|
||||||
|
const void *implementation,
|
||||||
|
const MetaWaylandPointerGrabInterface *grab_interface)
|
||||||
|
{
|
||||||
|
struct wl_client *client = wl_resource_get_client (resource);
|
||||||
|
struct wl_resource *cr;
|
||||||
|
MetaWaylandPointerConstraint *constraint;
|
||||||
|
|
||||||
|
if (meta_wayland_surface_get_pointer_constraint_for_seat (surface, seat))
|
||||||
|
{
|
||||||
|
wl_resource_post_error (resource,
|
||||||
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||||
|
"the pointer as already requested to be "
|
||||||
|
"locked or confined on that surface");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cr = wl_resource_create (client, interface,
|
||||||
|
wl_resource_get_version (resource),
|
||||||
|
id);
|
||||||
|
if (cr == NULL)
|
||||||
|
{
|
||||||
|
wl_client_post_no_memory (client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint = meta_wayland_pointer_constraint_new (surface, seat,
|
||||||
|
region,
|
||||||
|
lifetime,
|
||||||
|
cr, grab_interface);
|
||||||
|
if (constraint == NULL)
|
||||||
|
{
|
||||||
|
wl_client_post_no_memory (client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_wayland_surface_add_pointer_constraint (surface, constraint);
|
||||||
|
|
||||||
|
wl_resource_set_implementation (cr, implementation, constraint,
|
||||||
|
pointer_constraint_resource_destroyed);
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_maybe_enable (constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_destroy (struct wl_client *client,
|
||||||
|
struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_resource_get_user_data (resource);
|
||||||
|
gboolean warp_pointer = FALSE;
|
||||||
|
int warp_x, warp_y;
|
||||||
|
|
||||||
|
if (constraint && constraint->is_enabled && constraint->hint_set &&
|
||||||
|
is_within_constraint_region (constraint,
|
||||||
|
constraint->x_hint,
|
||||||
|
constraint->y_hint))
|
||||||
|
{
|
||||||
|
float sx, sy;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
sx = (float)wl_fixed_to_double (constraint->x_hint);
|
||||||
|
sy = (float)wl_fixed_to_double (constraint->y_hint);
|
||||||
|
meta_wayland_surface_get_absolute_coordinates (constraint->surface,
|
||||||
|
sx, sy,
|
||||||
|
&x, &y);
|
||||||
|
warp_pointer = TRUE;
|
||||||
|
warp_x = (int) x;
|
||||||
|
warp_y = (int) y;
|
||||||
|
}
|
||||||
|
wl_resource_destroy (resource);
|
||||||
|
|
||||||
|
if (warp_pointer)
|
||||||
|
meta_backend_warp_pointer (meta_get_backend (), warp_x, warp_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_set_cursor_position_hint (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
wl_fixed_t surface_x,
|
||||||
|
wl_fixed_t surface_y)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
/* Ignore a set cursor hint that was already sent after the constraint
|
||||||
|
* was cancelled. */
|
||||||
|
if (!constraint->resource || constraint->resource != resource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
constraint->hint_set = TRUE;
|
||||||
|
constraint->x_hint = surface_x;
|
||||||
|
constraint->y_hint = surface_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_set_region (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_resource *region_resource)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_resource_get_user_data (resource);
|
||||||
|
MetaWaylandRegion *region =
|
||||||
|
region_resource ? wl_resource_get_user_data (region_resource) : NULL;
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_set_pending_region (constraint, region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = {
|
||||||
|
locked_pointer_destroy,
|
||||||
|
locked_pointer_set_cursor_position_hint,
|
||||||
|
locked_pointer_set_region,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_grab_pointer_focus (MetaWaylandPointerGrab *grab,
|
||||||
|
MetaWaylandSurface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_grab_pointer_motion (MetaWaylandPointerGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
meta_wayland_pointer_send_relative_motion (grab->pointer, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
locked_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
meta_wayland_pointer_send_button (grab->pointer, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface = {
|
||||||
|
locked_pointer_grab_pointer_focus,
|
||||||
|
locked_pointer_grab_pointer_motion,
|
||||||
|
locked_pointer_grab_pointer_button,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_constraints_destroy (struct wl_client *client,
|
||||||
|
struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy (resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_constraints_lock_pointer (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t id,
|
||||||
|
struct wl_resource *surface_resource,
|
||||||
|
struct wl_resource *pointer_resource,
|
||||||
|
struct wl_resource *region_resource,
|
||||||
|
uint32_t lifetime)
|
||||||
|
{
|
||||||
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||||
|
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
|
||||||
|
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||||
|
MetaWaylandRegion *region =
|
||||||
|
region_resource ? wl_resource_get_user_data (region_resource) : NULL;
|
||||||
|
|
||||||
|
init_pointer_constraint (resource, id, surface, seat, region, lifetime,
|
||||||
|
&zwp_locked_pointer_v1_interface,
|
||||||
|
&locked_pointer_interface,
|
||||||
|
&locked_pointer_grab_interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
confined_pointer_grab_pointer_focus (MetaWaylandPointerGrab *grab,
|
||||||
|
MetaWaylandSurface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
confined_pointer_grab_pointer_motion (MetaWaylandPointerGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_container_of (grab, constraint, grab);
|
||||||
|
MetaWaylandPointer *pointer = grab->pointer;
|
||||||
|
|
||||||
|
g_assert (pointer->focus_surface);
|
||||||
|
g_assert (pointer->focus_surface == constraint->surface);
|
||||||
|
|
||||||
|
meta_wayland_pointer_send_motion (pointer, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
confined_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab,
|
||||||
|
const ClutterEvent *event)
|
||||||
|
{
|
||||||
|
meta_wayland_pointer_send_button (grab->pointer, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface = {
|
||||||
|
confined_pointer_grab_pointer_focus,
|
||||||
|
confined_pointer_grab_pointer_motion,
|
||||||
|
confined_pointer_grab_pointer_button,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
confined_pointer_destroy (struct wl_client *client,
|
||||||
|
struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
wl_resource_destroy (resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
confined_pointer_set_region (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_resource *region_resource)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint =
|
||||||
|
wl_resource_get_user_data (resource);
|
||||||
|
MetaWaylandRegion *region =
|
||||||
|
region_resource ? wl_resource_get_user_data (region_resource) : NULL;
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_set_pending_region (constraint, region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = {
|
||||||
|
confined_pointer_destroy,
|
||||||
|
confined_pointer_set_region,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
pointer_constraints_confine_pointer (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t id,
|
||||||
|
struct wl_resource *surface_resource,
|
||||||
|
struct wl_resource *pointer_resource,
|
||||||
|
struct wl_resource *region_resource,
|
||||||
|
uint32_t lifetime)
|
||||||
|
{
|
||||||
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||||
|
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
|
||||||
|
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||||
|
MetaWaylandRegion *region =
|
||||||
|
region_resource ? wl_resource_get_user_data (region_resource) : NULL;
|
||||||
|
|
||||||
|
init_pointer_constraint (resource, id, surface, seat, region, lifetime,
|
||||||
|
&zwp_confined_pointer_v1_interface,
|
||||||
|
&confined_pointer_interface,
|
||||||
|
&confined_pointer_grab_interface);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_pointer_constraints_v1_interface pointer_constraints = {
|
||||||
|
pointer_constraints_destroy,
|
||||||
|
pointer_constraints_lock_pointer,
|
||||||
|
pointer_constraints_confine_pointer,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
bind_pointer_constraints (struct wl_client *client,
|
||||||
|
void *data,
|
||||||
|
uint32_t version,
|
||||||
|
uint32_t id)
|
||||||
|
{
|
||||||
|
MetaWaylandCompositor *compositor = data;
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
resource = wl_resource_create (client,
|
||||||
|
&zwp_pointer_constraints_v1_interface,
|
||||||
|
1, id);
|
||||||
|
|
||||||
|
wl_resource_set_implementation (resource,
|
||||||
|
&pointer_constraints,
|
||||||
|
compositor,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_constraints_init (MetaWaylandCompositor *compositor)
|
||||||
|
{
|
||||||
|
if (!wl_global_create (compositor->wayland_display,
|
||||||
|
&zwp_pointer_constraints_v1_interface, 1,
|
||||||
|
compositor, bind_pointer_constraints))
|
||||||
|
g_error ("Could not create wp_pointer_constraints global");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_init (MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_pointer_constraint_class_init (MetaWaylandPointerConstraintClass *klass)
|
||||||
|
{
|
||||||
|
quark_pending_constraint_state =
|
||||||
|
g_quark_from_static_string ("-meta-wayland-pointer-constraint-pending_state");
|
||||||
|
}
|
60
src/wayland/meta-wayland-pointer-constraints.h
Normal file
60
src/wayland/meta-wayland-pointer-constraints.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Red Hat
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by:
|
||||||
|
* Jonas Ådahl <jadahl@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_WAYLAND_POINTER_CONSTRAINTS_H
|
||||||
|
#define META_WAYLAND_POINTER_CONSTRAINTS_H
|
||||||
|
|
||||||
|
#include "meta-wayland-types.h"
|
||||||
|
#include "meta/window.h"
|
||||||
|
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
|
#define META_TYPE_WAYLAND_POINTER_CONSTRAINT (meta_wayland_pointer_constraint_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaWaylandPointerConstraint,
|
||||||
|
meta_wayland_pointer_constraint,
|
||||||
|
META, WAYLAND_POINTER_CONSTRAINT,
|
||||||
|
GObject);
|
||||||
|
|
||||||
|
typedef struct _MetaWaylandPointerConstraint MetaWaylandPointerConstraint;
|
||||||
|
|
||||||
|
void meta_wayland_pointer_constraints_init (MetaWaylandCompositor *compositor);
|
||||||
|
|
||||||
|
void meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
void meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
MetaWaylandSeat * meta_wayland_pointer_constraint_get_seat (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
cairo_region_t * meta_wayland_pointer_constraint_calculate_effective_region (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
cairo_region_t * meta_wayland_pointer_constraint_get_region (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
MetaWaylandSurface * meta_wayland_pointer_constraint_get_surface (MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
void meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat,
|
||||||
|
MetaWindow *focus_window);
|
||||||
|
|
||||||
|
void meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window);
|
||||||
|
|
||||||
|
#endif /* META_WAYLAND_POINTER_CONSTRAINTS_H */
|
@ -273,7 +273,7 @@ meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer,
|
meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer,
|
||||||
const ClutterEvent *event)
|
const ClutterEvent *event)
|
||||||
{
|
{
|
||||||
@ -1249,6 +1249,13 @@ meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor)
|
|||||||
g_error ("Could not create relative pointer manager global");
|
g_error ("Could not create relative pointer manager global");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaWaylandSeat *
|
||||||
|
meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
|
||||||
|
{
|
||||||
|
MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer);
|
||||||
|
return seat;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "meta-wayland-pointer-gesture-swipe.h"
|
#include "meta-wayland-pointer-gesture-swipe.h"
|
||||||
#include "meta-wayland-pointer-gesture-pinch.h"
|
#include "meta-wayland-pointer-gesture-pinch.h"
|
||||||
#include "meta-wayland-surface.h"
|
#include "meta-wayland-surface.h"
|
||||||
|
#include "meta-wayland-pointer-constraints.h"
|
||||||
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
#include <meta/meta-cursor-tracker.h>
|
||||||
|
|
||||||
@ -102,6 +103,9 @@ gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
|
|||||||
void meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
|
void meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
|
||||||
const ClutterEvent *event);
|
const ClutterEvent *event);
|
||||||
|
|
||||||
|
void meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer,
|
||||||
|
const ClutterEvent *event);
|
||||||
|
|
||||||
void meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
|
void meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
|
||||||
const ClutterEvent *event);
|
const ClutterEvent *event);
|
||||||
|
|
||||||
@ -145,4 +149,6 @@ void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *re
|
|||||||
|
|
||||||
void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor);
|
void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor);
|
||||||
|
|
||||||
|
MetaWaylandSeat *meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer);
|
||||||
|
|
||||||
#endif /* META_WAYLAND_POINTER_H */
|
#endif /* META_WAYLAND_POINTER_H */
|
||||||
|
@ -55,6 +55,14 @@
|
|||||||
#include "meta-surface-actor-wayland.h"
|
#include "meta-surface-actor-wayland.h"
|
||||||
#include "meta-xwayland-private.h"
|
#include "meta-xwayland-private.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PENDING_STATE_SIGNAL_APPLIED,
|
||||||
|
|
||||||
|
PENDING_STATE_SIGNAL_LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint pending_state_signals[PENDING_STATE_SIGNAL_LAST_SIGNAL];
|
||||||
|
|
||||||
typedef struct _MetaWaylandSurfaceRolePrivate
|
typedef struct _MetaWaylandSurfaceRolePrivate
|
||||||
{
|
{
|
||||||
MetaWaylandSurface *surface;
|
MetaWaylandSurface *surface;
|
||||||
@ -516,6 +524,14 @@ meta_wayland_pending_state_class_init (MetaWaylandPendingStateClass *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->finalize = meta_wayland_pending_state_finalize;
|
object_class->finalize = meta_wayland_pending_state_finalize;
|
||||||
|
|
||||||
|
pending_state_signals[PENDING_STATE_SIGNAL_APPLIED] =
|
||||||
|
g_signal_new ("applied",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -689,6 +705,10 @@ apply_pending_state (MetaWaylandSurface *surface,
|
|||||||
wl_list_init (&pending->frame_callback_list);
|
wl_list_init (&pending->frame_callback_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_signal_emit (pending,
|
||||||
|
pending_state_signals[PENDING_STATE_SIGNAL_APPLIED],
|
||||||
|
0);
|
||||||
|
|
||||||
meta_surface_actor_wayland_sync_state (
|
meta_surface_actor_wayland_sync_state (
|
||||||
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
|
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
|
||||||
|
|
||||||
@ -1072,6 +1092,9 @@ wl_surface_destructor (struct wl_resource *resource)
|
|||||||
if (surface->window)
|
if (surface->window)
|
||||||
destroy_window (surface);
|
destroy_window (surface);
|
||||||
|
|
||||||
|
g_list_free_full (surface->pointer_constraints,
|
||||||
|
(GDestroyNotify) meta_wayland_pointer_constraint_destroy);
|
||||||
|
|
||||||
surface_set_buffer (surface, NULL);
|
surface_set_buffer (surface, NULL);
|
||||||
g_clear_object (&surface->pending);
|
g_clear_object (&surface->pending);
|
||||||
|
|
||||||
@ -2468,6 +2491,39 @@ meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_surface_add_pointer_constraint (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
surface->pointer_constraints = g_list_append (surface->pointer_constraints,
|
||||||
|
constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_surface_remove_pointer_constraint (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandPointerConstraint *constraint)
|
||||||
|
{
|
||||||
|
surface->pointer_constraints = g_list_remove (surface->pointer_constraints,
|
||||||
|
constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWaylandPointerConstraint *
|
||||||
|
meta_wayland_surface_get_pointer_constraint_for_seat (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandSeat *seat)
|
||||||
|
{
|
||||||
|
GList *iter;
|
||||||
|
|
||||||
|
for (iter = surface->pointer_constraints; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
MetaWaylandPointerConstraint *constraint = iter->data;
|
||||||
|
|
||||||
|
if (seat == meta_wayland_pointer_constraint_get_seat (constraint))
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
||||||
float abs_x,
|
float abs_x,
|
||||||
@ -2483,6 +2539,27 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
|||||||
*sy /= surface->scale;
|
*sy /= surface->scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
||||||
|
float sx,
|
||||||
|
float sy,
|
||||||
|
float *x,
|
||||||
|
float *y)
|
||||||
|
{
|
||||||
|
ClutterActor *actor =
|
||||||
|
CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor));
|
||||||
|
ClutterVertex sv = {
|
||||||
|
.x = sx * surface->scale,
|
||||||
|
.y = sy * surface->scale,
|
||||||
|
};
|
||||||
|
ClutterVertex v = { 0 };
|
||||||
|
|
||||||
|
clutter_actor_apply_relative_transform_to_point (actor, NULL, &sv, &v);
|
||||||
|
|
||||||
|
*x = v.x;
|
||||||
|
*y = v.y;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_surface_init (MetaWaylandSurface *surface)
|
meta_wayland_surface_init (MetaWaylandSurface *surface)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "meta-wayland-types.h"
|
#include "meta-wayland-types.h"
|
||||||
#include "meta-surface-actor.h"
|
#include "meta-surface-actor.h"
|
||||||
#include "backends/meta-monitor-manager-private.h"
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
|
#include "meta-wayland-pointer-constraints.h"
|
||||||
|
|
||||||
typedef struct _MetaWaylandPendingState MetaWaylandPendingState;
|
typedef struct _MetaWaylandPendingState MetaWaylandPendingState;
|
||||||
|
|
||||||
@ -217,6 +218,8 @@ struct _MetaWaylandSurface
|
|||||||
gboolean pending_pos;
|
gboolean pending_pos;
|
||||||
GSList *pending_placement_ops;
|
GSList *pending_placement_ops;
|
||||||
} sub;
|
} sub;
|
||||||
|
|
||||||
|
GList *pointer_constraints;
|
||||||
};
|
};
|
||||||
|
|
||||||
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
|
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
|
||||||
@ -261,12 +264,27 @@ void meta_wayland_surface_queue_pending_frame_callbacks (MetaWayl
|
|||||||
void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
|
void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
|
||||||
MetaWaylandPendingState *pending);
|
MetaWaylandPendingState *pending);
|
||||||
|
|
||||||
|
void meta_wayland_surface_add_pointer_constraint (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandPointerConstraint *constraint);
|
||||||
|
|
||||||
|
void meta_wayland_surface_remove_pointer_constraint (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandPointerConstraint *constraint);
|
||||||
|
MetaWaylandPointerConstraint *
|
||||||
|
meta_wayland_surface_get_pointer_constraint_for_seat (MetaWaylandSurface *surface,
|
||||||
|
MetaWaylandSeat *seat);
|
||||||
|
|
||||||
void meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
void meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
||||||
float abs_x,
|
float abs_x,
|
||||||
float abs_y,
|
float abs_y,
|
||||||
float *sx,
|
float *sx,
|
||||||
float *sy);
|
float *sy);
|
||||||
|
|
||||||
|
void meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
||||||
|
float sx,
|
||||||
|
float sy,
|
||||||
|
float *x,
|
||||||
|
float *y);
|
||||||
|
|
||||||
MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role);
|
MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -329,6 +329,7 @@ meta_wayland_init (void)
|
|||||||
meta_wayland_pointer_gestures_init (compositor);
|
meta_wayland_pointer_gestures_init (compositor);
|
||||||
meta_wayland_seat_init (compositor);
|
meta_wayland_seat_init (compositor);
|
||||||
meta_wayland_relative_pointer_init (compositor);
|
meta_wayland_relative_pointer_init (compositor);
|
||||||
|
meta_wayland_pointer_constraints_init (compositor);
|
||||||
|
|
||||||
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
|
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
|
||||||
g_error ("Failed to start X Wayland");
|
g_error ("Failed to start X Wayland");
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "window-private.h"
|
#include "window-private.h"
|
||||||
#include "boxes-private.h"
|
#include "boxes-private.h"
|
||||||
#include "stack-tracker.h"
|
#include "stack-tracker.h"
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
#include "meta-wayland-surface.h"
|
#include "meta-wayland-surface.h"
|
||||||
#include "compositor/meta-surface-actor-wayland.h"
|
#include "compositor/meta-surface-actor-wayland.h"
|
||||||
|
|
||||||
@ -402,6 +403,11 @@ appears_focused_changed (GObject *object,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaWindow *window = META_WINDOW (object);
|
MetaWindow *window = META_WINDOW (object);
|
||||||
|
MetaWaylandCompositor *wayland_compositor;
|
||||||
|
|
||||||
|
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||||
|
meta_wayland_pointer_constraint_maybe_remove_for_seat (wayland_compositor->seat,
|
||||||
|
window);
|
||||||
|
|
||||||
/* When we're unmanaging, we remove focus from the window,
|
/* When we're unmanaging, we remove focus from the window,
|
||||||
* causing this to fire. Don't do anything in that case. */
|
* causing this to fire. Don't do anything in that case. */
|
||||||
@ -409,6 +415,8 @@ appears_focused_changed (GObject *object,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
surface_state_changed (window);
|
surface_state_changed (window);
|
||||||
|
|
||||||
|
meta_wayland_pointer_constraint_maybe_enable_for_window (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user