Start tablet protocol

This commit is contained in:
Markus Ongyerth 2018-04-11 16:17:28 +02:00
parent 4984ea49ee
commit bf8751d632
3 changed files with 220 additions and 0 deletions

View file

@ -33,6 +33,7 @@ protocols = [
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], [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-shell/xdg-shell-unstable-v6.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml'],
'gamma-control.xml', 'gamma-control.xml',
'gtk-primary-selection.xml', 'gtk-primary-selection.xml',
'idle.xml', 'idle.xml',

View file

@ -43,6 +43,7 @@ lib_wlr_types = static_library(
'wlr_screenshooter.c', 'wlr_screenshooter.c',
'wlr_server_decoration.c', 'wlr_server_decoration.c',
'wlr_surface.c', 'wlr_surface.c',
'wlr_tablet_v2.c',
'wlr_tablet_pad.c', 'wlr_tablet_pad.c',
'wlr_tablet_tool.c', 'wlr_tablet_tool.c',
'wlr_touch.c', 'wlr_touch.c',

218
types/wlr_tablet_v2.c Normal file
View file

@ -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;
}