mutter/src/wayland/meta-wayland-tablet-manager.c
Carlos Garnacho 00cbcb7ba1 core: Centralize cursor renderer and tracker updates
These use now more of a "pull" model, where they receive update
notifications and the relevant input position is queried, instead
of the coordinates being passed along.

This allows to treat cursor renderers all the same independently
of the device they track. This notifying of position changes should
ideally be more backend-y than core-y, a better location will be
figured out in future commits.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>
2020-11-27 15:14:33 +00:00

245 lines
7.5 KiB
C

/*
* Wayland Support
*
* 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include <glib.h>
#include <wayland-server.h>
#include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-tablet-manager.h"
#include "wayland/meta-wayland-tablet-seat.h"
#include "wayland/meta-wayland-tablet-tool.h"
#include "tablet-unstable-v2-server-protocol.h"
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static gboolean
is_tablet_device (ClutterInputDevice *device)
{
ClutterInputDeviceType device_type;
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL)
return FALSE;
device_type = clutter_input_device_get_device_type (device);
return (device_type == CLUTTER_TABLET_DEVICE ||
device_type == CLUTTER_PEN_DEVICE ||
device_type == CLUTTER_ERASER_DEVICE ||
device_type == CLUTTER_CURSOR_DEVICE ||
device_type == CLUTTER_PAD_DEVICE);
}
static void
tablet_manager_get_tablet_seat (struct wl_client *client,
struct wl_resource *resource,
guint32 id,
struct wl_resource *seat_resource)
{
MetaWaylandTabletManager *tablet_manager = wl_resource_get_user_data (resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandTabletSeat *tablet_seat;
tablet_seat = meta_wayland_tablet_manager_ensure_seat (tablet_manager, seat);
meta_wayland_tablet_seat_create_new_resource (tablet_seat, client,
resource, id);
}
static void
tablet_manager_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zwp_tablet_manager_v2_interface tablet_manager_interface = {
tablet_manager_get_tablet_seat,
tablet_manager_destroy
};
static void
bind_tablet_manager (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
MetaWaylandCompositor *compositor = data;
MetaWaylandTabletManager *tablet_manager = compositor->tablet_manager;
struct wl_resource *resource;
resource = wl_resource_create (client, &zwp_tablet_manager_v2_interface,
MIN (version, 1), id);
wl_resource_set_implementation (resource, &tablet_manager_interface,
tablet_manager, unbind_resource);
wl_resource_set_user_data (resource, tablet_manager);
wl_list_insert (&tablet_manager->resource_list,
wl_resource_get_link (resource));
}
static MetaWaylandTabletManager *
meta_wayland_tablet_manager_new (MetaWaylandCompositor *compositor)
{
MetaWaylandTabletManager *tablet_manager;
tablet_manager = g_slice_new0 (MetaWaylandTabletManager);
tablet_manager->compositor = compositor;
tablet_manager->wl_display = compositor->wayland_display;
tablet_manager->seats = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) meta_wayland_tablet_seat_free);
wl_list_init (&tablet_manager->resource_list);
wl_global_create (tablet_manager->wl_display,
&zwp_tablet_manager_v2_interface, 1,
compositor, bind_tablet_manager);
return tablet_manager;
}
void
meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor)
{
compositor->tablet_manager = meta_wayland_tablet_manager_new (compositor);
}
void
meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager)
{
g_hash_table_destroy (tablet_manager->seats);
g_slice_free (MetaWaylandTabletManager, tablet_manager);
}
static MetaWaylandTabletSeat *
meta_wayland_tablet_manager_lookup_seat (MetaWaylandTabletManager *manager,
ClutterInputDevice *device)
{
MetaWaylandTabletSeat *tablet_seat;
MetaWaylandSeat *seat;
GHashTableIter iter;
if (!device || !is_tablet_device (device))
return NULL;
g_hash_table_iter_init (&iter, manager->seats);
while (g_hash_table_iter_next (&iter, (gpointer*) &seat, (gpointer*) &tablet_seat))
{
if (meta_wayland_tablet_seat_lookup_tablet (tablet_seat, device) ||
meta_wayland_tablet_seat_lookup_pad (tablet_seat, device))
return tablet_seat;
}
return NULL;
}
gboolean
meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager,
const ClutterEvent *event)
{
ClutterInputDevice *device = clutter_event_get_source_device (event);
return meta_wayland_tablet_manager_lookup_seat (manager, device) != NULL;
}
void
meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager,
const ClutterEvent *event)
{
ClutterInputDevice *device = clutter_event_get_source_device (event);
MetaWaylandTabletSeat *tablet_seat;
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
if (!tablet_seat)
return;
switch (event->type)
{
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_MOTION:
case CLUTTER_PAD_BUTTON_PRESS:
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_RING:
case CLUTTER_PAD_STRIP:
meta_wayland_tablet_seat_update (tablet_seat, event);
break;
default:
break;
}
}
gboolean
meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager,
const ClutterEvent *event)
{
ClutterInputDevice *device = clutter_event_get_source_device (event);
MetaWaylandTabletSeat *tablet_seat;
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
if (!tablet_seat)
return CLUTTER_EVENT_PROPAGATE;
switch (event->type)
{
case CLUTTER_PROXIMITY_IN:
case CLUTTER_PROXIMITY_OUT:
case CLUTTER_BUTTON_PRESS:
case CLUTTER_BUTTON_RELEASE:
case CLUTTER_MOTION:
case CLUTTER_PAD_BUTTON_PRESS:
case CLUTTER_PAD_BUTTON_RELEASE:
case CLUTTER_PAD_RING:
case CLUTTER_PAD_STRIP:
return meta_wayland_tablet_seat_handle_event (tablet_seat, event);
default:
return CLUTTER_EVENT_PROPAGATE;
}
}
MetaWaylandTabletSeat *
meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
MetaWaylandSeat *seat)
{
MetaWaylandTabletSeat *tablet_seat;
tablet_seat = g_hash_table_lookup (manager->seats, seat);
if (!tablet_seat)
{
tablet_seat = meta_wayland_tablet_seat_new (manager, seat);
g_hash_table_insert (manager->seats, seat, tablet_seat);
}
return tablet_seat;
}