1*2b949d04SAndroid Build Coastguard Worker /*
2*2b949d04SAndroid Build Coastguard Worker * Copyright © 2012 Collabora, Ltd.
3*2b949d04SAndroid Build Coastguard Worker * Copyright © 2013 Ran Benita <[email protected]>
4*2b949d04SAndroid Build Coastguard Worker * Copyright © 2016 Daniel Stone <[email protected]>
5*2b949d04SAndroid Build Coastguard Worker *
6*2b949d04SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
7*2b949d04SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
8*2b949d04SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
9*2b949d04SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*2b949d04SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
11*2b949d04SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
12*2b949d04SAndroid Build Coastguard Worker *
13*2b949d04SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
14*2b949d04SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
15*2b949d04SAndroid Build Coastguard Worker * Software.
16*2b949d04SAndroid Build Coastguard Worker *
17*2b949d04SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*2b949d04SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*2b949d04SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*2b949d04SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*2b949d04SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22*2b949d04SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*2b949d04SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
24*2b949d04SAndroid Build Coastguard Worker */
25*2b949d04SAndroid Build Coastguard Worker
26*2b949d04SAndroid Build Coastguard Worker #include "config.h"
27*2b949d04SAndroid Build Coastguard Worker
28*2b949d04SAndroid Build Coastguard Worker #include <errno.h>
29*2b949d04SAndroid Build Coastguard Worker #include <fcntl.h>
30*2b949d04SAndroid Build Coastguard Worker #include <locale.h>
31*2b949d04SAndroid Build Coastguard Worker #include <stdbool.h>
32*2b949d04SAndroid Build Coastguard Worker #include <stdint.h>
33*2b949d04SAndroid Build Coastguard Worker #include <stdlib.h>
34*2b949d04SAndroid Build Coastguard Worker #include <string.h>
35*2b949d04SAndroid Build Coastguard Worker #include <sys/mman.h>
36*2b949d04SAndroid Build Coastguard Worker #include <unistd.h>
37*2b949d04SAndroid Build Coastguard Worker
38*2b949d04SAndroid Build Coastguard Worker #include "xkbcommon/xkbcommon.h"
39*2b949d04SAndroid Build Coastguard Worker #include "tools-common.h"
40*2b949d04SAndroid Build Coastguard Worker
41*2b949d04SAndroid Build Coastguard Worker #include <wayland-client.h>
42*2b949d04SAndroid Build Coastguard Worker #include "xdg-shell-client-protocol.h"
43*2b949d04SAndroid Build Coastguard Worker #include <wayland-util.h>
44*2b949d04SAndroid Build Coastguard Worker
45*2b949d04SAndroid Build Coastguard Worker #define MAX(a, b) ((a) > (b) ? (a) : (b))
46*2b949d04SAndroid Build Coastguard Worker
47*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy {
48*2b949d04SAndroid Build Coastguard Worker struct wl_display *dpy;
49*2b949d04SAndroid Build Coastguard Worker struct wl_compositor *compositor;
50*2b949d04SAndroid Build Coastguard Worker struct xdg_wm_base *shell;
51*2b949d04SAndroid Build Coastguard Worker struct wl_shm *shm;
52*2b949d04SAndroid Build Coastguard Worker uint32_t shm_format;
53*2b949d04SAndroid Build Coastguard Worker
54*2b949d04SAndroid Build Coastguard Worker struct xkb_context *ctx;
55*2b949d04SAndroid Build Coastguard Worker
56*2b949d04SAndroid Build Coastguard Worker struct wl_surface *wl_surf;
57*2b949d04SAndroid Build Coastguard Worker struct xdg_surface *xdg_surf;
58*2b949d04SAndroid Build Coastguard Worker struct xdg_toplevel *xdg_top;
59*2b949d04SAndroid Build Coastguard Worker
60*2b949d04SAndroid Build Coastguard Worker struct wl_list seats;
61*2b949d04SAndroid Build Coastguard Worker };
62*2b949d04SAndroid Build Coastguard Worker
63*2b949d04SAndroid Build Coastguard Worker struct interactive_seat {
64*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy *inter;
65*2b949d04SAndroid Build Coastguard Worker
66*2b949d04SAndroid Build Coastguard Worker struct wl_seat *wl_seat;
67*2b949d04SAndroid Build Coastguard Worker struct wl_keyboard *wl_kbd;
68*2b949d04SAndroid Build Coastguard Worker struct wl_pointer *wl_pointer;
69*2b949d04SAndroid Build Coastguard Worker uint32_t version; /* ... of wl_seat */
70*2b949d04SAndroid Build Coastguard Worker uint32_t global_name; /* an ID of sorts */
71*2b949d04SAndroid Build Coastguard Worker char *name_str; /* a descriptor */
72*2b949d04SAndroid Build Coastguard Worker
73*2b949d04SAndroid Build Coastguard Worker struct xkb_keymap *keymap;
74*2b949d04SAndroid Build Coastguard Worker struct xkb_state *state;
75*2b949d04SAndroid Build Coastguard Worker
76*2b949d04SAndroid Build Coastguard Worker struct wl_list link;
77*2b949d04SAndroid Build Coastguard Worker };
78*2b949d04SAndroid Build Coastguard Worker
79*2b949d04SAndroid Build Coastguard Worker static bool terminate;
80*2b949d04SAndroid Build Coastguard Worker
81*2b949d04SAndroid Build Coastguard Worker #ifdef HAVE_MKOSTEMP
82*2b949d04SAndroid Build Coastguard Worker static int
create_tmpfile_cloexec(char * tmpname)83*2b949d04SAndroid Build Coastguard Worker create_tmpfile_cloexec(char *tmpname)
84*2b949d04SAndroid Build Coastguard Worker {
85*2b949d04SAndroid Build Coastguard Worker int fd = mkostemp(tmpname, O_CLOEXEC);
86*2b949d04SAndroid Build Coastguard Worker if (fd >= 0)
87*2b949d04SAndroid Build Coastguard Worker unlink(tmpname);
88*2b949d04SAndroid Build Coastguard Worker return fd;
89*2b949d04SAndroid Build Coastguard Worker }
90*2b949d04SAndroid Build Coastguard Worker #else
91*2b949d04SAndroid Build Coastguard Worker /* The following utility functions are taken from Weston's
92*2b949d04SAndroid Build Coastguard Worker * shared/os-compatibility.c. */
93*2b949d04SAndroid Build Coastguard Worker static int
os_fd_set_cloexec(int fd)94*2b949d04SAndroid Build Coastguard Worker os_fd_set_cloexec(int fd)
95*2b949d04SAndroid Build Coastguard Worker {
96*2b949d04SAndroid Build Coastguard Worker long flags;
97*2b949d04SAndroid Build Coastguard Worker
98*2b949d04SAndroid Build Coastguard Worker if (fd == -1)
99*2b949d04SAndroid Build Coastguard Worker return -1;
100*2b949d04SAndroid Build Coastguard Worker
101*2b949d04SAndroid Build Coastguard Worker flags = fcntl(fd, F_GETFD);
102*2b949d04SAndroid Build Coastguard Worker if (flags == -1)
103*2b949d04SAndroid Build Coastguard Worker return -1;
104*2b949d04SAndroid Build Coastguard Worker
105*2b949d04SAndroid Build Coastguard Worker if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
106*2b949d04SAndroid Build Coastguard Worker return -1;
107*2b949d04SAndroid Build Coastguard Worker
108*2b949d04SAndroid Build Coastguard Worker return 0;
109*2b949d04SAndroid Build Coastguard Worker }
110*2b949d04SAndroid Build Coastguard Worker
111*2b949d04SAndroid Build Coastguard Worker static int
set_cloexec_or_close(int fd)112*2b949d04SAndroid Build Coastguard Worker set_cloexec_or_close(int fd)
113*2b949d04SAndroid Build Coastguard Worker {
114*2b949d04SAndroid Build Coastguard Worker if (os_fd_set_cloexec(fd) != 0) {
115*2b949d04SAndroid Build Coastguard Worker close(fd);
116*2b949d04SAndroid Build Coastguard Worker return -1;
117*2b949d04SAndroid Build Coastguard Worker }
118*2b949d04SAndroid Build Coastguard Worker return fd;
119*2b949d04SAndroid Build Coastguard Worker }
120*2b949d04SAndroid Build Coastguard Worker
121*2b949d04SAndroid Build Coastguard Worker static int
create_tmpfile_cloexec(char * tmpname)122*2b949d04SAndroid Build Coastguard Worker create_tmpfile_cloexec(char *tmpname)
123*2b949d04SAndroid Build Coastguard Worker {
124*2b949d04SAndroid Build Coastguard Worker int fd = mkstemp(tmpname);
125*2b949d04SAndroid Build Coastguard Worker if (fd >= 0) {
126*2b949d04SAndroid Build Coastguard Worker fd = set_cloexec_or_close(fd);
127*2b949d04SAndroid Build Coastguard Worker unlink(tmpname);
128*2b949d04SAndroid Build Coastguard Worker }
129*2b949d04SAndroid Build Coastguard Worker return fd;
130*2b949d04SAndroid Build Coastguard Worker }
131*2b949d04SAndroid Build Coastguard Worker #endif
132*2b949d04SAndroid Build Coastguard Worker
133*2b949d04SAndroid Build Coastguard Worker static int
os_resize_anonymous_file(int fd,off_t size)134*2b949d04SAndroid Build Coastguard Worker os_resize_anonymous_file(int fd, off_t size)
135*2b949d04SAndroid Build Coastguard Worker {
136*2b949d04SAndroid Build Coastguard Worker int ret;
137*2b949d04SAndroid Build Coastguard Worker #ifdef HAVE_POSIX_FALLOCATE
138*2b949d04SAndroid Build Coastguard Worker ret = posix_fallocate(fd, 0, size);
139*2b949d04SAndroid Build Coastguard Worker if (ret == 0)
140*2b949d04SAndroid Build Coastguard Worker return 0;
141*2b949d04SAndroid Build Coastguard Worker /*
142*2b949d04SAndroid Build Coastguard Worker * Filesystems that do support fallocate will return EINVAL
143*2b949d04SAndroid Build Coastguard Worker * or EOPNOTSUPP, fallback to ftruncate() then.
144*2b949d04SAndroid Build Coastguard Worker */
145*2b949d04SAndroid Build Coastguard Worker if (ret != EINVAL && ret != EOPNOTSUPP)
146*2b949d04SAndroid Build Coastguard Worker return ret;
147*2b949d04SAndroid Build Coastguard Worker #endif
148*2b949d04SAndroid Build Coastguard Worker ret = ftruncate(fd, size);
149*2b949d04SAndroid Build Coastguard Worker if (ret != 0)
150*2b949d04SAndroid Build Coastguard Worker return errno;
151*2b949d04SAndroid Build Coastguard Worker return 0;
152*2b949d04SAndroid Build Coastguard Worker }
153*2b949d04SAndroid Build Coastguard Worker
154*2b949d04SAndroid Build Coastguard Worker /*
155*2b949d04SAndroid Build Coastguard Worker * Create a new, unique, anonymous file of the given size, and
156*2b949d04SAndroid Build Coastguard Worker * return the file descriptor for it. The file descriptor is set
157*2b949d04SAndroid Build Coastguard Worker * CLOEXEC. The file is immediately suitable for mmap()'ing
158*2b949d04SAndroid Build Coastguard Worker * the given size at offset zero.
159*2b949d04SAndroid Build Coastguard Worker *
160*2b949d04SAndroid Build Coastguard Worker * The file should not have a permanent backing store like a disk,
161*2b949d04SAndroid Build Coastguard Worker * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
162*2b949d04SAndroid Build Coastguard Worker *
163*2b949d04SAndroid Build Coastguard Worker * The file name is deleted from the file system.
164*2b949d04SAndroid Build Coastguard Worker *
165*2b949d04SAndroid Build Coastguard Worker * The file is suitable for buffer sharing between processes by
166*2b949d04SAndroid Build Coastguard Worker * transmitting the file descriptor over Unix sockets using the
167*2b949d04SAndroid Build Coastguard Worker * SCM_RIGHTS methods.
168*2b949d04SAndroid Build Coastguard Worker *
169*2b949d04SAndroid Build Coastguard Worker * If the C library implements posix_fallocate(), it is used to
170*2b949d04SAndroid Build Coastguard Worker * guarantee that disk space is available for the file at the
171*2b949d04SAndroid Build Coastguard Worker * given size. If disk space is insufficent, errno is set to ENOSPC.
172*2b949d04SAndroid Build Coastguard Worker * If posix_fallocate() is not supported, program will fallback
173*2b949d04SAndroid Build Coastguard Worker * to ftruncate() instead.
174*2b949d04SAndroid Build Coastguard Worker */
175*2b949d04SAndroid Build Coastguard Worker static int
os_create_anonymous_file(off_t size)176*2b949d04SAndroid Build Coastguard Worker os_create_anonymous_file(off_t size)
177*2b949d04SAndroid Build Coastguard Worker {
178*2b949d04SAndroid Build Coastguard Worker static const char template[] = "/weston-shared-XXXXXX";
179*2b949d04SAndroid Build Coastguard Worker const char *path;
180*2b949d04SAndroid Build Coastguard Worker char *name;
181*2b949d04SAndroid Build Coastguard Worker int fd;
182*2b949d04SAndroid Build Coastguard Worker int ret;
183*2b949d04SAndroid Build Coastguard Worker
184*2b949d04SAndroid Build Coastguard Worker path = getenv("XDG_RUNTIME_DIR");
185*2b949d04SAndroid Build Coastguard Worker if (!path) {
186*2b949d04SAndroid Build Coastguard Worker errno = ENOENT;
187*2b949d04SAndroid Build Coastguard Worker return -1;
188*2b949d04SAndroid Build Coastguard Worker }
189*2b949d04SAndroid Build Coastguard Worker
190*2b949d04SAndroid Build Coastguard Worker name = malloc(strlen(path) + sizeof(template));
191*2b949d04SAndroid Build Coastguard Worker if (!name)
192*2b949d04SAndroid Build Coastguard Worker return -1;
193*2b949d04SAndroid Build Coastguard Worker
194*2b949d04SAndroid Build Coastguard Worker strcpy(name, path);
195*2b949d04SAndroid Build Coastguard Worker strcat(name, template);
196*2b949d04SAndroid Build Coastguard Worker
197*2b949d04SAndroid Build Coastguard Worker fd = create_tmpfile_cloexec(name);
198*2b949d04SAndroid Build Coastguard Worker
199*2b949d04SAndroid Build Coastguard Worker free(name);
200*2b949d04SAndroid Build Coastguard Worker
201*2b949d04SAndroid Build Coastguard Worker if (fd < 0)
202*2b949d04SAndroid Build Coastguard Worker return -1;
203*2b949d04SAndroid Build Coastguard Worker
204*2b949d04SAndroid Build Coastguard Worker ret = os_resize_anonymous_file(fd, size);
205*2b949d04SAndroid Build Coastguard Worker if (ret != 0) {
206*2b949d04SAndroid Build Coastguard Worker close(fd);
207*2b949d04SAndroid Build Coastguard Worker errno = ret;
208*2b949d04SAndroid Build Coastguard Worker return -1;
209*2b949d04SAndroid Build Coastguard Worker }
210*2b949d04SAndroid Build Coastguard Worker
211*2b949d04SAndroid Build Coastguard Worker return fd;
212*2b949d04SAndroid Build Coastguard Worker }
213*2b949d04SAndroid Build Coastguard Worker
214*2b949d04SAndroid Build Coastguard Worker static void
buffer_release(void * data,struct wl_buffer * buffer)215*2b949d04SAndroid Build Coastguard Worker buffer_release(void *data, struct wl_buffer *buffer)
216*2b949d04SAndroid Build Coastguard Worker {
217*2b949d04SAndroid Build Coastguard Worker wl_buffer_destroy(buffer);
218*2b949d04SAndroid Build Coastguard Worker }
219*2b949d04SAndroid Build Coastguard Worker
220*2b949d04SAndroid Build Coastguard Worker static const struct wl_buffer_listener buffer_listener = {
221*2b949d04SAndroid Build Coastguard Worker buffer_release
222*2b949d04SAndroid Build Coastguard Worker };
223*2b949d04SAndroid Build Coastguard Worker
224*2b949d04SAndroid Build Coastguard Worker static void
buffer_create(struct interactive_dpy * inter,uint32_t width,uint32_t height)225*2b949d04SAndroid Build Coastguard Worker buffer_create(struct interactive_dpy *inter, uint32_t width, uint32_t height)
226*2b949d04SAndroid Build Coastguard Worker {
227*2b949d04SAndroid Build Coastguard Worker struct wl_shm_pool *pool;
228*2b949d04SAndroid Build Coastguard Worker struct wl_buffer *buf;
229*2b949d04SAndroid Build Coastguard Worker struct wl_region *opaque;
230*2b949d04SAndroid Build Coastguard Worker uint32_t stride;
231*2b949d04SAndroid Build Coastguard Worker size_t size;
232*2b949d04SAndroid Build Coastguard Worker void *map;
233*2b949d04SAndroid Build Coastguard Worker int fd;
234*2b949d04SAndroid Build Coastguard Worker
235*2b949d04SAndroid Build Coastguard Worker switch (inter->shm_format) {
236*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_ARGB8888:
237*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_XRGB8888:
238*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_ABGR8888:
239*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_XBGR8888:
240*2b949d04SAndroid Build Coastguard Worker stride = width * 4;
241*2b949d04SAndroid Build Coastguard Worker break;
242*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_RGB565:
243*2b949d04SAndroid Build Coastguard Worker case WL_SHM_FORMAT_BGR565:
244*2b949d04SAndroid Build Coastguard Worker stride = width * 2;
245*2b949d04SAndroid Build Coastguard Worker break;
246*2b949d04SAndroid Build Coastguard Worker default:
247*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Unsupported SHM format %d\n", inter->shm_format);
248*2b949d04SAndroid Build Coastguard Worker exit(1);
249*2b949d04SAndroid Build Coastguard Worker }
250*2b949d04SAndroid Build Coastguard Worker
251*2b949d04SAndroid Build Coastguard Worker size = stride * height;
252*2b949d04SAndroid Build Coastguard Worker fd = os_create_anonymous_file(size);
253*2b949d04SAndroid Build Coastguard Worker if (fd < 0) {
254*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't create surface buffer\n");
255*2b949d04SAndroid Build Coastguard Worker exit(1);
256*2b949d04SAndroid Build Coastguard Worker }
257*2b949d04SAndroid Build Coastguard Worker
258*2b949d04SAndroid Build Coastguard Worker map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
259*2b949d04SAndroid Build Coastguard Worker if (map == MAP_FAILED) {
260*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't mmap surface buffer\n");
261*2b949d04SAndroid Build Coastguard Worker exit(1);
262*2b949d04SAndroid Build Coastguard Worker }
263*2b949d04SAndroid Build Coastguard Worker memset(map, 0xff, size);
264*2b949d04SAndroid Build Coastguard Worker munmap(map, size);
265*2b949d04SAndroid Build Coastguard Worker
266*2b949d04SAndroid Build Coastguard Worker pool = wl_shm_create_pool(inter->shm, fd, size);
267*2b949d04SAndroid Build Coastguard Worker buf = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
268*2b949d04SAndroid Build Coastguard Worker inter->shm_format);
269*2b949d04SAndroid Build Coastguard Worker wl_buffer_add_listener(buf, &buffer_listener, inter);
270*2b949d04SAndroid Build Coastguard Worker
271*2b949d04SAndroid Build Coastguard Worker wl_surface_attach(inter->wl_surf, buf, 0, 0);
272*2b949d04SAndroid Build Coastguard Worker wl_surface_damage(inter->wl_surf, 0, 0, width, height);
273*2b949d04SAndroid Build Coastguard Worker
274*2b949d04SAndroid Build Coastguard Worker opaque = wl_compositor_create_region(inter->compositor);
275*2b949d04SAndroid Build Coastguard Worker wl_region_add(opaque, 0, 0, width, height);
276*2b949d04SAndroid Build Coastguard Worker wl_surface_set_opaque_region(inter->wl_surf, opaque);
277*2b949d04SAndroid Build Coastguard Worker wl_region_destroy(opaque);
278*2b949d04SAndroid Build Coastguard Worker
279*2b949d04SAndroid Build Coastguard Worker wl_shm_pool_destroy(pool);
280*2b949d04SAndroid Build Coastguard Worker close(fd);
281*2b949d04SAndroid Build Coastguard Worker }
282*2b949d04SAndroid Build Coastguard Worker
283*2b949d04SAndroid Build Coastguard Worker static void
surface_configure(void * data,struct xdg_surface * surface,uint32_t serial)284*2b949d04SAndroid Build Coastguard Worker surface_configure(void *data, struct xdg_surface *surface,
285*2b949d04SAndroid Build Coastguard Worker uint32_t serial)
286*2b949d04SAndroid Build Coastguard Worker {
287*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy *inter = data;
288*2b949d04SAndroid Build Coastguard Worker
289*2b949d04SAndroid Build Coastguard Worker xdg_surface_ack_configure(inter->xdg_surf, serial);
290*2b949d04SAndroid Build Coastguard Worker wl_surface_commit(inter->wl_surf);
291*2b949d04SAndroid Build Coastguard Worker }
292*2b949d04SAndroid Build Coastguard Worker
293*2b949d04SAndroid Build Coastguard Worker static const struct xdg_surface_listener surface_listener = {
294*2b949d04SAndroid Build Coastguard Worker surface_configure,
295*2b949d04SAndroid Build Coastguard Worker };
296*2b949d04SAndroid Build Coastguard Worker
297*2b949d04SAndroid Build Coastguard Worker static void
toplevel_configure(void * data,struct xdg_toplevel * toplevel,int32_t width,int32_t height,struct wl_array * states)298*2b949d04SAndroid Build Coastguard Worker toplevel_configure(void *data, struct xdg_toplevel *toplevel,
299*2b949d04SAndroid Build Coastguard Worker int32_t width, int32_t height, struct wl_array *states)
300*2b949d04SAndroid Build Coastguard Worker {
301*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy *inter = data;
302*2b949d04SAndroid Build Coastguard Worker
303*2b949d04SAndroid Build Coastguard Worker if (width == 0)
304*2b949d04SAndroid Build Coastguard Worker width = 200;
305*2b949d04SAndroid Build Coastguard Worker if (height == 0)
306*2b949d04SAndroid Build Coastguard Worker height = 200;
307*2b949d04SAndroid Build Coastguard Worker
308*2b949d04SAndroid Build Coastguard Worker buffer_create(inter, width, height);
309*2b949d04SAndroid Build Coastguard Worker }
310*2b949d04SAndroid Build Coastguard Worker
311*2b949d04SAndroid Build Coastguard Worker static void
toplevel_close(void * data,struct xdg_toplevel * toplevel)312*2b949d04SAndroid Build Coastguard Worker toplevel_close(void *data, struct xdg_toplevel *toplevel)
313*2b949d04SAndroid Build Coastguard Worker {
314*2b949d04SAndroid Build Coastguard Worker terminate = true;
315*2b949d04SAndroid Build Coastguard Worker }
316*2b949d04SAndroid Build Coastguard Worker
317*2b949d04SAndroid Build Coastguard Worker static const struct xdg_toplevel_listener toplevel_listener = {
318*2b949d04SAndroid Build Coastguard Worker toplevel_configure,
319*2b949d04SAndroid Build Coastguard Worker toplevel_close
320*2b949d04SAndroid Build Coastguard Worker };
321*2b949d04SAndroid Build Coastguard Worker
surface_create(struct interactive_dpy * inter)322*2b949d04SAndroid Build Coastguard Worker static void surface_create(struct interactive_dpy *inter)
323*2b949d04SAndroid Build Coastguard Worker {
324*2b949d04SAndroid Build Coastguard Worker inter->wl_surf = wl_compositor_create_surface(inter->compositor);
325*2b949d04SAndroid Build Coastguard Worker inter->xdg_surf = xdg_wm_base_get_xdg_surface(inter->shell, inter->wl_surf);
326*2b949d04SAndroid Build Coastguard Worker xdg_surface_add_listener(inter->xdg_surf, &surface_listener, inter);
327*2b949d04SAndroid Build Coastguard Worker inter->xdg_top = xdg_surface_get_toplevel(inter->xdg_surf);
328*2b949d04SAndroid Build Coastguard Worker xdg_toplevel_add_listener(inter->xdg_top, &toplevel_listener, inter);
329*2b949d04SAndroid Build Coastguard Worker xdg_toplevel_set_title(inter->xdg_top, "xkbcommon event tester");
330*2b949d04SAndroid Build Coastguard Worker xdg_toplevel_set_app_id(inter->xdg_top,
331*2b949d04SAndroid Build Coastguard Worker "org.xkbcommon.test.interactive-wayland");
332*2b949d04SAndroid Build Coastguard Worker wl_surface_commit(inter->wl_surf);
333*2b949d04SAndroid Build Coastguard Worker }
334*2b949d04SAndroid Build Coastguard Worker
335*2b949d04SAndroid Build Coastguard Worker static void
shell_ping(void * data,struct xdg_wm_base * shell,uint32_t serial)336*2b949d04SAndroid Build Coastguard Worker shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
337*2b949d04SAndroid Build Coastguard Worker {
338*2b949d04SAndroid Build Coastguard Worker xdg_wm_base_pong(shell, serial);
339*2b949d04SAndroid Build Coastguard Worker }
340*2b949d04SAndroid Build Coastguard Worker
341*2b949d04SAndroid Build Coastguard Worker static const struct xdg_wm_base_listener shell_listener = {
342*2b949d04SAndroid Build Coastguard Worker shell_ping
343*2b949d04SAndroid Build Coastguard Worker };
344*2b949d04SAndroid Build Coastguard Worker
345*2b949d04SAndroid Build Coastguard Worker static void
kbd_keymap(void * data,struct wl_keyboard * wl_kbd,uint32_t format,int fd,uint32_t size)346*2b949d04SAndroid Build Coastguard Worker kbd_keymap(void *data, struct wl_keyboard *wl_kbd, uint32_t format,
347*2b949d04SAndroid Build Coastguard Worker int fd, uint32_t size)
348*2b949d04SAndroid Build Coastguard Worker {
349*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
350*2b949d04SAndroid Build Coastguard Worker void *buf;
351*2b949d04SAndroid Build Coastguard Worker
352*2b949d04SAndroid Build Coastguard Worker buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
353*2b949d04SAndroid Build Coastguard Worker if (buf == MAP_FAILED) {
354*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Failed to mmap keymap: %d\n", errno);
355*2b949d04SAndroid Build Coastguard Worker close(fd);
356*2b949d04SAndroid Build Coastguard Worker return;
357*2b949d04SAndroid Build Coastguard Worker }
358*2b949d04SAndroid Build Coastguard Worker
359*2b949d04SAndroid Build Coastguard Worker seat->keymap = xkb_keymap_new_from_buffer(seat->inter->ctx, buf, size - 1,
360*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_FORMAT_TEXT_V1,
361*2b949d04SAndroid Build Coastguard Worker XKB_KEYMAP_COMPILE_NO_FLAGS);
362*2b949d04SAndroid Build Coastguard Worker munmap(buf, size);
363*2b949d04SAndroid Build Coastguard Worker close(fd);
364*2b949d04SAndroid Build Coastguard Worker if (!seat->keymap) {
365*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Failed to compile keymap!\n");
366*2b949d04SAndroid Build Coastguard Worker return;
367*2b949d04SAndroid Build Coastguard Worker }
368*2b949d04SAndroid Build Coastguard Worker
369*2b949d04SAndroid Build Coastguard Worker seat->state = xkb_state_new(seat->keymap);
370*2b949d04SAndroid Build Coastguard Worker if (!seat->state) {
371*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Failed to create XKB state!\n");
372*2b949d04SAndroid Build Coastguard Worker return;
373*2b949d04SAndroid Build Coastguard Worker }
374*2b949d04SAndroid Build Coastguard Worker }
375*2b949d04SAndroid Build Coastguard Worker
376*2b949d04SAndroid Build Coastguard Worker static void
kbd_enter(void * data,struct wl_keyboard * wl_kbd,uint32_t serial,struct wl_surface * surf,struct wl_array * keys)377*2b949d04SAndroid Build Coastguard Worker kbd_enter(void *data, struct wl_keyboard *wl_kbd, uint32_t serial,
378*2b949d04SAndroid Build Coastguard Worker struct wl_surface *surf, struct wl_array *keys)
379*2b949d04SAndroid Build Coastguard Worker {
380*2b949d04SAndroid Build Coastguard Worker }
381*2b949d04SAndroid Build Coastguard Worker
382*2b949d04SAndroid Build Coastguard Worker static void
kbd_leave(void * data,struct wl_keyboard * wl_kbd,uint32_t serial,struct wl_surface * surf)383*2b949d04SAndroid Build Coastguard Worker kbd_leave(void *data, struct wl_keyboard *wl_kbd, uint32_t serial,
384*2b949d04SAndroid Build Coastguard Worker struct wl_surface *surf)
385*2b949d04SAndroid Build Coastguard Worker {
386*2b949d04SAndroid Build Coastguard Worker }
387*2b949d04SAndroid Build Coastguard Worker
388*2b949d04SAndroid Build Coastguard Worker static void
kbd_key(void * data,struct wl_keyboard * wl_kbd,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)389*2b949d04SAndroid Build Coastguard Worker kbd_key(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t time,
390*2b949d04SAndroid Build Coastguard Worker uint32_t key, uint32_t state)
391*2b949d04SAndroid Build Coastguard Worker {
392*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
393*2b949d04SAndroid Build Coastguard Worker
394*2b949d04SAndroid Build Coastguard Worker if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
395*2b949d04SAndroid Build Coastguard Worker return;
396*2b949d04SAndroid Build Coastguard Worker
397*2b949d04SAndroid Build Coastguard Worker printf("%s: ", seat->name_str);
398*2b949d04SAndroid Build Coastguard Worker tools_print_keycode_state(seat->state, NULL, key + 8,
399*2b949d04SAndroid Build Coastguard Worker XKB_CONSUMED_MODE_XKB);
400*2b949d04SAndroid Build Coastguard Worker
401*2b949d04SAndroid Build Coastguard Worker /* Exit on ESC. */
402*2b949d04SAndroid Build Coastguard Worker if (xkb_state_key_get_one_sym(seat->state, key + 8) == XKB_KEY_Escape)
403*2b949d04SAndroid Build Coastguard Worker terminate = true;
404*2b949d04SAndroid Build Coastguard Worker }
405*2b949d04SAndroid Build Coastguard Worker
406*2b949d04SAndroid Build Coastguard Worker static void
kbd_modifiers(void * data,struct wl_keyboard * wl_kbd,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)407*2b949d04SAndroid Build Coastguard Worker kbd_modifiers(void *data, struct wl_keyboard *wl_kbd, uint32_t serial,
408*2b949d04SAndroid Build Coastguard Worker uint32_t mods_depressed, uint32_t mods_latched,
409*2b949d04SAndroid Build Coastguard Worker uint32_t mods_locked, uint32_t group)
410*2b949d04SAndroid Build Coastguard Worker {
411*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
412*2b949d04SAndroid Build Coastguard Worker
413*2b949d04SAndroid Build Coastguard Worker xkb_state_update_mask(seat->state, mods_depressed, mods_latched,
414*2b949d04SAndroid Build Coastguard Worker mods_locked, 0, 0, group);
415*2b949d04SAndroid Build Coastguard Worker }
416*2b949d04SAndroid Build Coastguard Worker
417*2b949d04SAndroid Build Coastguard Worker static void
kbd_repeat_info(void * data,struct wl_keyboard * wl_kbd,int32_t rate,int32_t delay)418*2b949d04SAndroid Build Coastguard Worker kbd_repeat_info(void *data, struct wl_keyboard *wl_kbd, int32_t rate,
419*2b949d04SAndroid Build Coastguard Worker int32_t delay)
420*2b949d04SAndroid Build Coastguard Worker {
421*2b949d04SAndroid Build Coastguard Worker }
422*2b949d04SAndroid Build Coastguard Worker
423*2b949d04SAndroid Build Coastguard Worker static const struct wl_keyboard_listener kbd_listener = {
424*2b949d04SAndroid Build Coastguard Worker kbd_keymap,
425*2b949d04SAndroid Build Coastguard Worker kbd_enter,
426*2b949d04SAndroid Build Coastguard Worker kbd_leave,
427*2b949d04SAndroid Build Coastguard Worker kbd_key,
428*2b949d04SAndroid Build Coastguard Worker kbd_modifiers,
429*2b949d04SAndroid Build Coastguard Worker kbd_repeat_info
430*2b949d04SAndroid Build Coastguard Worker };
431*2b949d04SAndroid Build Coastguard Worker
432*2b949d04SAndroid Build Coastguard Worker static void
pointer_enter(void * data,struct wl_pointer * wl_pointer,uint32_t serial,struct wl_surface * surf,wl_fixed_t fsx,wl_fixed_t fsy)433*2b949d04SAndroid Build Coastguard Worker pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
434*2b949d04SAndroid Build Coastguard Worker struct wl_surface *surf, wl_fixed_t fsx, wl_fixed_t fsy)
435*2b949d04SAndroid Build Coastguard Worker {
436*2b949d04SAndroid Build Coastguard Worker }
437*2b949d04SAndroid Build Coastguard Worker
438*2b949d04SAndroid Build Coastguard Worker static void
pointer_leave(void * data,struct wl_pointer * wl_pointer,uint32_t serial,struct wl_surface * surf)439*2b949d04SAndroid Build Coastguard Worker pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
440*2b949d04SAndroid Build Coastguard Worker struct wl_surface *surf)
441*2b949d04SAndroid Build Coastguard Worker {
442*2b949d04SAndroid Build Coastguard Worker }
443*2b949d04SAndroid Build Coastguard Worker
444*2b949d04SAndroid Build Coastguard Worker static void
pointer_motion(void * data,struct wl_pointer * wl_pointer,uint32_t time,wl_fixed_t fsx,wl_fixed_t fsy)445*2b949d04SAndroid Build Coastguard Worker pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
446*2b949d04SAndroid Build Coastguard Worker wl_fixed_t fsx, wl_fixed_t fsy)
447*2b949d04SAndroid Build Coastguard Worker {
448*2b949d04SAndroid Build Coastguard Worker }
449*2b949d04SAndroid Build Coastguard Worker
450*2b949d04SAndroid Build Coastguard Worker static void
pointer_button(void * data,struct wl_pointer * wl_pointer,uint32_t serial,uint32_t time,uint32_t button,uint32_t state)451*2b949d04SAndroid Build Coastguard Worker pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
452*2b949d04SAndroid Build Coastguard Worker uint32_t time, uint32_t button, uint32_t state)
453*2b949d04SAndroid Build Coastguard Worker {
454*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
455*2b949d04SAndroid Build Coastguard Worker
456*2b949d04SAndroid Build Coastguard Worker xdg_toplevel_move(seat->inter->xdg_top, seat->wl_seat, serial);
457*2b949d04SAndroid Build Coastguard Worker }
458*2b949d04SAndroid Build Coastguard Worker
459*2b949d04SAndroid Build Coastguard Worker static void
pointer_axis(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis,wl_fixed_t value)460*2b949d04SAndroid Build Coastguard Worker pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time,
461*2b949d04SAndroid Build Coastguard Worker uint32_t axis, wl_fixed_t value)
462*2b949d04SAndroid Build Coastguard Worker {
463*2b949d04SAndroid Build Coastguard Worker }
464*2b949d04SAndroid Build Coastguard Worker
465*2b949d04SAndroid Build Coastguard Worker static void
pointer_frame(void * data,struct wl_pointer * wl_pointer)466*2b949d04SAndroid Build Coastguard Worker pointer_frame(void *data, struct wl_pointer *wl_pointer)
467*2b949d04SAndroid Build Coastguard Worker {
468*2b949d04SAndroid Build Coastguard Worker }
469*2b949d04SAndroid Build Coastguard Worker
470*2b949d04SAndroid Build Coastguard Worker static void
pointer_axis_source(void * data,struct wl_pointer * wl_pointer,uint32_t source)471*2b949d04SAndroid Build Coastguard Worker pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t source)
472*2b949d04SAndroid Build Coastguard Worker {
473*2b949d04SAndroid Build Coastguard Worker }
474*2b949d04SAndroid Build Coastguard Worker
475*2b949d04SAndroid Build Coastguard Worker static void
pointer_axis_stop(void * data,struct wl_pointer * wl_pointer,uint32_t time,uint32_t axis)476*2b949d04SAndroid Build Coastguard Worker pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time,
477*2b949d04SAndroid Build Coastguard Worker uint32_t axis)
478*2b949d04SAndroid Build Coastguard Worker {
479*2b949d04SAndroid Build Coastguard Worker }
480*2b949d04SAndroid Build Coastguard Worker
481*2b949d04SAndroid Build Coastguard Worker static void
pointer_axis_discrete(void * data,struct wl_pointer * wl_pointer,uint32_t time,int32_t discrete)482*2b949d04SAndroid Build Coastguard Worker pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t time,
483*2b949d04SAndroid Build Coastguard Worker int32_t discrete)
484*2b949d04SAndroid Build Coastguard Worker {
485*2b949d04SAndroid Build Coastguard Worker }
486*2b949d04SAndroid Build Coastguard Worker
487*2b949d04SAndroid Build Coastguard Worker static const struct wl_pointer_listener pointer_listener = {
488*2b949d04SAndroid Build Coastguard Worker pointer_enter,
489*2b949d04SAndroid Build Coastguard Worker pointer_leave,
490*2b949d04SAndroid Build Coastguard Worker pointer_motion,
491*2b949d04SAndroid Build Coastguard Worker pointer_button,
492*2b949d04SAndroid Build Coastguard Worker pointer_axis,
493*2b949d04SAndroid Build Coastguard Worker pointer_frame,
494*2b949d04SAndroid Build Coastguard Worker pointer_axis_source,
495*2b949d04SAndroid Build Coastguard Worker pointer_axis_stop,
496*2b949d04SAndroid Build Coastguard Worker pointer_axis_discrete
497*2b949d04SAndroid Build Coastguard Worker };
498*2b949d04SAndroid Build Coastguard Worker
499*2b949d04SAndroid Build Coastguard Worker static void
seat_capabilities(void * data,struct wl_seat * wl_seat,uint32_t caps)500*2b949d04SAndroid Build Coastguard Worker seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t caps)
501*2b949d04SAndroid Build Coastguard Worker {
502*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
503*2b949d04SAndroid Build Coastguard Worker
504*2b949d04SAndroid Build Coastguard Worker if (!seat->wl_kbd && (caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
505*2b949d04SAndroid Build Coastguard Worker seat->wl_kbd = wl_seat_get_keyboard(seat->wl_seat);
506*2b949d04SAndroid Build Coastguard Worker wl_keyboard_add_listener(seat->wl_kbd, &kbd_listener, seat);
507*2b949d04SAndroid Build Coastguard Worker }
508*2b949d04SAndroid Build Coastguard Worker else if (seat->wl_kbd && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) {
509*2b949d04SAndroid Build Coastguard Worker if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
510*2b949d04SAndroid Build Coastguard Worker wl_keyboard_release(seat->wl_kbd);
511*2b949d04SAndroid Build Coastguard Worker else
512*2b949d04SAndroid Build Coastguard Worker wl_keyboard_destroy(seat->wl_kbd);
513*2b949d04SAndroid Build Coastguard Worker
514*2b949d04SAndroid Build Coastguard Worker xkb_state_unref(seat->state);
515*2b949d04SAndroid Build Coastguard Worker xkb_keymap_unref(seat->keymap);
516*2b949d04SAndroid Build Coastguard Worker
517*2b949d04SAndroid Build Coastguard Worker seat->state = NULL;
518*2b949d04SAndroid Build Coastguard Worker seat->keymap = NULL;
519*2b949d04SAndroid Build Coastguard Worker seat->wl_kbd = NULL;
520*2b949d04SAndroid Build Coastguard Worker }
521*2b949d04SAndroid Build Coastguard Worker
522*2b949d04SAndroid Build Coastguard Worker if (!seat->wl_pointer && (caps & WL_SEAT_CAPABILITY_POINTER)) {
523*2b949d04SAndroid Build Coastguard Worker seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
524*2b949d04SAndroid Build Coastguard Worker wl_pointer_add_listener(seat->wl_pointer, &pointer_listener,
525*2b949d04SAndroid Build Coastguard Worker seat);
526*2b949d04SAndroid Build Coastguard Worker }
527*2b949d04SAndroid Build Coastguard Worker else if (seat->wl_pointer && !(caps & WL_SEAT_CAPABILITY_POINTER)) {
528*2b949d04SAndroid Build Coastguard Worker if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
529*2b949d04SAndroid Build Coastguard Worker wl_pointer_release(seat->wl_pointer);
530*2b949d04SAndroid Build Coastguard Worker else
531*2b949d04SAndroid Build Coastguard Worker wl_pointer_destroy(seat->wl_pointer);
532*2b949d04SAndroid Build Coastguard Worker seat->wl_pointer = NULL;
533*2b949d04SAndroid Build Coastguard Worker }
534*2b949d04SAndroid Build Coastguard Worker }
535*2b949d04SAndroid Build Coastguard Worker
536*2b949d04SAndroid Build Coastguard Worker static void
seat_name(void * data,struct wl_seat * wl_seat,const char * name)537*2b949d04SAndroid Build Coastguard Worker seat_name(void *data, struct wl_seat *wl_seat, const char *name)
538*2b949d04SAndroid Build Coastguard Worker {
539*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = data;
540*2b949d04SAndroid Build Coastguard Worker
541*2b949d04SAndroid Build Coastguard Worker free(seat->name_str);
542*2b949d04SAndroid Build Coastguard Worker seat->name_str = strdup(name);
543*2b949d04SAndroid Build Coastguard Worker }
544*2b949d04SAndroid Build Coastguard Worker
545*2b949d04SAndroid Build Coastguard Worker static const struct wl_seat_listener seat_listener = {
546*2b949d04SAndroid Build Coastguard Worker seat_capabilities,
547*2b949d04SAndroid Build Coastguard Worker seat_name
548*2b949d04SAndroid Build Coastguard Worker };
549*2b949d04SAndroid Build Coastguard Worker
550*2b949d04SAndroid Build Coastguard Worker static void
seat_create(struct interactive_dpy * inter,struct wl_registry * registry,uint32_t name,uint32_t version)551*2b949d04SAndroid Build Coastguard Worker seat_create(struct interactive_dpy *inter, struct wl_registry *registry,
552*2b949d04SAndroid Build Coastguard Worker uint32_t name, uint32_t version)
553*2b949d04SAndroid Build Coastguard Worker {
554*2b949d04SAndroid Build Coastguard Worker int ret;
555*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat = calloc(1, sizeof(*seat));
556*2b949d04SAndroid Build Coastguard Worker
557*2b949d04SAndroid Build Coastguard Worker seat->global_name = name;
558*2b949d04SAndroid Build Coastguard Worker seat->inter = inter;
559*2b949d04SAndroid Build Coastguard Worker seat->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface,
560*2b949d04SAndroid Build Coastguard Worker MAX(version, 5));
561*2b949d04SAndroid Build Coastguard Worker wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
562*2b949d04SAndroid Build Coastguard Worker ret = asprintf(&seat->name_str, "seat:%d",
563*2b949d04SAndroid Build Coastguard Worker wl_proxy_get_id((struct wl_proxy *) seat->wl_seat));
564*2b949d04SAndroid Build Coastguard Worker assert(ret >= 0);
565*2b949d04SAndroid Build Coastguard Worker wl_list_insert(&inter->seats, &seat->link);
566*2b949d04SAndroid Build Coastguard Worker }
567*2b949d04SAndroid Build Coastguard Worker
568*2b949d04SAndroid Build Coastguard Worker static void
seat_destroy(struct interactive_seat * seat)569*2b949d04SAndroid Build Coastguard Worker seat_destroy(struct interactive_seat *seat)
570*2b949d04SAndroid Build Coastguard Worker {
571*2b949d04SAndroid Build Coastguard Worker if (seat->wl_kbd) {
572*2b949d04SAndroid Build Coastguard Worker if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
573*2b949d04SAndroid Build Coastguard Worker wl_keyboard_release(seat->wl_kbd);
574*2b949d04SAndroid Build Coastguard Worker else
575*2b949d04SAndroid Build Coastguard Worker wl_keyboard_destroy(seat->wl_kbd);
576*2b949d04SAndroid Build Coastguard Worker
577*2b949d04SAndroid Build Coastguard Worker xkb_state_unref(seat->state);
578*2b949d04SAndroid Build Coastguard Worker xkb_keymap_unref(seat->keymap);
579*2b949d04SAndroid Build Coastguard Worker }
580*2b949d04SAndroid Build Coastguard Worker
581*2b949d04SAndroid Build Coastguard Worker if (seat->wl_pointer) {
582*2b949d04SAndroid Build Coastguard Worker if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
583*2b949d04SAndroid Build Coastguard Worker wl_pointer_release(seat->wl_pointer);
584*2b949d04SAndroid Build Coastguard Worker else
585*2b949d04SAndroid Build Coastguard Worker wl_pointer_destroy(seat->wl_pointer);
586*2b949d04SAndroid Build Coastguard Worker }
587*2b949d04SAndroid Build Coastguard Worker
588*2b949d04SAndroid Build Coastguard Worker if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION)
589*2b949d04SAndroid Build Coastguard Worker wl_seat_release(seat->wl_seat);
590*2b949d04SAndroid Build Coastguard Worker else
591*2b949d04SAndroid Build Coastguard Worker wl_seat_destroy(seat->wl_seat);
592*2b949d04SAndroid Build Coastguard Worker
593*2b949d04SAndroid Build Coastguard Worker free(seat->name_str);
594*2b949d04SAndroid Build Coastguard Worker wl_list_remove(&seat->link);
595*2b949d04SAndroid Build Coastguard Worker free(seat);
596*2b949d04SAndroid Build Coastguard Worker }
597*2b949d04SAndroid Build Coastguard Worker
598*2b949d04SAndroid Build Coastguard Worker static void
registry_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)599*2b949d04SAndroid Build Coastguard Worker registry_global(void *data, struct wl_registry *registry, uint32_t name,
600*2b949d04SAndroid Build Coastguard Worker const char *interface, uint32_t version)
601*2b949d04SAndroid Build Coastguard Worker {
602*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy *inter = data;
603*2b949d04SAndroid Build Coastguard Worker
604*2b949d04SAndroid Build Coastguard Worker if (strcmp(interface, "wl_seat") == 0) {
605*2b949d04SAndroid Build Coastguard Worker seat_create(inter, registry, name, version);
606*2b949d04SAndroid Build Coastguard Worker }
607*2b949d04SAndroid Build Coastguard Worker else if (strcmp(interface, "xdg_wm_base") == 0) {
608*2b949d04SAndroid Build Coastguard Worker inter->shell = wl_registry_bind(registry, name,
609*2b949d04SAndroid Build Coastguard Worker &xdg_wm_base_interface,
610*2b949d04SAndroid Build Coastguard Worker MAX(version, 2));
611*2b949d04SAndroid Build Coastguard Worker xdg_wm_base_add_listener(inter->shell, &shell_listener, inter);
612*2b949d04SAndroid Build Coastguard Worker }
613*2b949d04SAndroid Build Coastguard Worker else if (strcmp(interface, "wl_compositor") == 0) {
614*2b949d04SAndroid Build Coastguard Worker inter->compositor = wl_registry_bind(registry, name,
615*2b949d04SAndroid Build Coastguard Worker &wl_compositor_interface,
616*2b949d04SAndroid Build Coastguard Worker MAX(version, 1));
617*2b949d04SAndroid Build Coastguard Worker }
618*2b949d04SAndroid Build Coastguard Worker else if (strcmp(interface, "wl_shm") == 0) {
619*2b949d04SAndroid Build Coastguard Worker inter->shm = wl_registry_bind(registry, name, &wl_shm_interface,
620*2b949d04SAndroid Build Coastguard Worker MAX(version, 1));
621*2b949d04SAndroid Build Coastguard Worker }
622*2b949d04SAndroid Build Coastguard Worker }
623*2b949d04SAndroid Build Coastguard Worker
624*2b949d04SAndroid Build Coastguard Worker static void
registry_delete(void * data,struct wl_registry * registry,uint32_t name)625*2b949d04SAndroid Build Coastguard Worker registry_delete(void *data, struct wl_registry *registry, uint32_t name)
626*2b949d04SAndroid Build Coastguard Worker {
627*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy *inter = data;
628*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat, *tmp;
629*2b949d04SAndroid Build Coastguard Worker
630*2b949d04SAndroid Build Coastguard Worker wl_list_for_each_safe(seat, tmp, &inter->seats, link) {
631*2b949d04SAndroid Build Coastguard Worker if (seat->global_name != name)
632*2b949d04SAndroid Build Coastguard Worker continue;
633*2b949d04SAndroid Build Coastguard Worker
634*2b949d04SAndroid Build Coastguard Worker seat_destroy(seat);
635*2b949d04SAndroid Build Coastguard Worker }
636*2b949d04SAndroid Build Coastguard Worker }
637*2b949d04SAndroid Build Coastguard Worker
638*2b949d04SAndroid Build Coastguard Worker static const struct wl_registry_listener registry_listener = {
639*2b949d04SAndroid Build Coastguard Worker registry_global,
640*2b949d04SAndroid Build Coastguard Worker registry_delete
641*2b949d04SAndroid Build Coastguard Worker };
642*2b949d04SAndroid Build Coastguard Worker
643*2b949d04SAndroid Build Coastguard Worker static void
dpy_disconnect(struct interactive_dpy * inter)644*2b949d04SAndroid Build Coastguard Worker dpy_disconnect(struct interactive_dpy *inter)
645*2b949d04SAndroid Build Coastguard Worker {
646*2b949d04SAndroid Build Coastguard Worker struct interactive_seat *seat, *tmp;
647*2b949d04SAndroid Build Coastguard Worker
648*2b949d04SAndroid Build Coastguard Worker wl_list_for_each_safe(seat, tmp, &inter->seats, link)
649*2b949d04SAndroid Build Coastguard Worker seat_destroy(seat);
650*2b949d04SAndroid Build Coastguard Worker
651*2b949d04SAndroid Build Coastguard Worker if (inter->xdg_surf)
652*2b949d04SAndroid Build Coastguard Worker xdg_surface_destroy(inter->xdg_surf);
653*2b949d04SAndroid Build Coastguard Worker if (inter->xdg_top)
654*2b949d04SAndroid Build Coastguard Worker xdg_toplevel_destroy(inter->xdg_top);
655*2b949d04SAndroid Build Coastguard Worker if (inter->wl_surf)
656*2b949d04SAndroid Build Coastguard Worker wl_surface_destroy(inter->wl_surf);
657*2b949d04SAndroid Build Coastguard Worker if (inter->shell)
658*2b949d04SAndroid Build Coastguard Worker xdg_wm_base_destroy(inter->shell);
659*2b949d04SAndroid Build Coastguard Worker if (inter->compositor)
660*2b949d04SAndroid Build Coastguard Worker wl_compositor_destroy(inter->compositor);
661*2b949d04SAndroid Build Coastguard Worker if (inter->shm)
662*2b949d04SAndroid Build Coastguard Worker wl_shm_destroy(inter->shm);
663*2b949d04SAndroid Build Coastguard Worker
664*2b949d04SAndroid Build Coastguard Worker /* Do one last roundtrip to try to destroy our wl_buffer. */
665*2b949d04SAndroid Build Coastguard Worker wl_display_roundtrip(inter->dpy);
666*2b949d04SAndroid Build Coastguard Worker
667*2b949d04SAndroid Build Coastguard Worker xkb_context_unref(inter->ctx);
668*2b949d04SAndroid Build Coastguard Worker wl_display_disconnect(inter->dpy);
669*2b949d04SAndroid Build Coastguard Worker }
670*2b949d04SAndroid Build Coastguard Worker
671*2b949d04SAndroid Build Coastguard Worker int
main(int argc,char * argv[])672*2b949d04SAndroid Build Coastguard Worker main(int argc, char *argv[])
673*2b949d04SAndroid Build Coastguard Worker {
674*2b949d04SAndroid Build Coastguard Worker int ret;
675*2b949d04SAndroid Build Coastguard Worker struct interactive_dpy inter;
676*2b949d04SAndroid Build Coastguard Worker struct wl_registry *registry;
677*2b949d04SAndroid Build Coastguard Worker
678*2b949d04SAndroid Build Coastguard Worker if (argc != 1) {
679*2b949d04SAndroid Build Coastguard Worker ret = strcmp(argv[1], "--help");
680*2b949d04SAndroid Build Coastguard Worker fprintf(ret ? stderr : stdout, "Usage: %s [--help]\n", argv[0]);
681*2b949d04SAndroid Build Coastguard Worker if (ret)
682*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "unrecognized option: %s\n", argv[1]);
683*2b949d04SAndroid Build Coastguard Worker return ret ? EXIT_INVALID_USAGE : EXIT_SUCCESS;
684*2b949d04SAndroid Build Coastguard Worker }
685*2b949d04SAndroid Build Coastguard Worker
686*2b949d04SAndroid Build Coastguard Worker setlocale(LC_ALL, "");
687*2b949d04SAndroid Build Coastguard Worker
688*2b949d04SAndroid Build Coastguard Worker memset(&inter, 0, sizeof(inter));
689*2b949d04SAndroid Build Coastguard Worker wl_list_init(&inter.seats);
690*2b949d04SAndroid Build Coastguard Worker
691*2b949d04SAndroid Build Coastguard Worker inter.dpy = wl_display_connect(NULL);
692*2b949d04SAndroid Build Coastguard Worker if (!inter.dpy) {
693*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't connect to Wayland server\n");
694*2b949d04SAndroid Build Coastguard Worker ret = -1;
695*2b949d04SAndroid Build Coastguard Worker goto err_out;
696*2b949d04SAndroid Build Coastguard Worker }
697*2b949d04SAndroid Build Coastguard Worker
698*2b949d04SAndroid Build Coastguard Worker inter.ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
699*2b949d04SAndroid Build Coastguard Worker if (!inter.ctx) {
700*2b949d04SAndroid Build Coastguard Worker ret = -1;
701*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't create xkb context\n");
702*2b949d04SAndroid Build Coastguard Worker goto err_out;
703*2b949d04SAndroid Build Coastguard Worker }
704*2b949d04SAndroid Build Coastguard Worker
705*2b949d04SAndroid Build Coastguard Worker registry = wl_display_get_registry(inter.dpy);
706*2b949d04SAndroid Build Coastguard Worker wl_registry_add_listener(registry, ®istry_listener, &inter);
707*2b949d04SAndroid Build Coastguard Worker
708*2b949d04SAndroid Build Coastguard Worker /* The first roundtrip gets the list of advertised globals. */
709*2b949d04SAndroid Build Coastguard Worker wl_display_roundtrip(inter.dpy);
710*2b949d04SAndroid Build Coastguard Worker
711*2b949d04SAndroid Build Coastguard Worker /* The second roundtrip dispatches the events sent after binding, e.g.
712*2b949d04SAndroid Build Coastguard Worker * after binding to wl_seat globals in the first roundtrip, we will get
713*2b949d04SAndroid Build Coastguard Worker * the wl_seat::capabilities event in this roundtrip. */
714*2b949d04SAndroid Build Coastguard Worker wl_display_roundtrip(inter.dpy);
715*2b949d04SAndroid Build Coastguard Worker
716*2b949d04SAndroid Build Coastguard Worker if (!inter.shell || !inter.shm || !inter.compositor) {
717*2b949d04SAndroid Build Coastguard Worker fprintf(stderr, "Required Wayland interfaces %s%s%s unsupported\n",
718*2b949d04SAndroid Build Coastguard Worker (inter.shell) ? "" : "xdg_shell ",
719*2b949d04SAndroid Build Coastguard Worker (inter.shm) ? "" : "wl_shm",
720*2b949d04SAndroid Build Coastguard Worker (inter.compositor) ? "" : "wl_compositor");
721*2b949d04SAndroid Build Coastguard Worker ret = -1;
722*2b949d04SAndroid Build Coastguard Worker goto err_conn;
723*2b949d04SAndroid Build Coastguard Worker }
724*2b949d04SAndroid Build Coastguard Worker
725*2b949d04SAndroid Build Coastguard Worker surface_create(&inter);
726*2b949d04SAndroid Build Coastguard Worker
727*2b949d04SAndroid Build Coastguard Worker tools_disable_stdin_echo();
728*2b949d04SAndroid Build Coastguard Worker do {
729*2b949d04SAndroid Build Coastguard Worker ret = wl_display_dispatch(inter.dpy);
730*2b949d04SAndroid Build Coastguard Worker } while (ret >= 0 && !terminate);
731*2b949d04SAndroid Build Coastguard Worker tools_enable_stdin_echo();
732*2b949d04SAndroid Build Coastguard Worker
733*2b949d04SAndroid Build Coastguard Worker wl_registry_destroy(registry);
734*2b949d04SAndroid Build Coastguard Worker err_conn:
735*2b949d04SAndroid Build Coastguard Worker dpy_disconnect(&inter);
736*2b949d04SAndroid Build Coastguard Worker err_out:
737*2b949d04SAndroid Build Coastguard Worker exit(ret >= 0 ? EXIT_SUCCESS : EXIT_FAILURE);
738*2b949d04SAndroid Build Coastguard Worker }
739