1 #include <assert.h>
2 #include <errno.h>
3 #include <cairo/cairo.h>
4 #include <getopt.h>
5 #include <libinput.h>
6 #include <libudev.h>
7 #include <poll.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/mman.h>
13 #include <time.h>
14 #include <unistd.h>
15 #include <wayland-client.h>
16 #include <xkbcommon/xkbcommon.h>
17 #include "devmgr.h"
18 #include "shm.h"
19 #include "pango.h"
20 #include "wlr-layer-shell-unstable-v1-client-protocol.h"
21 #include "xdg-output-unstable-v1-client-protocol.h"
22
23 struct wsk_keypress {
24 xkb_keysym_t sym;
25 char name[128];
26 char utf8[128];
27 struct wsk_keypress *next;
28 };
29
30 struct wsk_output {
31 struct wl_output *output;
32 int scale;
33 enum wl_output_subpixel subpixel;
34 struct wsk_output *next;
35 };
36
37 struct wsk_state {
38 int devmgr;
39 pid_t devmgr_pid;
40 struct udev *udev;
41 struct libinput *libinput;
42
43 uint32_t foreground, background, specialfg;
44 const char *font;
45 int timeout;
46
47 struct wl_display *display;
48 struct wl_registry *registry;
49 struct wl_compositor *compositor;
50 struct wl_shm *shm;
51 struct wl_seat *seat;
52 struct wl_keyboard *keyboard;
53 struct zxdg_output_manager_v1 *output_mgr;
54 struct zwlr_layer_shell_v1 *layer_shell;
55
56 struct wl_surface *surface;
57 struct zwlr_layer_surface_v1 *layer_surface;
58 uint32_t width, height;
59 bool frame_scheduled, dirty;
60 struct pool_buffer buffers[2];
61 struct pool_buffer *current_buffer;
62 struct wsk_output *output, *outputs;
63
64 struct xkb_state *xkb_state;
65 struct xkb_context *xkb_context;
66 struct xkb_keymap *xkb_keymap;
67
68 struct wsk_keypress *keys;
69 struct timespec last_key;
70
71 bool run;
72 };
73
cairo_set_source_u32(cairo_t * cairo,uint32_t color)74 static void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
75 cairo_set_source_rgba(cairo,
76 (color >> (3*8) & 0xFF) / 255.0,
77 (color >> (2*8) & 0xFF) / 255.0,
78 (color >> (1*8) & 0xFF) / 255.0,
79 (color >> (0*8) & 0xFF) / 255.0);
80 }
81
to_cairo_subpixel_order(enum wl_output_subpixel subpixel)82 static cairo_subpixel_order_t to_cairo_subpixel_order(
83 enum wl_output_subpixel subpixel) {
84 switch (subpixel) {
85 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
86 return CAIRO_SUBPIXEL_ORDER_RGB;
87 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
88 return CAIRO_SUBPIXEL_ORDER_BGR;
89 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
90 return CAIRO_SUBPIXEL_ORDER_VRGB;
91 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
92 return CAIRO_SUBPIXEL_ORDER_VBGR;
93 default:
94 return CAIRO_SUBPIXEL_ORDER_DEFAULT;
95 }
96 return CAIRO_SUBPIXEL_ORDER_DEFAULT;
97 }
98
render_to_cairo(cairo_t * cairo,struct wsk_state * state,int scale,uint32_t * width,uint32_t * height)99 static void render_to_cairo(cairo_t *cairo, struct wsk_state *state,
100 int scale, uint32_t *width, uint32_t *height) {
101 cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
102 cairo_set_source_u32(cairo, state->background);
103 cairo_paint(cairo);
104
105 struct wsk_keypress *key = state->keys;
106 while (key) {
107 bool special = false;
108 const char *name = key->utf8;
109 if (!name[0]) {
110 special = true;
111 cairo_set_source_u32(cairo, state->specialfg);
112 name = key->name;
113 } else {
114 cairo_set_source_u32(cairo, state->foreground);
115 }
116
117 cairo_move_to(cairo, *width, 0);
118
119 int w, h;
120 if (special) {
121 get_text_size(cairo, state->font, &w, &h, NULL, scale, "%s+", name);
122 pango_printf(cairo, state->font, scale, "%s+", name);
123 } else {
124 get_text_size(cairo, state->font, &w, &h, NULL, scale, "%s", name);
125 pango_printf(cairo, state->font, scale, "%s", name);
126 }
127
128 *width = *width + w;
129 if ((int)*height < h) {
130 *height = h;
131 }
132 key = key->next;
133 }
134 }
135
render_frame(struct wsk_state * state)136 static void render_frame(struct wsk_state *state) {
137 cairo_surface_t *recorder = cairo_recording_surface_create(
138 CAIRO_CONTENT_COLOR_ALPHA, NULL);
139 cairo_t *cairo = cairo_create(recorder);
140 cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
141 cairo_font_options_t *fo = cairo_font_options_create();
142 cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
143 cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
144 if (state->output) {
145 cairo_font_options_set_subpixel_order(
146 fo, to_cairo_subpixel_order(state->output->subpixel));
147 }
148 cairo_set_font_options(cairo, fo);
149 cairo_font_options_destroy(fo);
150 cairo_save(cairo);
151 cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
152 cairo_paint(cairo);
153 cairo_restore(cairo);
154
155 int scale = state->output ? state->output->scale : 1;
156 uint32_t width = 0, height = 0;
157 render_to_cairo(cairo, state, scale, &width, &height);
158 if (height / scale != state->height
159 || width / scale != state->width
160 || state->width == 0) {
161 // Reconfigure surface
162 if (width == 0 || height == 0) {
163 wl_surface_attach(state->surface, NULL, 0, 0);
164 } else {
165 zwlr_layer_surface_v1_set_size(
166 state->layer_surface, width / scale, height / scale);
167 }
168
169 // TODO: this could infinite loop if the compositor assigns us a
170 // different height than what we asked for
171 wl_surface_commit(state->surface);
172 } else if (height > 0) {
173 // Replay recording into shm and send it off
174 state->current_buffer = get_next_buffer(state->shm,
175 state->buffers, state->width * scale, state->height * scale);
176 if (!state->current_buffer) {
177 cairo_surface_destroy(recorder);
178 cairo_destroy(cairo);
179 return;
180 }
181 cairo_t *shm = state->current_buffer->cairo;
182
183 cairo_save(shm);
184 cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR);
185 cairo_paint(shm);
186 cairo_restore(shm);
187
188 cairo_set_source_surface(shm, recorder, 0.0, 0.0);
189 cairo_paint(shm);
190
191 wl_surface_set_buffer_scale(state->surface, scale);
192 wl_surface_attach(state->surface,
193 state->current_buffer->buffer, 0, 0);
194 wl_surface_damage_buffer(state->surface, 0, 0,
195 state->width, state->height);
196 wl_surface_commit(state->surface);
197 }
198 }
199
set_dirty(struct wsk_state * state)200 static void set_dirty(struct wsk_state *state) {
201 if (state->frame_scheduled) {
202 state->dirty = true;
203 } else if (state->surface) {
204 render_frame(state);
205 }
206 }
207
layer_surface_configure(void * data,struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1,uint32_t serial,uint32_t width,uint32_t height)208 static void layer_surface_configure(void *data,
209 struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1,
210 uint32_t serial, uint32_t width, uint32_t height) {
211 struct wsk_state *state = data;
212 state->width = width;
213 state->height = height;
214 zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial);
215 set_dirty(state);
216 }
217
layer_surface_closed(void * data,struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1)218 static void layer_surface_closed(void *data,
219 struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1) {
220 struct wsk_state *state = data;
221 state->run = false;
222 }
223
224 static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
225 .configure = layer_surface_configure,
226 .closed = layer_surface_closed,
227 };
228
surface_enter(void * data,struct wl_surface * wl_surface,struct wl_output * output)229 static void surface_enter(void *data,
230 struct wl_surface *wl_surface, struct wl_output *output) {
231 struct wsk_state *state = data;
232 struct wsk_output *wsk_output = state->outputs;
233 while (wsk_output->output != output) {
234 wsk_output = wsk_output->next;
235 }
236 state->output = wsk_output;
237 }
238
surface_leave(void * data,struct wl_surface * wl_surface,struct wl_output * output)239 static void surface_leave(void *data,
240 struct wl_surface *wl_surface, struct wl_output *output) {
241 // Who cares (not really possible with layer shell)
242 }
243
244 static const struct wl_surface_listener wl_surface_listener = {
245 .enter = surface_enter,
246 .leave = surface_leave,
247 };
248
keyboard_keymap(void * data,struct wl_keyboard * wl_keyboard,uint32_t format,int32_t fd,uint32_t size)249 static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
250 uint32_t format, int32_t fd, uint32_t size) {
251 struct wsk_state *state = data;
252 char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
253 if (map_shm == MAP_FAILED) {
254 close(fd);
255 fprintf(stderr, "Unable to mmap keymap: %s", strerror(errno));
256 return;
257 }
258 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
259 munmap(map_shm, size);
260 close(fd);
261 return;
262 }
263
264 struct xkb_keymap *keymap = xkb_keymap_new_from_string(
265 state->xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
266 XKB_KEYMAP_COMPILE_NO_FLAGS);
267 munmap(map_shm, size);
268 close(fd);
269
270 struct xkb_state *xkb_state = xkb_state_new(keymap);
271 xkb_keymap_unref(state->xkb_keymap);
272 xkb_state_unref(state->xkb_state);
273 state->xkb_keymap = keymap;
274 state->xkb_state = xkb_state;
275 }
276
keyboard_enter(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,struct wl_surface * surface,struct wl_array * keys)277 static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard,
278 uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
279 // Who cares
280 }
281
keyboard_leave(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,struct wl_surface * surface)282 static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard,
283 uint32_t serial, struct wl_surface *surface) {
284 // Who cares
285 }
286
keyboard_key(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,uint32_t time,uint32_t key,uint32_t state)287 static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
288 uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
289 // Who cares
290 }
291
keyboard_modifiers(void * data,struct wl_keyboard * wl_keyboard,uint32_t serial,uint32_t mods_depressed,uint32_t mods_latched,uint32_t mods_locked,uint32_t group)292 static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
293 uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
294 uint32_t mods_locked, uint32_t group) {
295 // Who cares
296 }
297
keyboard_repeat_info(void * data,struct wl_keyboard * wl_keyboard,int32_t rate,int32_t delay)298 static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
299 int32_t rate, int32_t delay) {
300 // TODO
301 }
302
303 static const struct wl_keyboard_listener wl_keyboard_listener = {
304 .keymap = keyboard_keymap,
305 .enter = keyboard_enter,
306 .leave = keyboard_leave,
307 .key = keyboard_key,
308 .modifiers = keyboard_modifiers,
309 .repeat_info = keyboard_repeat_info,
310 };
311
seat_capabilities(void * data,struct wl_seat * wl_seat,uint32_t capabilities)312 static void seat_capabilities(
313 void *data, struct wl_seat *wl_seat, uint32_t capabilities) {
314 struct wsk_state *state = data;
315 if (state->keyboard) {
316 // TODO: support multiple seats
317 return;
318 }
319
320 if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
321 fprintf(stderr, "wl_seat does not support keyboard");
322 state->run = false;
323 return;
324 }
325
326 state->keyboard = wl_seat_get_keyboard(wl_seat);
327 wl_keyboard_add_listener(state->keyboard, &wl_keyboard_listener, state);
328 }
329
seat_name(void * data,struct wl_seat * wl_seat,const char * name)330 static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) {
331 struct wsk_state *state = data;
332 /* TODO: support multiple seats */
333 if (libinput_udev_assign_seat(state->libinput, "seat0") != 0) {
334 fprintf(stderr, "Failed to assign libinput seat\n");
335 state->run = false;
336 return;
337 }
338 }
339
340 static const struct wl_seat_listener wl_seat_listener = {
341 .capabilities = seat_capabilities,
342 .name = seat_name,
343 };
344
output_geometry(void * data,struct wl_output * wl_output,int32_t x,int32_t y,int32_t physical_width,int32_t physical_height,int32_t subpixel,const char * make,const char * model,int32_t transform)345 static void output_geometry(void *data, struct wl_output *wl_output,
346 int32_t x, int32_t y, int32_t physical_width, int32_t physical_height,
347 int32_t subpixel, const char *make, const char *model,
348 int32_t transform) {
349 struct wsk_output *output = data;
350 output->subpixel = subpixel;
351 }
352
output_mode(void * data,struct wl_output * wl_output,uint32_t flags,int32_t width,int32_t height,int32_t refresh)353 static void output_mode(void *data, struct wl_output *wl_output,
354 uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
355 // Who cares
356 }
357
output_done(void * data,struct wl_output * wl_output)358 static void output_done(void *data, struct wl_output *wl_output) {
359 // Who cares
360 }
361
output_scale(void * data,struct wl_output * wl_output,int32_t factor)362 static void output_scale(void *data,
363 struct wl_output *wl_output, int32_t factor) {
364 struct wsk_output *output = data;
365 output->scale = factor;
366 }
367
368 static const struct wl_output_listener wl_output_listener = {
369 .geometry = output_geometry,
370 .mode = output_mode,
371 .done = output_done,
372 .scale = output_scale,
373 };
374
registry_global(void * data,struct wl_registry * wl_registry,uint32_t name,const char * interface,uint32_t version)375 static void registry_global(void *data, struct wl_registry *wl_registry,
376 uint32_t name, const char *interface, uint32_t version) {
377 struct wsk_state *state = data;
378 if (strcmp(interface, wl_compositor_interface.name) == 0) {
379 state->compositor = wl_registry_bind(wl_registry,
380 name, &wl_compositor_interface, 4);
381 } else if (strcmp(interface, wl_shm_interface.name) == 0) {
382 state->shm = wl_registry_bind(wl_registry, name, &wl_shm_interface, 1);
383 } else if (strcmp(interface, wl_seat_interface.name) == 0) {
384 state->seat = wl_registry_bind(wl_registry,
385 name, &wl_seat_interface, 5);
386 } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
387 state->output_mgr = wl_registry_bind(wl_registry,
388 name, &zxdg_output_manager_v1_interface, 1);
389 } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
390 state->layer_shell = wl_registry_bind(wl_registry,
391 name, &zwlr_layer_shell_v1_interface, 1);
392 } else if (strcmp(interface, wl_output_interface.name) == 0) {
393 struct wsk_output *output = calloc(1, sizeof(struct wsk_output));
394 output->output = wl_registry_bind(wl_registry,
395 name, &wl_output_interface, 3);
396 output->scale = 1;
397 struct wsk_output **link = &state->outputs;
398 while (*link) {
399 link = &(*link)->next;
400 }
401 *link = output;
402 wl_output_add_listener(output->output, &wl_output_listener, output);
403 }
404 }
405
registry_global_remove(void * data,struct wl_registry * wl_registry,uint32_t name)406 static void registry_global_remove(void *data,
407 struct wl_registry *wl_registry, uint32_t name) {
408 /* This space deliberately left blank */
409 }
410
411 static const struct wl_registry_listener registry_listener = {
412 .global = registry_global,
413 .global_remove = registry_global_remove,
414 };
415
handle_libinput_event(struct wsk_state * state,struct libinput_event * event)416 static void handle_libinput_event(struct wsk_state *state,
417 struct libinput_event *event) {
418 if (!state->xkb_state) {
419 return;
420 }
421
422 enum libinput_event_type event_type = libinput_event_get_type(event);
423 if (event_type != LIBINPUT_EVENT_KEYBOARD_KEY) {
424 return;
425 }
426
427 struct libinput_event_keyboard *kbevent =
428 libinput_event_get_keyboard_event(event);
429
430 uint32_t keycode = libinput_event_keyboard_get_key(kbevent) + 8;
431 enum libinput_key_state key_state =
432 libinput_event_keyboard_get_key_state(kbevent);
433 xkb_state_update_key(state->xkb_state, keycode,
434 key_state == LIBINPUT_KEY_STATE_RELEASED ?
435 XKB_KEY_UP : XKB_KEY_DOWN);
436
437 xkb_keysym_t keysym = xkb_state_key_get_one_sym(state->xkb_state, keycode);
438
439 struct wsk_keypress *keypress;
440 switch (key_state) {
441 case LIBINPUT_KEY_STATE_RELEASED:
442 /* Who cares */
443 break;
444 case LIBINPUT_KEY_STATE_PRESSED:
445 keypress = calloc(1, sizeof(struct wsk_keypress));
446 assert(keypress);
447 keypress->sym = keysym;
448 xkb_keysym_get_name(keypress->sym, keypress->name,
449 sizeof(keypress->name));
450 if (xkb_state_key_get_utf8(state->xkb_state, keycode,
451 keypress->utf8, sizeof(keypress->utf8)) <= 0 ||
452 keypress->utf8[0] <= ' ') {
453 keypress->utf8[0] = '\0';
454 }
455
456 struct wsk_keypress **link = &state->keys;
457 while (*link) {
458 link = &(*link)->next;
459 }
460 *link = keypress;
461 break;
462 }
463
464 clock_gettime(CLOCK_MONOTONIC, &state->last_key);
465 set_dirty(state);
466 }
467
libinput_open_restricted(const char * path,int flags,void * data)468 static int libinput_open_restricted(const char *path,
469 int flags, void *data) {
470 int *fd = data;
471 return devmgr_open(*fd, path);
472 }
473
libinput_close_restricted(int fd,void * data)474 static void libinput_close_restricted(int fd, void *data) {
475 close(fd);
476 }
477
478 static const struct libinput_interface libinput_impl = {
479 .open_restricted = libinput_open_restricted,
480 .close_restricted = libinput_close_restricted,
481 };
482
parse_color(const char * color)483 static uint32_t parse_color(const char *color) {
484 if (color[0] == '#') {
485 ++color;
486 }
487
488 int len = strlen(color);
489 if (len != 6 && len != 8) {
490 fprintf(stderr, "Invalid color %s, defaulting to color "
491 "0xFFFFFFFF\n", color);
492 return 0xFFFFFFFF;
493 }
494 uint32_t res = (uint32_t)strtoul(color, NULL, 16);
495 if (strlen(color) == 6) {
496 res = (res << 8) | 0xFF;
497 }
498 return res;
499 }
500
main(int argc,char * argv[])501 int main(int argc, char *argv[]) {
502 /* NOTICE: This code runs as root */
503 struct wsk_state state = { 0 };
504 if (devmgr_start(&state.devmgr, &state.devmgr_pid, INPUTDEVPATH) > 0) {
505 return 1;
506 }
507
508 /* Begin normal user code: */
509 int ret = 0;
510
511 unsigned int anchor = 0;
512 int margin = 32;
513 state.background = 0x000000CC;
514 state.specialfg = 0xAAAAAAFF;
515 state.foreground = 0xFFFFFFFF;
516 state.font = "monospace 24";
517 state.timeout = 1;
518
519 int c;
520 while ((c = getopt(argc, argv, "hb:f:s:F:t:a:m:o:")) != -1) {
521 switch (c) {
522 case 'b':
523 state.background = parse_color(optarg);
524 break;
525 case 'f':
526 state.foreground = parse_color(optarg);
527 break;
528 case 's':
529 state.specialfg = parse_color(optarg);
530 break;
531 case 'F':
532 state.font = optarg;
533 break;
534 case 't':
535 state.timeout = atoi(optarg);
536 break;
537 case 'a':
538 if (strcmp(optarg, "top") == 0) {
539 anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
540 } else if (strcmp(optarg, "left") == 0) {
541 anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
542 } else if (strcmp(optarg, "right") == 0) {
543 anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
544 } else if (strcmp(optarg, "bottom") == 0) {
545 anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
546 }
547 break;
548 case 'm':
549 margin = atoi(optarg);
550 break;
551 case 'o':
552 fprintf(stderr, "-o is unimplemented\n");
553 return 0;
554 default:
555 fprintf(stderr, "usage: wshowkeys [-b|-f|-s #RRGGBB[AA]] [-F font] "
556 "[-t timeout]\n\t[-a top|left|right|bottom] [-m margin] "
557 "[-o output]\n");
558 return 1;
559 }
560 }
561
562 state.udev = udev_new();
563 if (!state.udev) {
564 fprintf(stderr, "udev_create: %s\n", strerror(errno));
565 ret = 1;
566 goto exit;
567 }
568
569 state.libinput = libinput_udev_create_context(
570 &libinput_impl, &state.devmgr, state.udev);
571 udev_unref(state.udev);
572 if (!state.libinput) {
573 fprintf(stderr, "libinput_udev_create_context: %s\n", strerror(errno));
574 ret = 1;
575 goto exit;
576 }
577
578 state.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
579 if (!state.xkb_context) {
580 fprintf(stderr, "xkb_context_new: %s\n", strerror(errno));
581 ret = 1;
582 goto exit;
583 }
584
585 state.display = wl_display_connect(NULL);
586 if (!state.display) {
587 fprintf(stderr, "wl_display_connect: %s\n", strerror(errno));
588 ret = 1;
589 goto exit;
590 }
591
592 state.registry = wl_display_get_registry(state.display);
593 assert(state.registry);
594 wl_registry_add_listener(state.registry, ®istry_listener, &state);
595 wl_display_roundtrip(state.display);
596
597 struct {
598 const char *name;
599 void *ptr;
600 } need_globals[] = {
601 "wl_compositor", &state.compositor,
602 "wl_shm", &state.shm,
603 "wl_seat", &state.seat,
604 "wlr_layer_shell", &state.layer_shell,
605 };
606 for (size_t i = 0; i < sizeof(need_globals) / sizeof(need_globals[0]); ++i) {
607 if (!need_globals[i].ptr) {
608 fprintf(stderr, "Error: required Wayland interface '%s' "
609 "is not present\n", need_globals[i].name);
610 ret = 1;
611 goto exit;
612 }
613 }
614
615 // TODO: Listener for xdg output
616
617 wl_seat_add_listener(state.seat, &wl_seat_listener, &state);
618 wl_display_roundtrip(state.display);
619
620 state.surface = wl_compositor_create_surface(state.compositor);
621 assert(state.surface);
622 wl_surface_add_listener(state.surface, &wl_surface_listener, &state);
623
624 state.layer_surface = zwlr_layer_shell_v1_get_layer_surface(
625 state.layer_shell, state.surface, NULL,
626 ZWLR_LAYER_SHELL_V1_LAYER_TOP, "showkeys");
627 assert(state.layer_surface);
628 zwlr_layer_surface_v1_add_listener(
629 state.layer_surface, &layer_surface_listener, &state);
630 zwlr_layer_surface_v1_set_size(state.layer_surface, 1, 1);
631 zwlr_layer_surface_v1_set_anchor(state.layer_surface, anchor);
632 zwlr_layer_surface_v1_set_margin(state.layer_surface,
633 margin, margin, margin, margin);
634 zwlr_layer_surface_v1_set_exclusive_zone(state.layer_surface, -1);
635 wl_surface_commit(state.surface);
636
637 struct pollfd pollfds[] = {
638 { .fd = libinput_get_fd(state.libinput), .events = POLLIN, },
639 { .fd = wl_display_get_fd(state.display), .events = POLLIN, },
640 };
641
642 state.run = true;
643 while (state.run) {
644 errno = 0;
645 do {
646 if (wl_display_flush(state.display) == -1 && errno != EAGAIN) {
647 fprintf(stderr, "wl_display_flush: %s\n", strerror(errno));
648 break;
649 }
650 } while (errno == EAGAIN);
651
652 int timeout = -1;
653 if (state.keys) {
654 timeout = 100;
655 }
656
657 if (poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), timeout) < 0) {
658 fprintf(stderr, "poll: %s\n", strerror(errno));
659 break;
660 }
661
662 /* Clear out old keys */
663 struct timespec now;
664 clock_gettime(CLOCK_MONOTONIC, &now);
665 if (now.tv_sec >= state.last_key.tv_sec + state.timeout &&
666 now.tv_nsec >= state.last_key.tv_nsec) {
667 struct wsk_keypress *key = state.keys;
668 while (key) {
669 struct wsk_keypress *next = key->next;
670 free(key);
671 key = next;
672 }
673 state.keys = NULL;
674 set_dirty(&state);
675 }
676
677 if ((pollfds[0].revents & POLLIN)) {
678 if (libinput_dispatch(state.libinput) != 0) {
679 fprintf(stderr, "libinput_dispatch: %s\n", strerror(errno));
680 break;
681 }
682 struct libinput_event *event;
683 while ((event = libinput_get_event(state.libinput))) {
684 handle_libinput_event(&state, event);
685 libinput_event_destroy(event);
686 }
687 }
688
689 if ((pollfds[1].revents & POLLIN)
690 && wl_display_dispatch(state.display) == -1) {
691 fprintf(stderr, "wl_display_dispatch: %s\n", strerror(errno));
692 break;
693 }
694 }
695
696 exit:
697 wl_display_disconnect(state.display);
698 libinput_unref(state.libinput);
699 devmgr_finish(state.devmgr, state.devmgr_pid);
700 return ret;
701 }
702