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