From 539c5a6c95a66cfd8b26352a3fb11b86d63a3866 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Fri, 13 Aug 2021 18:18:34 +0300 Subject: [PATCH] simple-touch: Convert to xdg-shell wl_shell is officially deprecated so remove support for it and instead add support for xdg-shell. With it, we've further: - moved out the buffer handling into its own a distinct structure in case we might want to do multi-buffer rendering - perform a redraw after we have receiving the initial configure event, as to draw to working area where to user can use it for receving touch events Additionally we are setting an appid in case one might want to use it in tandem with kiosk-shell as to be able to place it on a distinct/different output. Signed-off-by: Marius Vlad --- clients/meson.build | 2 + clients/simple-touch.c | 177 ++++++++++++++++++++++++++++++----------- 2 files changed, 134 insertions(+), 45 deletions(-) diff --git a/clients/meson.build b/clients/meson.build index 2c016b84..0d75e5fe 100644 --- a/clients/meson.build +++ b/clients/meson.build @@ -119,6 +119,8 @@ simple_clients = [ 'name': 'touch', 'sources': [ 'simple-touch.c', + xdg_shell_client_protocol_h, + xdg_shell_protocol_c, ], 'dep_objs': [ dep_wayland_client, dep_libshared ] }, diff --git a/clients/simple-touch.c b/clients/simple-touch.c index 385188c3..0f550c4a 100644 --- a/clients/simple-touch.c +++ b/clients/simple-touch.c @@ -1,6 +1,7 @@ /* * Copyright © 2011 Benjamin Franzke * Copyright © 2011 Intel Corporation + * Copyright © 2021 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -33,38 +34,52 @@ #include #include #include +#include #include #include "shared/helpers.h" +#include "shared/xalloc.h" #include "shared/os-compatibility.h" +#include "xdg-shell-client-protocol.h" + struct seat { struct touch *touch; struct wl_seat *seat; struct wl_touch *wl_touch; }; +struct buffer { + struct wl_buffer *buffer; + void *data; +}; + struct touch { struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; - struct wl_shell *shell; + struct xdg_wm_base *wm_base; struct wl_shm *shm; - struct wl_pointer *pointer; - struct wl_keyboard *keyboard; struct wl_surface *surface; - struct wl_shell_surface *shell_surface; - struct wl_buffer *buffer; - int has_argb; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + struct buffer *buffer; + bool has_argb; int width, height; - void *data; + bool wait_for_configure; }; -static void +static struct buffer * create_shm_buffer(struct touch *touch) { struct wl_shm_pool *pool; int fd, size, stride; + void *data; + struct buffer *buffer = NULL; + + buffer = zalloc(sizeof(*buffer)); + if (!buffer) + return NULL; stride = touch->width * 4; size = stride * touch->height; @@ -76,22 +91,44 @@ create_shm_buffer(struct touch *touch) exit(1); } - touch->data = - mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (touch->data == MAP_FAILED) { + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { fprintf(stderr, "mmap failed: %s\n", strerror(errno)); close(fd); - exit(1); + return NULL; } pool = wl_shm_create_pool(touch->shm, fd, size); - touch->buffer = + buffer->buffer = wl_shm_pool_create_buffer(pool, 0, touch->width, touch->height, stride, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + buffer->data = data; close(fd); + + return buffer; +} + +static void +initial_redraw(void *data) +{ + struct touch *touch = data; + struct buffer *buffer = NULL; + + buffer = create_shm_buffer(touch); + assert(buffer); + + touch->buffer = buffer; + + /* paint the "work-area" */ + memset(buffer->data, 64, touch->width * touch->height * 4); + + wl_surface_attach(touch->surface, buffer->buffer, 0, 0); + wl_surface_damage(touch->surface, 0, 0, touch->width, touch->height); + wl_surface_commit(touch->surface); } static void @@ -130,7 +167,7 @@ touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id) y < 2 || y >= touch->height - 2) return; - p = (uint32_t *) touch->data + (x - 2) + (y - 2) * touch->width; + p = ((uint32_t *) touch->buffer->data) + (x - 2) + (y - 2) * touch->width; p[2] = c; p += touch->width; p[1] = c; @@ -149,7 +186,7 @@ touch_paint(struct touch *touch, int32_t x, int32_t y, int32_t id) p += touch->width; p[2] = c; - wl_surface_attach(touch->surface, touch->buffer, 0, 0); + wl_surface_attach(touch->surface, touch->buffer->buffer, 0, 0); wl_surface_damage(touch->surface, x - 2, y - 2, 5, 5); /* todo: We could queue up more damage before committing, if there * are more input events to handle. @@ -241,27 +278,31 @@ add_seat(struct touch *touch, uint32_t name, uint32_t version) } static void -handle_ping(void *data, struct wl_shell_surface *shell_surface, - uint32_t serial) +handle_xdg_surface_configure(void *data, struct xdg_surface *surface, + uint32_t serial) { - wl_shell_surface_pong(shell_surface, serial); -} + struct touch *touch = data; -static void -handle_configure(void *data, struct wl_shell_surface *shell_surface, - uint32_t edges, int32_t width, int32_t height) -{ + xdg_surface_ack_configure(surface, serial); + + if (touch->wait_for_configure) { + initial_redraw(touch); + touch->wait_for_configure = false; + } } +static const struct xdg_surface_listener xdg_surface_listener = { + handle_xdg_surface_configure, +}; + static void -handle_popup_done(void *data, struct wl_shell_surface *shell_surface) +xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { + xdg_wm_base_pong(shell, serial); } -static const struct wl_shell_surface_listener shell_surface_listener = { - handle_ping, - handle_configure, - handle_popup_done +static const struct xdg_wm_base_listener wm_base_listener = { + xdg_wm_base_ping, }; static void @@ -274,10 +315,12 @@ handle_global(void *data, struct wl_registry *registry, touch->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); - } else if (strcmp(interface, "wl_shell") == 0) { - touch->shell = + } else if (strcmp(interface, "xdg_wm_base") == 0) { + touch->wm_base = wl_registry_bind(registry, name, - &wl_shell_interface, 1); + &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(touch->wm_base, + &wm_base_listener, touch); } else if (strcmp(interface, "wl_shm") == 0) { touch->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -297,6 +340,23 @@ static const struct wl_registry_listener registry_listener = { handle_global_remove }; +static void +handle_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, + int32_t width, int32_t height, + struct wl_array *state) +{ +} + +static void +handle_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) +{ +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_toplevel_configure, + handle_toplevel_close, +}; + static struct touch * touch_create(int width, int height) { @@ -321,30 +381,56 @@ touch_create(int width, int height) exit(1); } + if (!touch->wm_base) { + fprintf(stderr, "xdg-shell required!\n"); + exit(1); + } + touch->width = width; touch->height = height; touch->surface = wl_compositor_create_surface(touch->compositor); - touch->shell_surface = wl_shell_get_shell_surface(touch->shell, - touch->surface); - create_shm_buffer(touch); - - if (touch->shell_surface) { - wl_shell_surface_add_listener(touch->shell_surface, - &shell_surface_listener, touch); - wl_shell_surface_set_toplevel(touch->shell_surface); - } - wl_surface_set_user_data(touch->surface, touch); - wl_shell_surface_set_title(touch->shell_surface, "simple-touch"); + touch->xdg_surface = + xdg_wm_base_get_xdg_surface(touch->wm_base, touch->surface); + assert(touch->xdg_surface); + + xdg_surface_add_listener(touch->xdg_surface, &xdg_surface_listener, touch); - memset(touch->data, 64, width * height * 4); - wl_surface_attach(touch->surface, touch->buffer, 0, 0); - wl_surface_damage(touch->surface, 0, 0, width, height); + touch->xdg_toplevel = xdg_surface_get_toplevel(touch->xdg_surface); + assert(touch->xdg_toplevel); + xdg_toplevel_add_listener(touch->xdg_toplevel, + &xdg_toplevel_listener, touch); + xdg_toplevel_set_title(touch->xdg_toplevel, "simple-touch"); + xdg_toplevel_set_app_id(touch->xdg_toplevel, "simple-touch"); + touch->wait_for_configure = true; wl_surface_commit(touch->surface); return touch; } +static void +destroy_touch(struct touch *touch) +{ + if (touch->buffer->buffer) + wl_buffer_destroy(touch->buffer->buffer); + + if (touch->xdg_toplevel) + xdg_toplevel_destroy(touch->xdg_toplevel); + if (touch->xdg_surface) + xdg_surface_destroy(touch->xdg_surface); + if (touch->wm_base) + xdg_wm_base_destroy(touch->wm_base); + if (touch->shm) + wl_shm_destroy(touch->shm); + if (touch->compositor) + wl_compositor_destroy(touch->compositor); + + + wl_surface_destroy(touch->surface); + free(touch->buffer); + free(touch); +} + int main(int argc, char **argv) { @@ -356,5 +442,6 @@ main(int argc, char **argv) while (ret != -1) ret = wl_display_dispatch(touch->display); + destroy_touch(touch); return 0; }