Start tablet protocol
This commit is contained in:
parent
4984ea49ee
commit
bf8751d632
|
@ -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',
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue