diff options
Diffstat (limited to 'src/wayland/meta-wayland-pointer-constraints.c')
-rw-r--r-- | src/wayland/meta-wayland-pointer-constraints.c | 1201 |
1 files changed, 0 insertions, 1201 deletions
diff --git a/src/wayland/meta-wayland-pointer-constraints.c b/src/wayland/meta-wayland-pointer-constraints.c deleted file mode 100644 index 965b95dda..000000000 --- a/src/wayland/meta-wayland-pointer-constraints.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* -*- 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-wayland-pointer-constraints.h" - -#include <glib.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-pointer-constraint.h" -#include "core/frame.h" -#include "core/window-private.h" -#include "meta/meta-backend.h" -#include "wayland/meta-pointer-confinement-wayland.h" -#include "wayland/meta-pointer-lock-wayland.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-region.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-xwayland.h" - -#include "pointer-constraints-unstable-v1-server-protocol.h" - -static GQuark quark_pending_constraint_state = 0; -static GQuark quark_surface_pointer_constraints_data = 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; - gulong pointer_focus_surface_handler_id; - - gboolean hint_set; - wl_fixed_t x_hint; - wl_fixed_t y_hint; - - MetaPointerConfinementWayland *confinement; -}; - -typedef struct _MetaWaylandSurfacePointerConstraintsData -{ - MetaWaylandSurface *surface; - - GList *pointer_constraints; - - MetaWindow *window; - gulong window_associated_handler_id; - - gulong appears_changed_handler_id; - gulong raised_handler_id; -} MetaWaylandSurfacePointerConstraintsData; - -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 void -meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint); - -static void -meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint); - -static void -meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window); - -static void -meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat, - MetaWindow *window); - -static MetaWaylandSurfacePointerConstraintsData * -get_surface_constraints_data (MetaWaylandSurface *surface) -{ - return g_object_get_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data); -} - -static void -appears_focused_changed (MetaWindow *window, - GParamSpec *pspec, - gpointer user_data) -{ - MetaWaylandCompositor *wayland_compositor; - - wayland_compositor = meta_wayland_compositor_get_default (); - meta_wayland_pointer_constraint_maybe_remove_for_seat (wayland_compositor->seat, - window); - - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static void -window_raised (MetaWindow *window) -{ - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static void -connect_window (MetaWaylandSurfacePointerConstraintsData *data, - MetaWindow *window) -{ - data->window = window; - g_object_add_weak_pointer (G_OBJECT (data->window), - (gpointer *) &data->window); - data->appears_changed_handler_id = - g_signal_connect (data->window, "notify::appears-focused", - G_CALLBACK (appears_focused_changed), NULL); - data->raised_handler_id = - g_signal_connect (data->window, "raised", - G_CALLBACK (window_raised), NULL); -} - -static void -window_associated (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfacePointerConstraintsData *data) -{ - MetaWaylandSurface *surface = data->surface; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - connect_window (data, window); - g_clear_signal_handler (&data->window_associated_handler_id, surface); - - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static MetaWaylandSurfacePointerConstraintsData * -surface_constraint_data_new (MetaWaylandSurface *surface) -{ - MetaWaylandSurfacePointerConstraintsData *data; - MetaWindow *window; - - data = g_new0 (MetaWaylandSurfacePointerConstraintsData, 1); - - data->surface = surface; - - window = meta_wayland_surface_get_window (surface); - if (window) - { - connect_window (data, 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 - { - /* TODO: Support constraints on non-toplevel windows, such as subsurfaces. - */ - g_warn_if_reached (); - } - - return data; -} -static void -surface_constraint_data_free (MetaWaylandSurfacePointerConstraintsData *data) -{ - if (data->window) - { - g_clear_signal_handler (&data->appears_changed_handler_id, data->window); - g_clear_signal_handler (&data->raised_handler_id, data->window); - g_object_remove_weak_pointer (G_OBJECT (data->window), - (gpointer *) &data->window); - } - else - { - g_clear_signal_handler (&data->window_associated_handler_id, - data->surface->role); - } - - g_list_free_full (data->pointer_constraints, - (GDestroyNotify) meta_wayland_pointer_constraint_destroy); - g_free (data); -} - -static void -constrained_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandSurfacePointerConstraintsData *data) -{ - surface_constraint_data_free (data); -} - -static MetaWaylandSurfacePointerConstraintsData * -ensure_surface_constraints_data (MetaWaylandSurface *surface) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = get_surface_constraints_data (surface); - if (!data) - { - data = surface_constraint_data_new (surface); - g_object_set_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data, - data); - g_signal_connect (surface, "destroy", - G_CALLBACK (constrained_surface_destroyed), data); - } - - return data; -} - -static void -surface_add_pointer_constraint (MetaWaylandSurface *surface, - MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = ensure_surface_constraints_data (surface); - data->pointer_constraints = g_list_append (data->pointer_constraints, - constraint); -} - -static void -surface_remove_pointer_constraints (MetaWaylandSurface *surface, - MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = get_surface_constraints_data (surface); - data->pointer_constraints = - g_list_remove (data->pointer_constraints, constraint); - - if (!data->pointer_constraints) - { - g_object_set_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data, - NULL); - } -} - -static void -pointer_focus_surface_changed (MetaWaylandPointer *pointer, - MetaWaylandPointerConstraint *constraint) -{ - MetaWindow *window; - - window = meta_wayland_surface_get_window (constraint->surface); - if (window) - { - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - - meta_wayland_pointer_constraint_maybe_remove_for_seat (seat, window); - } - - meta_wayland_pointer_constraint_maybe_enable (constraint); -} - -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 = NULL; - } - - constraint->pointer_focus_surface_handler_id = - g_signal_connect (seat->pointer, "focus-surface-changed", - G_CALLBACK (pointer_focus_surface_changed), - constraint); - - 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 MetaPointerConfinementWayland * -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 (constraint); - } - 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) -{ - 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->confinement = - meta_wayland_pointer_constraint_create_pointer_constraint (constraint); - meta_pointer_confinement_wayland_enable (constraint->confinement); - g_object_add_weak_pointer (G_OBJECT (constraint->confinement), - (gpointer *) &constraint->confinement); -} - -static void -meta_wayland_pointer_constraint_disable (MetaWaylandPointerConstraint *constraint) -{ - constraint->is_enabled = FALSE; - - if (constraint->confinement) - { - meta_pointer_confinement_wayland_disable (constraint->confinement); - g_object_unref (constraint->confinement); - } - - meta_wayland_pointer_constraint_notify_deactivated (constraint); - meta_wayland_pointer_end_grab (constraint->grab.pointer); -} - -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); - g_clear_pointer (&constraint->region, cairo_region_destroy); - 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 (region, - wl_fixed_to_int (sx), - wl_fixed_to_int (sy)); - cairo_region_destroy (region); - - return is_within; -} - -static gboolean -should_constraint_be_enabled (MetaWaylandPointerConstraint *constraint) -{ - MetaWindow *window; - - window = meta_wayland_surface_get_window (constraint->surface); - if (!window) - { - /* - * 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 FALSE; - } - - if (window->unmanaging) - return FALSE; - - if (constraint->seat->pointer->focus_surface != constraint->surface) - return FALSE; - - if (meta_xwayland_is_xwayland_surface (constraint->surface)) - { - MetaDisplay *display = meta_get_display (); - - /* - * We need to handle Xwayland surfaces differently in order to allow - * Xwayland to be able to lock the pointer. For example, we cannot require - * the locked window to "appear focused" because the surface Xwayland - * locks might not be able to appear focused (for example it may be a - * override redirect window). - * - * Since we don't have any way to know what focused window an override - * redirect is associated with, nor have a way to know if the override - * redirect window even shares the same connection as a focused window, - * we simply can only really restrict it to enable the lock if any - * Xwayland window appears focused. - */ - - if (display->focus_window && - display->focus_window->client_type != META_WINDOW_CLIENT_TYPE_X11) - return FALSE; - } - else - { - if (!meta_window_appears_focused (window)) - return FALSE; - } - - return TRUE; -} - -static void -meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint) -{ - wl_fixed_t sx, sy; - - if (constraint->is_enabled) - return; - - if (!should_constraint_be_enabled (constraint)) - 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; - - surface_remove_pointer_constraints (surface, constraint); - meta_wayland_pointer_constraint_destroy (constraint); -} - -static void -meta_wayland_pointer_constraint_deactivate (MetaWaylandPointerConstraint *constraint) -{ - 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_remove_for_seat (MetaWaylandSeat *seat, - MetaWindow *window) -{ - MetaWaylandPointer *pointer = seat->pointer; - MetaWaylandPointerConstraint *constraint; - - if ((pointer->grab->interface != &confined_pointer_grab_interface && - pointer->grab->interface != &locked_pointer_grab_interface)) - return; - - constraint = wl_container_of (pointer->grab, constraint, grab); - - if (should_constraint_be_enabled (constraint)) - return; - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static void -meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window) -{ - MetaWaylandSurface *surface = window->surface; - MetaWaylandSurfacePointerConstraintsData *surface_data; - GList *l; - - if (!surface) - { - g_warn_if_fail (window->client_type == META_WINDOW_CLIENT_TYPE_X11); - return; - } - - surface_data = get_surface_constraints_data (surface); - if (!surface_data) - return; - - for (l = surface_data->pointer_constraints; l; l = l->next) - { - MetaWaylandPointerConstraint *constraint = l->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; - MetaWindow *window; - - region = meta_wayland_surface_calculate_input_region (constraint->surface); - if (constraint->region) - cairo_region_intersect (region, constraint->region); - - window = meta_wayland_surface_get_window (constraint->surface); - if (window && window->frame) - { - MetaFrame *frame = window->frame; - int actual_width, actual_height; - - g_assert (meta_xwayland_is_xwayland_surface (constraint->surface)); - - actual_width = window->buffer_rect.width - (frame->child_x + - frame->right_width); - actual_height = window->buffer_rect.height - (frame->child_y + - frame->bottom_height); - if (actual_width > 0 && actual_height > 0) - { - cairo_region_intersect_rectangle (region, &(cairo_rectangle_int_t) { - .x = frame->child_x, - .y = frame->child_y, - .width = actual_width, - .height = actual_height - }); - } - } - - return 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 (MetaWaylandSurfaceState *pending) -{ - return g_object_get_qdata (G_OBJECT (pending), - quark_pending_constraint_state); -} - -static MetaWaylandPendingConstraintState * -get_pending_constraint_state (MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfaceState *pending; - MetaWaylandPendingConstraintStateContainer *container; - GList *l; - - pending = meta_wayland_surface_get_pending_state (constraint->surface); - 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 (MetaWaylandSurfaceState *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, - MetaWaylandSurfaceState *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 (MetaWaylandSurfaceState *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 = NULL; - } - - g_clear_signal_handler (&constraint_pending->applied_handler_id, pending); - 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) -{ - MetaWaylandSurfaceState *pending; - MetaWaylandPendingConstraintStateContainer *container; - MetaWaylandPendingConstraintState *constraint_pending; - - pending = meta_wayland_surface_get_pending_state (constraint->surface); - 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 MetaWaylandPointerConstraint * -get_pointer_constraint_for_seat (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - MetaWaylandSurfacePointerConstraintsData *surface_data; - GList *l; - - surface_data = get_surface_constraints_data (surface); - if (!surface_data) - return NULL; - - for (l = surface_data->pointer_constraints; l; l = l->next) - { - MetaWaylandPointerConstraint *constraint = l->data; - - if (seat == constraint->seat) - return constraint; - } - - return NULL; -} - -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 (get_pointer_constraint_for_seat (surface, seat)) - { - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "the pointer was 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; - } - - switch (lifetime) - { - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT: - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT: - break; - - default: - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "Invalid constraint lifetime"); - return; - } - - constraint = meta_wayland_pointer_constraint_new (surface, seat, - region, - lifetime, - cr, grab_interface); - if (constraint == NULL) - { - wl_client_post_no_memory (client); - return; - } - - 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) - { - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - clutter_seat_warp_pointer (seat, 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 || !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; - - if (!constraint) - return; - - 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); - meta_wayland_pointer_broadcast_frame (grab->pointer); -} - -static void -locked_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - meta_wayland_pointer_send_button (grab->pointer, event); -} - -static void -locked_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab) -{ - MetaWaylandPointerConstraint *constraint = - wl_container_of (grab, constraint, grab); - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface = { - locked_pointer_grab_pointer_focus, - locked_pointer_grab_pointer_motion, - locked_pointer_grab_pointer_button, - locked_pointer_grab_pointer_cancel, -}; - -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 void -confined_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab) -{ - MetaWaylandPointerConstraint *constraint = - wl_container_of (grab, constraint, grab); - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface = { - confined_pointer_grab_pointer_focus, - confined_pointer_grab_pointer_motion, - confined_pointer_grab_pointer_button, - confined_pointer_grab_pointer_cancel, -}; - -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; - - if (!constraint) - return; - - 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); -} - -static void -meta_wayland_pointer_constraint_finalize (GObject *object) -{ - MetaWaylandPointerConstraint *constraint = - META_WAYLAND_POINTER_CONSTRAINT (object); - - g_clear_signal_handler (&constraint->pointer_focus_surface_handler_id, - constraint->seat->pointer); - - G_OBJECT_CLASS (meta_wayland_pointer_constraint_parent_class)->finalize (object); -} - -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) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_pointer_constraint_finalize; - - quark_pending_constraint_state = - g_quark_from_static_string ("-meta-wayland-pointer-constraint-pending_state"); - quark_surface_pointer_constraints_data = - g_quark_from_static_string ("-meta-wayland-surface-constraints-data"); -} |