diff --git a/src/Makefile.am b/src/Makefile.am index 3abe14b56..a805e3b8f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -296,6 +296,8 @@ libmutter_la_SOURCES += \ wayland/meta-wayland-seat.h \ wayland/meta-wayland-tablet.c \ wayland/meta-wayland-tablet.h \ + wayland/meta-wayland-tablet-manager.c \ + wayland/meta-wayland-tablet-manager.h \ wayland/meta-wayland-tablet-seat.c \ wayland/meta-wayland-tablet-seat.h \ wayland/meta-wayland-tablet-tool.c \ diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index 313dc8546..a8c4568d7 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -33,6 +33,7 @@ #include "meta-wayland-surface.h" #include "meta-wayland-seat.h" #include "meta-wayland-pointer-gestures.h" +#include "meta-wayland-tablet-manager.h" typedef struct _MetaXWaylandSelection MetaXWaylandSelection; @@ -69,6 +70,7 @@ struct _MetaWaylandCompositor MetaXWaylandManager xwayland_manager; MetaWaylandSeat *seat; + MetaWaylandTabletManager *tablet_manager; }; #endif /* META_WAYLAND_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-tablet-manager.c b/src/wayland/meta-wayland-tablet-manager.c new file mode 100644 index 000000000..eb7ce427e --- /dev/null +++ b/src/wayland/meta-wayland-tablet-manager.c @@ -0,0 +1,239 @@ +/* + * 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 + */ + +#define _GNU_SOURCE + +#include "config.h" + +#include + +#include +#include "tablet-unstable-v1-server-protocol.h" + +#include "meta-wayland-private.h" +#include "meta-wayland-tablet-manager.h" +#include "meta-wayland-tablet-seat.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_MASTER) + 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); +} + +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_v1_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_v1_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_v1_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) +{ + ClutterDeviceManager *device_manager; + + device_manager = clutter_device_manager_get_default (); + g_signal_handlers_disconnect_by_data (device_manager, 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)) + 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: + 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: + 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); + g_hash_table_insert (manager->seats, seat, tablet_seat); + } + + return tablet_seat; +} diff --git a/src/wayland/meta-wayland-tablet-manager.h b/src/wayland/meta-wayland-tablet-manager.h new file mode 100644 index 000000000..b39d3a973 --- /dev/null +++ b/src/wayland/meta-wayland-tablet-manager.h @@ -0,0 +1,54 @@ +/* + * Wayland Support + * + * Copyright (C) 2015 Red Hat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Carlos Garnacho + */ + +#ifndef META_WAYLAND_TABLET_MANAGER_H +#define META_WAYLAND_TABLET_MANAGER_H + +#include + +#include + +#include "meta-wayland-types.h" + +struct _MetaWaylandTabletManager +{ + MetaWaylandCompositor *compositor; + struct wl_display *wl_display; + struct wl_list resource_list; + + GHashTable *seats; +}; + +void meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor); +void meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager); + +gboolean meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager, + const ClutterEvent *event); +void meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager, + const ClutterEvent *event); +gboolean meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager, + const ClutterEvent *event); + +MetaWaylandTabletSeat * + meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager, + MetaWaylandSeat *seat); + +#endif /* META_WAYLAND_TABLET_MANAGER_H */