summaryrefslogtreecommitdiff
path: root/src/wayland/meta-wayland-pointer-constraints.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wayland/meta-wayland-pointer-constraints.c')
-rw-r--r--src/wayland/meta-wayland-pointer-constraints.c1201
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");
-}