mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 18:40:40 -05:00
201 lines
6.2 KiB
C
201 lines
6.2 KiB
C
|
/* -*- 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;
|
||
|
}
|