aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocol/meson.build1
-rw-r--r--types/meson.build1
-rw-r--r--types/wlr_tablet_v2.c218
3 files changed, 220 insertions, 0 deletions
diff --git a/protocol/meson.build b/protocol/meson.build
index 5ab82d84..b7a6e80a 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -33,6 +33,7 @@ protocols = [
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml'],
'gamma-control.xml',
'gtk-primary-selection.xml',
'idle.xml',
diff --git a/types/meson.build b/types/meson.build
index 49f87bf8..a571dffd 100644
--- a/types/meson.build
+++ b/types/meson.build
@@ -43,6 +43,7 @@ lib_wlr_types = static_library(
'wlr_screenshooter.c',
'wlr_server_decoration.c',
'wlr_surface.c',
+ 'wlr_tablet_v2.c',
'wlr_tablet_pad.c',
'wlr_tablet_tool.c',
'wlr_touch.c',
diff --git a/types/wlr_tablet_v2.c b/types/wlr_tablet_v2.c
new file mode 100644
index 00000000..09e0ef35
--- /dev/null
+++ b/types/wlr_tablet_v2.c
@@ -0,0 +1,218 @@
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <wlr/config.h>
+#include <wlr/types/wlr_seat.h>
+
+#include "tablet-unstable-v2-protocol.h"
+
+
+struct wlr_tablet_manager_v2 {
+ struct wl_global *wl_global;
+ struct wl_list clients; // wlr_tablet_client_v2::link
+
+ struct wl_listener display_destroy;
+
+ void *data;
+};
+
+struct wlr_tablet_client_v2 {
+ struct wl_list link;
+ struct wl_client *client;
+ struct wl_resource *resource;
+
+ struct wlr_tablet_manager_v2 *manager;
+
+ struct wl_list tablet_seats; // wlr_tablet_seat_v2::link
+};
+
+struct wlr_tablet_seat_v2 {
+ struct wl_list link;
+ struct wl_resource *resource;
+
+ struct wlr_tablet_client_v2 *client;
+ struct wlr_seat_client *seat;
+
+ struct wl_listener seat_destroy;
+
+ struct wl_list tools;
+};
+
+struct wlr_tablet_v2 {
+ struct wl_list link;
+ struct wl_resource *resource;
+};
+
+void wlr_tablet_v2_destroy(struct wlr_tablet_manager_v2 *manager);
+static struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource);
+
+static void tablet_seat_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static struct zwp_tablet_seat_v2_interface seat_impl = {
+ .destroy = tablet_seat_destroy,
+};
+
+static struct wlr_tablet_seat_v2 *tablet_seat_from_resource (
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource, &zwp_tablet_seat_v2_interface,
+ &seat_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void wlr_tablet_seat_v2_destroy(struct wl_resource *resource) {
+ struct wlr_tablet_seat_v2 *seat = tablet_seat_from_resource(resource);
+
+ seat->resource = NULL;
+ /* We can't just destroy the struct, because we may need to iterate it
+ * on display->destroy/manager_destroy
+ */
+ // TODO: Implement the free() check
+}
+
+static void handle_seat_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_tablet_seat_v2 *seat =
+ wl_container_of(listener, seat, seat_destroy);
+
+ seat->seat = NULL;
+ wl_list_remove(&seat->seat_destroy.link);
+ /* Remove leaves it in a defunct state, we will remove again in the
+ * actual destroy sequence
+ */
+ wl_list_init(&seat->seat_destroy.link);
+}
+
+static void tablet_manager_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static void get_tablet_seat(struct wl_client *wl_client, struct wl_resource *resource,
+ uint32_t id, struct wl_resource *seat_resource)
+{
+ struct wlr_tablet_client_v2 *manager = tablet_client_from_resource(resource);
+ struct wlr_seat_client *seat = wlr_seat_client_from_resource(seat_resource);
+
+ struct wlr_tablet_seat_v2 *tablet_seat =
+ calloc(1, sizeof(struct wlr_tablet_seat_v2));
+ if (tablet_seat == NULL) {
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+
+ tablet_seat->resource =
+ wl_resource_create(wl_client, &zwp_tablet_seat_v2_interface, 1, id);
+ if (tablet_seat->resource == NULL) {
+ free(tablet_seat);
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+
+
+ tablet_seat->seat = seat;
+ tablet_seat->client = manager;
+
+ tablet_seat->seat_destroy.notify = handle_seat_destroy;
+ wl_signal_add(&seat->events.destroy, &tablet_seat->seat_destroy);
+
+ wl_resource_set_implementation(tablet_seat->resource, &seat_impl, tablet_seat,
+ wlr_tablet_seat_v2_destroy);
+ wl_list_insert(&manager->tablet_seats, &tablet_seat->link);
+}
+
+static struct zwp_tablet_manager_v2_interface manager_impl = {
+ .get_tablet_seat = get_tablet_seat,
+ .destroy = tablet_manager_destroy,
+};
+
+static struct wlr_tablet_client_v2 *tablet_client_from_resource (
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource, &zwp_tablet_manager_v2_interface,
+ &manager_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void wlr_tablet_manager_v2_destroy(struct wl_resource *resource) {
+ struct wlr_tablet_client_v2 *client = tablet_client_from_resource(resource);
+
+ client->resource = NULL;
+ /* We can't just destroy the struct, because we may need to iterate it
+ * on display->destroy/manager_destroy
+ */
+ // TODO: Implement the free() check
+}
+
+static void tablet_v2_bind(struct wl_client *wl_client, void *data,
+ uint32_t version, uint32_t id) {
+ struct wlr_tablet_manager_v2 *manager = data;
+ assert(wl_client && manager);
+
+ struct wlr_tablet_client_v2 *client =
+ calloc(1, sizeof(struct wlr_tablet_client_v2));
+ if (client == NULL) {
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+
+ wl_list_init(&client->tablet_seats);
+
+ client->resource =
+ wl_resource_create(wl_client, &zwp_tablet_manager_v2_interface, version, id);
+ if (client->resource == NULL) {
+ free(client);
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+ client->client = wl_client;
+ client->manager = manager;
+
+ wl_resource_set_implementation(client->resource, &manager_impl, client,
+ wlr_tablet_manager_v2_destroy);
+ wl_list_insert(&manager->clients, &client->link);
+}
+
+static void handle_display_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_tablet_manager_v2 *tablet =
+ wl_container_of(listener, tablet, display_destroy);
+ wlr_tablet_v2_destroy(tablet);
+}
+
+void wlr_tablet_v2_destroy(struct wlr_tablet_manager_v2 *manager) {
+ struct wlr_tablet_client_v2 *tmp;
+ struct wlr_tablet_client_v2 *pos;
+
+ wl_list_for_each_safe(pos, tmp, &manager->clients, link) {
+ wl_resource_destroy(pos->resource);
+ }
+
+ wl_global_destroy(manager->wl_global);
+ free(manager);
+}
+
+struct wlr_tablet_manager_v2 *wlr_tablet_v2_create(struct wl_display *display) {
+ struct wlr_tablet_manager_v2 *tablet =
+ calloc(1, sizeof(struct wlr_tablet_manager_v2));
+ if (!tablet) {
+ return NULL;
+ }
+
+ wl_list_init(&tablet->clients);
+
+ tablet->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &tablet->display_destroy);
+
+ tablet->wl_global = wl_global_create(display,
+ &zwp_tablet_manager_v2_interface, 1, tablet, tablet_v2_bind);
+ if (tablet->wl_global == NULL) {
+ free(tablet);
+ return NULL;
+ }
+
+ return tablet;
+}