rofi 2.1.0
display.c
Go to the documentation of this file.
1
24
25#include "helper.h"
26#define G_LOG_DOMAIN "Wayland"
27#pragma GCC diagnostic ignored "-Wunused-variable"
28#pragma GCC diagnostic ignored "-Wunused-parameter"
29
30#include <config.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <locale.h>
34#include <math.h>
35#include <stdint.h>
36#include <sys/mman.h>
37#include <sys/types.h>
38#include <unistd.h>
39
40#include <cairo.h>
41#include <glib.h>
42#include <glib/gstdio.h>
43#include <wayland-client.h>
44#include <wayland-cursor.h>
45#include <xkbcommon/xkbcommon-compose.h>
46#include <xkbcommon/xkbcommon.h>
47
48#include <libgwater-wayland.h>
49
50#include <nkutils-bindings.h>
51
52#include <rofi.h>
53
54#include "input-codes.h"
55#include "keyb.h"
56#include "rofi-types.h"
57#include "settings.h"
58#include "view.h"
59
60#include "display-internal.h"
61#include "display.h"
62#include "wayland-internal.h"
63
64#ifdef HAVE_WAYLAND_CURSOR_SHAPE
65#include "cursor-shape-v1-protocol.h"
66#endif
67#include "keyboard-shortcuts-inhibit-unstable-v1-protocol.h"
68#include "primary-selection-unstable-v1-protocol.h"
69#include "text-input-unstable-v3-protocol.h"
70#include "wlr-layer-shell-unstable-v1-protocol.h"
71
72#define wayland_output_get_dpi(output, scale, dimension) \
73 ((output)->current.physical_##dimension > 0 && (scale) > 0 \
74 ? round((double)(output)->current.dimension * 25.4 / (scale) / \
75 (output)->current.physical_##dimension) \
76 : 0)
77
78/* One wheel detent in the units of wl_pointer.axis_value120. The wheel fields
79 * of a seat hold this unit, and each whole multiple is one scroll step */
80#define WHEEL_DETENT 120
81
83typedef struct {
85 uint32_t global_name;
86 struct wl_output *output;
87 gchar *name;
88 struct {
89 int32_t x;
90 int32_t y;
91 int32_t width;
92 int32_t height;
93 int32_t physical_width; /* mm */
94 int32_t physical_height; /* mm */
95 int32_t scale;
96 int32_t transform;
97 } current, pending;
99
100typedef struct {
102 struct wl_buffer *buffer;
103 uint8_t *data;
104 gboolean released;
106
116
117static gboolean wayland_display_late_setup(void);
118
121static const cairo_user_data_key_t wayland_cairo_surface_user_data;
122
123static const struct zwp_text_input_v3_listener text_input_listener;
124
125static void update_cursor_rectangle(struct zwp_text_input_v3 *text_input) {
127 if (tb == NULL) {
128 return;
129 }
130
131 int menu_x = 0, menu_y = 0;
132 rofi_view_get_menu_rect(&menu_x, &menu_y, NULL, NULL);
133
134 widget *tb_widget = WIDGET(tb);
135 int x = textbox_get_cursor_x_pos(tb);
136 int y = 0;
137
138 for (widget *iter = tb_widget; iter != NULL; iter = iter->parent) {
139 x += iter->x;
140 y += iter->y;
141 }
142
143 x += menu_x;
144 y += menu_y;
145
146 int w = 1;
147 int h = widget_get_height(tb_widget);
148 zwp_text_input_v3_set_cursor_rectangle(text_input, x, y, w, h);
149}
150
151static const struct _view_proxy *wayland_display_view_proxy(void);
152
154 if (!self->to_free) {
155 return;
156 }
157
158 size_t i, count = 0;
159 for (i = 0; i < wayland->buffer_count; ++i) {
160 if ((self->buffers[i].released) && (self->buffers[i].buffer != NULL)) {
161 wl_buffer_destroy(self->buffers[i].buffer);
162 self->buffers[i].buffer = NULL;
163 }
164 if (self->buffers[i].buffer == NULL) {
165 ++count;
166 }
167 }
168
169 if (count < wayland->buffer_count) {
170 return;
171 }
172
173 munmap(self->data, self->size);
174 g_free(self->buffers);
175 g_free(self);
176}
177
178static void wayland_buffer_release(void *data, struct wl_buffer *buffer) {
179 wayland_buffer_pool *self = data;
180
181 size_t i;
182 for (i = 0; i < wayland->buffer_count; ++i) {
183 if (self->buffers[i].buffer == buffer) {
184 self->buffers[i].released = TRUE;
185 }
186 }
187
189}
190
191static const struct wl_buffer_listener wayland_buffer_listener = {
193
195 struct wl_shm_pool *wl_pool;
196 struct wl_buffer *buffer;
197 int fd;
198 uint8_t *data;
199 width *= wayland->scale;
200 height *= wayland->scale;
201 int32_t stride;
202 size_t size;
203 size_t pool_size;
204
205 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
206 if (stride < 0) {
207 g_warning("cairo stride width calculation failure");
208 return NULL;
209 }
210 size = (size_t)stride * height;
211 pool_size = size * wayland->buffer_count;
212
213 gchar *shm_name = "/rofi-wayland-surface";
214 fd = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0600);
215 shm_unlink(shm_name);
216 if (fd < 0) {
217 g_warning("creating a buffer file for %zu B failed: %s", pool_size,
218 g_strerror(errno));
219 return NULL;
220 }
221 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
222 g_close(fd, NULL);
223 return NULL;
224 }
225 if (ftruncate(fd, pool_size) < 0) {
226 g_close(fd, NULL);
227 return NULL;
228 }
229
230 data = mmap(NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
231 if (data == MAP_FAILED) {
232 g_warning("mmap of size %zu failed: %s", pool_size, g_strerror(errno));
233 close(fd);
234 return NULL;
235 }
236
238 pool = g_new0(wayland_buffer_pool, 1);
239 pool->data = data;
240 pool->size = pool_size;
241
242 pool->width = width;
243 pool->height = height;
244
245 pool->buffers = g_new0(wayland_buffer, wayland->buffer_count);
246
247 wl_pool = wl_shm_create_pool(wayland->shm, fd, pool_size);
248 size_t i;
249 for (i = 0; i < wayland->buffer_count; ++i) {
250 pool->buffers[i].pool = pool;
251 pool->buffers[i].buffer = wl_shm_pool_create_buffer(
252 wl_pool, size * i, width, height, stride, WL_SHM_FORMAT_ARGB8888);
253 pool->buffers[i].data = data + size * i;
254 pool->buffers[i].released = TRUE;
255 wl_buffer_add_listener(pool->buffers[i].buffer, &wayland_buffer_listener,
256 pool);
257 }
258 wl_shm_pool_destroy(wl_pool);
259 close(fd);
260
261 return pool;
262}
263
265 if (self == NULL) {
266 return;
267 }
268 self->to_free = TRUE;
270}
271
272static void wayland_surface_protocol_enter(void *data,
273 struct wl_surface *wl_surface,
274 struct wl_output *wl_output) {
275 wayland_output *output;
276
277 output = g_hash_table_lookup(wayland->outputs, wl_output);
278 if (output == NULL) {
279 return;
280 }
281
282 if (config.dpi == 0 || config.dpi == 1) {
283 // DPI auto-detect requested.
284 config.dpi = wayland_output_get_dpi(output, output->current.scale, height);
285 g_debug("Auto-detected DPI: %d", config.dpi);
286 }
287
288 wl_surface_set_buffer_scale(wl_surface, output->current.scale);
289
290 if (wayland->scale != output->current.scale) {
291 wayland->scale = output->current.scale;
292
293 // create new buffers with the correct scaled size
295
297 if (state != NULL) {
298 rofi_view_set_size(state, -1, -1);
299 }
300 }
301}
302
303static void wayland_surface_protocol_leave(void *data,
304 struct wl_surface *wl_surface,
305 struct wl_output *wl_output) {}
306
307static const struct wl_surface_listener wayland_surface_interface = {
310};
311
312static void wayland_frame_callback(void *data, struct wl_callback *callback,
313 uint32_t time);
314
315static const struct wl_callback_listener wayland_frame_wl_callback_listener = {
317};
318
319cairo_surface_t *
321 wayland_buffer *buffer = NULL;
322 size_t i;
323 for (i = 0; (buffer == NULL) && (i < wayland->buffer_count); ++i) {
324 buffer = pool->buffers + i;
325 if (!buffer->released) {
326 buffer = NULL;
327 }
328 }
329 if (buffer == NULL) {
330 return NULL;
331 }
332
333 cairo_surface_t *surface;
334
335 surface = cairo_image_surface_create_for_data(
336 buffer->data, CAIRO_FORMAT_ARGB32, pool->width, pool->height,
337 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pool->width));
338 cairo_surface_set_user_data(surface, &wayland_cairo_surface_user_data, buffer,
339 NULL);
340 return surface;
341}
342
343void display_surface_commit(cairo_surface_t *surface) {
344 if (surface == NULL || wayland->surface == NULL) {
345 return;
346 }
347
348 wayland_buffer *buffer =
349 cairo_surface_get_user_data(surface, &wayland_cairo_surface_user_data);
350 wayland_buffer_pool *pool = buffer->pool;
351
352 cairo_surface_destroy(surface);
353
354 wl_surface_damage(wayland->surface, 0, 0, pool->width, pool->height);
355 wl_surface_attach(wayland->surface, buffer->buffer, 0, 0);
356 // FIXME: hidpi
357 wl_surface_set_buffer_scale(wayland->surface, wayland->scale);
358 buffer->released = FALSE;
359
360 wl_surface_commit(wayland->surface);
361}
362
363static void wayland_frame_callback(void *data, struct wl_callback *callback,
364 uint32_t timestamp) {
365 if (wayland->frame_cb != NULL) {
366 wl_callback_destroy(wayland->frame_cb);
367 wayland->frame_cb = NULL;
369 }
370 if (wayland->surface != NULL) {
371 wayland->frame_cb = wl_surface_frame(wayland->surface);
372 wl_callback_add_listener(wayland->frame_cb,
374 }
375}
376
377static void wayland_keyboard_keymap(void *data, struct wl_keyboard *keyboard,
378 enum wl_keyboard_keymap_format format,
379 int32_t fd, uint32_t size) {
380 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
381 close(fd);
382 return;
383 }
384
385 char *str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
386 if (str == MAP_FAILED) {
387 close(fd);
388 return;
389 }
390
391 struct xkb_keymap *keymap = xkb_keymap_new_from_string(
392 nk_bindings_seat_get_context(wayland->bindings_seat), str,
393 XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
394 if (keymap == NULL) {
395 fprintf(stderr, "Failed to get Keymap for current keyboard device.\n");
396 return;
397 }
398 struct xkb_state *state = xkb_state_new(keymap);
399 if (state == NULL) {
400 fprintf(stderr,
401 "Failed to get state object for current keyboard device.\n");
402 return;
403 }
404
405 nk_bindings_seat_update_keymap(wayland->bindings_seat, keymap, state);
406}
407
408static void wayland_keyboard_enter(void *data, struct wl_keyboard *keyboard,
409 uint32_t serial, struct wl_surface *surface,
410 struct wl_array *keys) {
411 wayland_seat *self = data;
412
413 wayland->last_seat = self;
414 self->serial = serial;
415
416 uint32_t *key, *kend;
417 for (key = keys->data, kend = key + keys->size / sizeof(*key); key < kend;
418 ++key) {
419 nk_bindings_seat_handle_key(wayland->bindings_seat, NULL, *key + 8,
420 NK_BINDINGS_KEY_STATE_PRESSED);
421 }
422}
423
424static void wayland_keyboard_leave(void *data, struct wl_keyboard *keyboard,
425 uint32_t serial,
426 struct wl_surface *surface) {
427 wayland_seat *self = data;
428 // TODO?
429}
430
431static gboolean wayland_key_repeat(void *data) {
432 wayland_seat *self = data;
433
434 if (self->repeat.key == 0) {
435 self->repeat.source = NULL;
436 return G_SOURCE_REMOVE;
437 }
438
439 char *text = nk_bindings_seat_handle_key(wayland->bindings_seat, NULL,
440 self->repeat.key,
441 NK_BINDINGS_KEY_STATE_PRESS);
442
444 if (state == NULL) {
445 return G_SOURCE_REMOVE;
446 }
447
448 if (text != NULL) {
449 rofi_view_handle_text(state, text);
450 }
451
453
454 return G_SOURCE_CONTINUE;
455}
456
457static gboolean wayland_key_repeat_delay(void *data) {
458 wayland_seat *self = data;
459
460 if (self->repeat.key == 0) {
461 return FALSE;
462 }
463
464 char *text = nk_bindings_seat_handle_key(wayland->bindings_seat, NULL,
465 self->repeat.key,
466 NK_BINDINGS_KEY_STATE_PRESS);
467
469 if (state == NULL) {
470 return G_SOURCE_REMOVE;
471 }
472
473 if (text != NULL) {
474 rofi_view_handle_text(state, text);
475 }
476
477 guint repeat_wait_ms = 30;
478 if (self->repeat.rate != 0) {
479 repeat_wait_ms = 1000 / self->repeat.rate;
480 }
481 guint source_id = g_timeout_add(repeat_wait_ms, wayland_key_repeat, data);
482 self->repeat.source = g_main_context_find_source_by_id(NULL, source_id);
483
485
486 return G_SOURCE_REMOVE;
487}
488
489static void wayland_keyboard_key(void *data, struct wl_keyboard *keyboard,
490 uint32_t serial, uint32_t time, uint32_t key,
491 enum wl_keyboard_key_state kstate) {
493 wayland_seat *self = data;
494
495 wayland->last_seat = self;
496 self->serial = serial;
497
498 xkb_keycode_t keycode = key + 8;
499 if (kstate == WL_KEYBOARD_KEY_STATE_RELEASED) {
500 if (keycode == self->repeat.key) {
501 self->repeat.key = 0;
502 if (self->repeat.source != NULL) {
503 g_source_destroy(self->repeat.source);
504 self->repeat.source = NULL;
505 }
506 }
507 nk_bindings_seat_handle_key(wayland->bindings_seat, NULL, keycode,
508 NK_BINDINGS_KEY_STATE_RELEASE);
509 } else if (kstate == WL_KEYBOARD_KEY_STATE_PRESSED) {
510 gchar *text = nk_bindings_seat_handle_key(
511 wayland->bindings_seat, NULL, keycode, NK_BINDINGS_KEY_STATE_PRESS);
512
513 if (self->repeat.source != NULL) {
514 g_source_destroy(self->repeat.source);
515 self->repeat.source = NULL;
516 }
517
518 if (state != NULL) {
519 if (text != NULL) {
520 rofi_view_handle_text(state, text);
521 }
522 self->repeat.key = keycode;
523 guint source_id =
524 g_timeout_add(self->repeat.delay, wayland_key_repeat_delay, data);
525 self->repeat.source = g_main_context_find_source_by_id(NULL, source_id);
526 }
527 }
528
529 if (state != NULL) {
531 }
532}
533
534static void wayland_keyboard_modifiers(void *data, struct wl_keyboard *keyboard,
535 uint32_t serial, uint32_t mods_depressed,
536 uint32_t mods_latched,
537 uint32_t mods_locked, uint32_t group) {
538 wayland_seat *self = data;
539 nk_bindings_seat_update_mask(wayland->bindings_seat, NULL, mods_depressed,
540 mods_latched, mods_locked, 0, 0, group);
541
543 if (state != NULL) {
545 if (self->text_input) {
547 zwp_text_input_v3_commit(self->text_input);
548 }
549 }
550}
551
552static void wayland_keyboard_repeat_info(void *data,
553 struct wl_keyboard *keyboard,
554 int32_t rate, int32_t delay) {
555 wayland_seat *self = data;
556 self->repeat.key = 0;
557 self->repeat.rate = rate;
558 self->repeat.delay = delay;
559 if (self->repeat.source != NULL) {
560 g_source_destroy(self->repeat.source);
561 self->repeat.source = NULL;
562 }
563}
564
565static const struct wl_keyboard_listener wayland_keyboard_listener = {
566 .keymap = wayland_keyboard_keymap,
567 .enter = wayland_keyboard_enter,
568 .leave = wayland_keyboard_leave,
570 .modifiers = wayland_keyboard_modifiers,
571 .repeat_info = wayland_keyboard_repeat_info,
572};
573
574static gboolean wayland_cursor_reload_theme(guint scale);
575
576static void wayland_cursor_set_image(int i) {
577 struct wl_buffer *buffer;
578 struct wl_cursor_image *image;
579 image = wayland->cursor.cursor->images[i];
580
581 wayland->cursor.image = image;
582 buffer = wl_cursor_image_get_buffer(wayland->cursor.image);
583 wl_surface_set_buffer_scale(wayland->cursor.surface, wayland->scale);
584 wl_surface_attach(wayland->cursor.surface, buffer, 0, 0);
585 wl_surface_damage(wayland->cursor.surface, 0, 0, wayland->cursor.image->width,
586 wayland->cursor.image->height);
587 wl_surface_commit(wayland->cursor.surface);
588}
589
590static void wayland_cursor_frame_callback(void *data,
591 struct wl_callback *callback,
592 uint32_t time);
593
594static const struct wl_callback_listener
598
599static void wayland_cursor_frame_callback(void *data,
600 struct wl_callback *callback,
601 uint32_t time) {
602 int i;
603
604 if (wayland->cursor.frame_cb != NULL) {
605 wl_callback_destroy(wayland->cursor.frame_cb);
606 }
607 wayland->cursor.frame_cb = wl_surface_frame(wayland->cursor.surface);
608 wl_callback_add_listener(wayland->cursor.frame_cb,
610
611 i = wl_cursor_frame(wayland->cursor.cursor, time);
613}
614
617
618 if (state == NULL) {
619 return;
620 }
621
622 int menu_x = 0, menu_y = 0, menu_w = 0, menu_h = 0;
623
624 gboolean capture = config.click_to_exit;
625
626 if (capture) {
627 rofi_view_get_menu_rect(&menu_x, &menu_y, &menu_w, &menu_h);
628 if (menu_w <= 0 || menu_h <= 0) {
629 capture = FALSE;
630 }
631 }
632
633 if (self->motion.x > -1 || self->motion.y > -1) {
634 int motion_x = self->motion.x;
635 int motion_y = self->motion.y;
636
637 if (capture) {
638 motion_x -= menu_x;
639 motion_y -= menu_y;
640 }
641
642 rofi_view_handle_mouse_motion(state, motion_x, motion_y,
643 config.hover_select);
644 self->motion.x = -1;
645 self->motion.y = -1;
646 }
647
648 NkBindingsMouseButton button = -1;
649 switch (self->button.button) {
650 case BTN_LEFT:
651 button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
652 break;
653 case BTN_RIGHT:
654 button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
655 break;
656 case BTN_MIDDLE:
657 button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
658 break;
659 }
660
661 if (self->button.button > 0) {
662 gboolean inside = TRUE;
663
664 if (capture) {
665 inside = self->button.x >= menu_x && self->button.x < menu_x + menu_w &&
666 self->button.y >= menu_y && self->button.y < menu_y + menu_h;
667 }
668
669 if (self->button.pressed) {
670 if (capture && !inside) {
671 rofi_view_cancel(state);
672
673 self->button.button = 0;
675 return;
676 }
677
678 int button_x = self->button.x;
679 int button_y = self->button.y;
680
681 if (capture) {
682 button_x -= menu_x;
683 button_y -= menu_y;
684 }
685
686 rofi_view_handle_mouse_motion(state, button_x, button_y, FALSE);
687 nk_bindings_seat_handle_button(wayland->bindings_seat, NULL, button,
688 NK_BINDINGS_BUTTON_STATE_PRESS,
689 self->button.time);
690 } else {
691 if (!capture || inside) {
692 nk_bindings_seat_handle_button(wayland->bindings_seat, NULL, button,
693 NK_BINDINGS_BUTTON_STATE_RELEASE,
694 self->button.time);
695 }
696 }
697
698 self->button.button = 0;
699 }
700
701 if (self->axis_source == WL_POINTER_AXIS_SOURCE_FINGER ||
702 self->axis_source == WL_POINTER_AXIS_SOURCE_CONTINUOUS) {
703 self->wheel.vertical += 20 * self->wheel_continuous.vertical;
704 self->wheel.horizontal += 20 * self->wheel_continuous.horizontal;
705 }
706
707 if (abs(self->wheel.vertical) >= WHEEL_DETENT) {
708 gint v120 = self->wheel.vertical;
709 nk_bindings_seat_handle_scroll(wayland->bindings_seat, NULL,
710 NK_BINDINGS_SCROLL_AXIS_VERTICAL,
711 v120 / WHEEL_DETENT);
712 if (v120 > 0) {
713 self->wheel.vertical = v120 % WHEEL_DETENT;
714 } else {
715 self->wheel.vertical = -((-v120) % WHEEL_DETENT);
716 }
717 }
718
719 if (abs(self->wheel.horizontal) >= WHEEL_DETENT) {
720 gint v120 = self->wheel.horizontal;
721 nk_bindings_seat_handle_scroll(wayland->bindings_seat, NULL,
722 NK_BINDINGS_SCROLL_AXIS_HORIZONTAL,
723 v120 / WHEEL_DETENT);
724 if (v120 > 0) {
725 self->wheel.horizontal = v120 % WHEEL_DETENT;
726 } else {
727 self->wheel.horizontal = -((-v120) % WHEEL_DETENT);
728 }
729 }
730
731 self->axis_source = 0;
732 self->wheel_continuous.vertical = 0;
734
736 if (self->text_input) {
738 zwp_text_input_v3_commit(self->text_input);
739 }
740}
741
742static struct wl_cursor *
743rofi_cursor_type_to_wl_cursor(struct wl_cursor_theme *theme,
744 RofiCursorType type) {
745 static const char *const default_names[] = {
746 "default", "left_ptr", "top_left_arrow", "left-arrow", NULL};
747 static const char *const pointer_names[] = {"pointer", "hand1", NULL};
748 static const char *const text_names[] = {"text", "xterm", NULL};
749
750 const char *const *name;
751 struct wl_cursor *cursor = NULL;
752
753 switch (type) {
755 name = pointer_names;
756 break;
757 case ROFI_CURSOR_TEXT:
758 name = text_names;
759 break;
760 default:
761 name = default_names;
762 break;
763 }
764 for (; cursor == NULL && *name != NULL; ++name) {
765 cursor = wl_cursor_theme_get_cursor(theme, *name);
766 }
767 return cursor;
768}
769
770#ifdef HAVE_WAYLAND_CURSOR_SHAPE
771static enum wp_cursor_shape_device_v1_shape
772rofi_cursor_type_to_wp_cursor_shape(RofiCursorType type) {
773 switch (type) {
775 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER;
776 case ROFI_CURSOR_TEXT:
777 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;
778 default:
779 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
780 }
781}
782#endif
783
785#ifdef HAVE_WAYLAND_CURSOR_SHAPE
786 if (seat->cursor_shape_device != NULL) {
787 wp_cursor_shape_device_v1_set_shape(
788 seat->cursor_shape_device, seat->pointer_serial,
789 rofi_cursor_type_to_wp_cursor_shape(wayland->cursor.type));
790 return;
791 } else if (wayland->cursor.theme == NULL) {
792 // cursor-shape-v1 is available, but the seat haven't seen a pointer yet
793 return;
794 }
795#endif
796
797 if (wayland->cursor.surface == NULL) {
798 wayland->cursor.surface = wl_compositor_create_surface(wayland->compositor);
799 }
800
801 if (wayland->cursor.cursor->image_count < 2) {
803 } else {
804 wayland_cursor_frame_callback(wayland, wayland->cursor.frame_cb, 0);
805 }
806
807 wl_pointer_set_cursor(
808 seat->pointer, seat->pointer_serial, wayland->cursor.surface,
809 wayland->cursor.image->hotspot_x / wayland->cursor.scale,
810 wayland->cursor.image->hotspot_y / wayland->cursor.scale);
811}
812
813static void wayland_pointer_enter(void *data, struct wl_pointer *pointer,
814 uint32_t serial, struct wl_surface *surface,
815 wl_fixed_t x, wl_fixed_t y) {
816 wayland_seat *self = data;
817
818 self->pointer_serial = serial;
819
820#ifdef HAVE_WAYLAND_CURSOR_SHAPE
821 if (wayland->cursor_shape_manager != NULL) {
822 if (self->cursor_shape_device == NULL) {
823 self->cursor_shape_device = wp_cursor_shape_manager_v1_get_pointer(
824 wayland->cursor_shape_manager, pointer);
825 }
826 } else
827#endif
829 return;
830 }
831
833}
834
836 wayland_seat *seat;
837 GHashTableIter iter;
838 struct wl_cursor *cursor;
839
840 if (wayland->cursor.type == type) {
841 return;
842 }
843 wayland->cursor.type = type;
844
845#ifdef HAVE_WAYLAND_CURSOR_SHAPE
846 if (wayland->cursor_shape_manager == NULL)
847#endif
848 {
849 if (wayland->cursor.theme == NULL) {
850 return;
851 }
852
853 cursor = rofi_cursor_type_to_wl_cursor(wayland->cursor.theme, type);
854 if (cursor == NULL) {
855 g_info("Failed to load cursor type %d", type);
856 return;
857 }
858 wayland->cursor.cursor = cursor;
859 }
860
861 g_hash_table_iter_init(&iter, wayland->seats);
862 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
863 if (seat->pointer != NULL) {
865 }
866 }
867}
868
869static void wayland_pointer_leave(void *data, struct wl_pointer *pointer,
870 uint32_t serial, struct wl_surface *surface) {
871 wayland_seat *self = data;
872
873 if (wayland->cursor.frame_cb != NULL) {
874 wl_callback_destroy(wayland->cursor.frame_cb);
875 wayland->cursor.frame_cb = NULL;
876 }
877}
878
879static void wayland_pointer_motion(void *data, struct wl_pointer *pointer,
880 uint32_t time, wl_fixed_t x, wl_fixed_t y) {
881 wayland_seat *self = data;
882
883 self->button.x = wl_fixed_to_int(x);
884 self->button.y = wl_fixed_to_int(y);
885 self->motion.x = wl_fixed_to_int(x);
886 self->motion.y = wl_fixed_to_int(y);
887 self->motion.time = time;
888}
889
890static void wayland_pointer_button(void *data, struct wl_pointer *pointer,
891 uint32_t serial, uint32_t time,
892 uint32_t button,
893 enum wl_pointer_button_state state) {
894 wayland_seat *self = data;
895
896 wayland->last_seat = self;
897 self->serial = serial;
898
899 self->button.time = time;
900 self->button.pressed = (state == WL_POINTER_BUTTON_STATE_PRESSED);
901 self->button.button = button;
902}
903
904static void wayland_pointer_axis(void *data, struct wl_pointer *pointer,
905 uint32_t time, enum wl_pointer_axis axis,
906 wl_fixed_t value) {
907 wayland_seat *self = data;
908
909 switch (axis) {
910 case WL_POINTER_AXIS_VERTICAL_SCROLL:
911 self->wheel_continuous.vertical += wl_fixed_to_double(value);
912 break;
913 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
914 self->wheel_continuous.horizontal += wl_fixed_to_double(value);
915 break;
916 }
917}
918
919static void wayland_pointer_frame(void *data, struct wl_pointer *pointer) {
920 wayland_seat *self = data;
922}
923
924static void
925wayland_pointer_axis_source(void *data, struct wl_pointer *pointer,
926 enum wl_pointer_axis_source axis_source) {
927
928 wayland_seat *self = data;
929 self->axis_source = axis_source;
930}
931
932static void wayland_pointer_axis_stop(void *data, struct wl_pointer *pointer,
933 uint32_t time,
934 enum wl_pointer_axis axis) {}
935
936static void wayland_pointer_axis_discrete(void *data,
937 struct wl_pointer *pointer,
938 enum wl_pointer_axis axis,
939 int32_t discrete) {
940 wayland_seat *self = data;
941
942 // values are multiplied by WHEEL_DETENT for compatibility with the
943 // new high-resolution events
944 switch (axis) {
945 case WL_POINTER_AXIS_VERTICAL_SCROLL:
946 self->wheel.vertical += discrete * WHEEL_DETENT;
947 break;
948 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
949 self->wheel.horizontal += discrete * WHEEL_DETENT;
950 break;
951 }
952}
953
954#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
955static void wayland_pointer_axis120(void *data, struct wl_pointer *wl_pointer,
956 enum wl_pointer_axis axis,
957 int32_t value120) {
958 wayland_seat *self = data;
959
960 switch (axis) {
961 case WL_POINTER_AXIS_VERTICAL_SCROLL:
962 self->wheel.vertical += value120;
963 break;
964 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
965 self->wheel.horizontal += value120;
966 break;
967 }
968}
969#endif
970
971static const struct wl_pointer_listener wayland_pointer_listener = {
972 .enter = wayland_pointer_enter,
973 .leave = wayland_pointer_leave,
974 .motion = wayland_pointer_motion,
975 .button = wayland_pointer_button,
976 .axis = wayland_pointer_axis,
977 .frame = wayland_pointer_frame,
978 .axis_source = wayland_pointer_axis_source,
979 .axis_stop = wayland_pointer_axis_stop,
980#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
981 .axis_value120 = wayland_pointer_axis120,
982#endif
983 .axis_discrete = wayland_pointer_axis_discrete,
984};
985
986/* Touch sends the same events as a pointer. Only the first finger counts,
987 * until it lifts. A finger that stays in TOUCH_TAP_SLOP is a left click where
988 * it touched. The press and the release both go on the lift, so a finger that
989 * moves is not a click. It scrolls along the axis on which it first leaves
990 * TOUCH_AXIS_LOCK, which stays fixed until the lift, so a vertical swipe that
991 * drifts sideways does not jump a column: one wheel step per scroll step,
992 * opposite to the finger, so the list moves with the finger. The step is the
993 * touch-scroll-step option, or else one list element, or else
994 * TOUCH_SCROLL_STEP when the menu shows no list */
995#define TOUCH_TAP_SLOP 8
996#define TOUCH_AXIS_LOCK (2 * TOUCH_TAP_SLOP)
997#define TOUCH_SCROLL_STEP 30
998
1000 gint step = config.touch_scroll_step;
1001
1002 if (step <= 0) {
1004 }
1005 return step > 0 ? step : TOUCH_SCROLL_STEP;
1006}
1007
1008static void wayland_touch_down(void *data, struct wl_touch *touch,
1009 uint32_t serial, uint32_t time,
1010 struct wl_surface *surface, int32_t id,
1011 wl_fixed_t x, wl_fixed_t y) {
1012 wayland_seat *self = data;
1013
1014 if (self->touch_id != -1) {
1015 return;
1016 }
1017 self->touch_id = id;
1018 self->touch_x = wl_fixed_to_int(x);
1019 self->touch_y = wl_fixed_to_int(y);
1021 self->touch_scroll = 0;
1022
1023 wayland->last_seat = self;
1024 self->serial = serial;
1025
1026 self->motion.x = self->touch_x;
1027 self->motion.y = self->touch_y;
1028 self->motion.time = time;
1029}
1030
1031static void wayland_touch_up(void *data, struct wl_touch *touch,
1032 uint32_t serial, uint32_t time, int32_t id) {
1033 wayland_seat *self = data;
1034
1035 if (id != self->touch_id) {
1036 return;
1037 }
1038 self->touch_id = -1;
1039
1040 wayland->last_seat = self;
1041 self->serial = serial;
1042
1043 if (self->touch_axis != WAYLAND_TOUCH_AXIS_NONE) {
1044 return;
1045 }
1046
1047 self->button.x = self->touch_x;
1048 self->button.y = self->touch_y;
1049 self->button.time = time;
1050 self->button.button = BTN_LEFT;
1051 self->button.pressed = TRUE;
1053 self->button.button = BTN_LEFT;
1054 self->button.pressed = FALSE;
1055}
1056
1057static void wayland_touch_motion(void *data, struct wl_touch *touch,
1058 uint32_t time, int32_t id, wl_fixed_t x,
1059 wl_fixed_t y) {
1060 wayland_seat *self = data;
1061 gint px, py, dx, dy, step;
1062 gint *wheel;
1063
1064 if (id != self->touch_id) {
1065 return;
1066 }
1067
1068 px = wl_fixed_to_int(x);
1069 py = wl_fixed_to_int(y);
1070 dx = px - self->touch_x;
1071 dy = py - self->touch_y;
1072
1073 if (self->touch_axis == WAYLAND_TOUCH_AXIS_NONE) {
1074 if (ABS(dx) <= TOUCH_TAP_SLOP && ABS(dy) <= TOUCH_TAP_SLOP) {
1075 return;
1076 }
1078 }
1080 if (ABS(dx) <= TOUCH_AXIS_LOCK && ABS(dy) <= TOUCH_AXIS_LOCK) {
1081 return;
1082 }
1083 self->touch_axis = ABS(dx) > ABS(dy) ? WAYLAND_TOUCH_AXIS_HORIZONTAL
1085 }
1086
1088 self->touch_scroll += dx;
1089 wheel = &self->wheel.horizontal;
1091 } else {
1092 self->touch_scroll += dy;
1093 wheel = &self->wheel.vertical;
1095 }
1096 self->touch_x = px;
1097 self->touch_y = py;
1098
1099 while (self->touch_scroll >= step) {
1100 *wheel -= WHEEL_DETENT;
1101 self->touch_scroll -= step;
1102 }
1103 while (self->touch_scroll <= -step) {
1104 *wheel += WHEEL_DETENT;
1105 self->touch_scroll += step;
1106 }
1107}
1108
1109static void wayland_touch_frame(void *data, struct wl_touch *touch) {
1110 wayland_seat *self = data;
1112}
1113
1114/* The compositor took the touch sequence for its own gesture. Thus the finger
1115 * is not a click or a scroll */
1116static void wayland_touch_cancel(void *data, struct wl_touch *touch) {
1117 wayland_seat *self = data;
1118
1119 self->touch_id = -1;
1121 self->touch_scroll = 0;
1122 self->motion.x = -1;
1123 self->motion.y = -1;
1124}
1125
1126static void wayland_touch_shape(void *data, struct wl_touch *touch, int32_t id,
1127 wl_fixed_t major, wl_fixed_t minor) {}
1128
1129static void wayland_touch_orientation(void *data, struct wl_touch *touch,
1130 int32_t id, wl_fixed_t orientation) {}
1131
1132static const struct wl_touch_listener wayland_touch_listener = {
1133 .down = wayland_touch_down,
1134 .up = wayland_touch_up,
1135 .motion = wayland_touch_motion,
1136 .frame = wayland_touch_frame,
1137 .cancel = wayland_touch_cancel,
1138 .shape = wayland_touch_shape,
1139 .orientation = wayland_touch_orientation,
1140};
1141
1143 if (self->keyboard == NULL) {
1144 return;
1145 }
1146
1147 if (self->text_input) {
1148 zwp_text_input_v3_destroy(self->text_input);
1149 self->text_input = NULL;
1150 }
1151
1152 wl_keyboard_release(self->keyboard);
1153
1154 self->repeat.key = 0;
1155 if (self->repeat.source != NULL) {
1156 g_source_destroy(self->repeat.source);
1157 self->repeat.source = NULL;
1158 }
1159
1160 self->keyboard = NULL;
1161}
1162
1163#define CLIPBOARD_READ_INCREMENT 1024
1164
1172
1173static gboolean clipboard_read_glib_callback(GIOChannel *channel,
1174 GIOCondition condition,
1175 gpointer opaque) {
1176 struct clipboard_read_info *info = opaque;
1177 gsize read;
1178
1179 GIOStatus status =
1180 g_io_channel_read_chars(channel, info->buffer + info->size,
1181 CLIPBOARD_READ_INCREMENT, &read, NULL);
1182 switch (status) {
1183 case G_IO_STATUS_AGAIN:
1184 return TRUE;
1185
1186 case G_IO_STATUS_NORMAL: {
1187 info->size += read;
1188 char *buffer =
1189 g_realloc(info->buffer, info->size + CLIPBOARD_READ_INCREMENT);
1190 if (buffer == NULL) {
1191
1192 g_io_channel_shutdown(channel, FALSE, NULL);
1193 g_io_channel_unref(channel);
1194 if (info->buffer) {
1195 g_free(info->buffer);
1196 }
1197 close(info->fd);
1198 g_free(info);
1199 return FALSE;
1200 }
1201 info->buffer = buffer;
1202 return TRUE;
1203 }
1204
1205 default:
1206 info->buffer[info->size] = '\0';
1207 if (status == G_IO_STATUS_EOF) {
1208 char *str = rofi_force_utf8(info->buffer, info->size);
1209 info->callback(str, info->user_data);
1210 g_free(str);
1211 } else { // G_IO_STATUS_ERROR
1212 g_warning("Could not read data from clipboard");
1213 }
1214 g_io_channel_shutdown(channel, FALSE, NULL);
1215 g_io_channel_unref(channel);
1216 close(info->fd);
1217 if (info->buffer != NULL) {
1218 g_free(info->buffer);
1219 }
1220 g_free(info);
1221 return FALSE;
1222 }
1223}
1224
1226 void *user_data) {
1227 GIOChannel *channel = g_io_channel_unix_new(fd);
1228
1229 struct clipboard_read_info *info = g_malloc(sizeof *info);
1230 if (info == NULL) {
1231 g_io_channel_unref(channel);
1232 close(fd);
1233 return FALSE;
1234 }
1235
1236 info->fd = fd;
1237 info->size = 0;
1238 info->callback = callback;
1239 info->user_data = user_data;
1240 info->buffer = g_malloc(CLIPBOARD_READ_INCREMENT);
1241
1242 if (info->buffer == NULL) {
1243 g_io_channel_unref(channel);
1244 close(info->fd);
1245 g_free(info);
1246 return FALSE;
1247 }
1248
1249 g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
1251
1252 return TRUE;
1253}
1254
1255static void data_offer_handle_offer(void *data, struct wl_data_offer *offer,
1256 const char *mime_type) {}
1257
1259 void *data, struct wl_data_offer *wl_data_offer, uint32_t source_actions) {}
1260
1261static void data_offer_handle_action(void *data,
1262 struct wl_data_offer *wl_data_offer,
1263 uint32_t dnd_action) {}
1264
1265static const struct wl_data_offer_listener data_offer_listener = {
1266 .offer = data_offer_handle_offer,
1267 .source_actions = data_offer_handle_source_actions,
1268 .action = data_offer_handle_action,
1269};
1270
1271static void data_device_handle_data_offer(void *data,
1272 struct wl_data_device *data_device,
1273 struct wl_data_offer *offer) {
1274 wl_data_offer_add_listener(offer, &data_offer_listener, NULL);
1275}
1276
1277static void data_device_handle_enter(void *data,
1278 struct wl_data_device *wl_data_device,
1279 uint32_t serial,
1280 struct wl_surface *surface, wl_fixed_t x,
1281 wl_fixed_t y, struct wl_data_offer *id) {}
1282
1283static void data_device_handle_leave(void *data,
1284 struct wl_data_device *wl_data_device) {}
1285
1286static void data_device_handle_motion(void *data,
1287 struct wl_data_device *wl_data_device,
1288 uint32_t time, wl_fixed_t x,
1289 wl_fixed_t y) {}
1290
1291static void data_device_handle_drop(void *data,
1292 struct wl_data_device *wl_data_device) {}
1293
1295 void *offer) {
1296 clipboard_data *clipboard = &wayland->clipboards[cb_type];
1297
1298 if (clipboard->offer != NULL) {
1299 if (cb_type == CLIPBOARD_DEFAULT) {
1300 wl_data_offer_destroy(clipboard->offer);
1301 } else {
1302 zwp_primary_selection_offer_v1_destroy(clipboard->offer);
1303 }
1304 }
1305 clipboard->offer = offer;
1306}
1307
1308static void data_device_handle_selection(void *data,
1309 struct wl_data_device *data_device,
1310 struct wl_data_offer *offer) {
1312}
1313
1314static const struct wl_data_device_listener data_device_listener = {
1315 .data_offer = data_device_handle_data_offer,
1316 .enter = data_device_handle_enter,
1317 .leave = data_device_handle_leave,
1318 .motion = data_device_handle_motion,
1320 .selection = data_device_handle_selection,
1321};
1322
1323static void
1325 struct zwp_primary_selection_offer_v1 *offer,
1326 const char *mime_type) {}
1327
1328static const struct zwp_primary_selection_offer_v1_listener
1332
1334 void *data, struct zwp_primary_selection_device_v1 *data_device,
1335 struct zwp_primary_selection_offer_v1 *offer) {
1336 zwp_primary_selection_offer_v1_add_listener(
1337 offer, &primary_selection_offer_listener, NULL);
1338}
1339
1341 void *data, struct zwp_primary_selection_device_v1 *data_device,
1342 struct zwp_primary_selection_offer_v1 *offer) {
1344}
1345
1346static const struct zwp_primary_selection_device_v1_listener
1351
1353 if (self->pointer == NULL) {
1354 return;
1355 }
1356
1357#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1358 if (self->cursor_shape_device != NULL) {
1359 wp_cursor_shape_device_v1_destroy(self->cursor_shape_device);
1360 self->cursor_shape_device = NULL;
1361 }
1362#endif
1363
1364 wl_pointer_release(self->pointer);
1365
1366 self->pointer = NULL;
1367}
1368
1370 if (self->touch == NULL) {
1371 return;
1372 }
1373
1374 wl_touch_release(self->touch);
1375
1376 self->touch = NULL;
1377 self->touch_id = -1;
1378}
1379
1384
1385 wl_seat_release(self->seat);
1386
1387 g_hash_table_remove(wayland->seats, self->seat);
1388
1389 g_free(self);
1390}
1391
1392static void wayland_seat_capabilities(void *data, struct wl_seat *seat,
1393 uint32_t capabilities) {
1394 wayland_seat *self = data;
1395
1396 if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) &&
1397 (self->keyboard == NULL)) {
1398 self->keyboard = wl_seat_get_keyboard(self->seat);
1399 wl_keyboard_add_listener(self->keyboard, &wayland_keyboard_listener, self);
1400 if (wayland->text_input_manager) {
1401 self->text_input = zwp_text_input_manager_v3_get_text_input(
1402 wayland->text_input_manager, seat);
1403 zwp_text_input_v3_add_listener(self->text_input, &text_input_listener,
1404 self);
1405 }
1406 } else if ((!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) &&
1407 (self->keyboard != NULL)) {
1409 }
1410
1411 if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && (self->pointer == NULL)) {
1412 self->pointer = wl_seat_get_pointer(self->seat);
1413 wl_pointer_add_listener(self->pointer, &wayland_pointer_listener, self);
1414 } else if ((!(capabilities & WL_SEAT_CAPABILITY_POINTER)) &&
1415 (self->pointer != NULL)) {
1417 }
1418
1419 if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) && (self->touch == NULL)) {
1420 self->touch = wl_seat_get_touch(self->seat);
1421 wl_touch_add_listener(self->touch, &wayland_touch_listener, self);
1422 } else if ((!(capabilities & WL_SEAT_CAPABILITY_TOUCH)) &&
1423 (self->touch != NULL)) {
1425 }
1426
1427 if (wayland->data_device_manager != NULL) {
1428 self->data_device = wl_data_device_manager_get_data_device(
1429 wayland->data_device_manager, seat);
1430 wl_data_device_add_listener(self->data_device, &data_device_listener, NULL);
1431 }
1432
1433 if (wayland->primary_selection_device_manager != NULL) {
1435 zwp_primary_selection_device_manager_v1_get_device(
1436 wayland->primary_selection_device_manager, seat);
1437 zwp_primary_selection_device_v1_add_listener(
1439 NULL);
1440 }
1441}
1442
1443static void wayland_seat_name(void *data, struct wl_seat *seat,
1444 const char *name) {
1445 wayland_seat *self = data;
1446
1447 if (self->name != NULL) {
1448 g_hash_table_remove(wayland->seats_by_name, self->name);
1449 }
1450 self->name = g_strdup(name);
1451 g_hash_table_insert(wayland->seats_by_name, self->name, self);
1452}
1453
1454static const struct wl_seat_listener wayland_seat_listener = {
1455 .capabilities = wayland_seat_capabilities,
1456 .name = wayland_seat_name,
1457};
1458
1459static void text_input_enter(void *data, struct zwp_text_input_v3 *text_input,
1460 struct wl_surface *surface) {
1461 zwp_text_input_v3_enable(text_input);
1462 zwp_text_input_v3_set_content_type(text_input,
1463 ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
1464 ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL);
1465 update_cursor_rectangle(text_input);
1466 zwp_text_input_v3_commit(text_input);
1467}
1468static void text_input_leave(void *data, struct zwp_text_input_v3 *text_input,
1469 struct wl_surface *surface) {
1470 zwp_text_input_v3_disable(text_input);
1471 zwp_text_input_v3_commit(text_input);
1472}
1473
1474static void text_input_preedit_string(void *data,
1475 struct zwp_text_input_v3 *text_input,
1476 const char *text, int32_t cursor_begin,
1477 int32_t cursor_end) {
1479 if (state) {
1481 }
1482 update_cursor_rectangle(text_input);
1483 zwp_text_input_v3_commit(text_input);
1484}
1485
1486static void text_input_commit_string(void *data,
1487 struct zwp_text_input_v3 *text_input,
1488 const char *text) {
1489 if (text == NULL) {
1490 return;
1491 }
1492
1494 if (state) {
1495 rofi_view_handle_text(state, text);
1497 }
1498 update_cursor_rectangle(text_input);
1499 zwp_text_input_v3_commit(text_input);
1500}
1501
1503 void *data, struct zwp_text_input_v3 *text_input, uint32_t before_length,
1504 uint32_t after_length) {}
1505
1506static void text_input_done(void *data, struct zwp_text_input_v3 *text_input,
1507 uint32_t serial) {
1509 if (state) {
1511 }
1512}
1513
1514static const struct zwp_text_input_v3_listener text_input_listener = {
1515 .enter = text_input_enter,
1516 .leave = text_input_leave,
1517 .preedit_string = text_input_preedit_string,
1518 .commit_string = text_input_commit_string,
1519 .delete_surrounding_text = text_input_delete_surrounding_text,
1520 .done = text_input_done,
1521};
1522
1524 g_debug("Output release: %s", self->name);
1525
1526 if (wl_output_get_version(self->output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) {
1527 wl_output_release(self->output);
1528 } else {
1529 wl_output_destroy(self->output);
1530 }
1531
1532 g_hash_table_remove(wayland->outputs, self->output);
1533
1534 g_free(self->name);
1535 g_free(self);
1536}
1537
1538static wayland_output *wayland_output_by_name(const char *name) {
1539#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1540 GHashTableIter iter;
1541 wayland_output *output;
1542
1543 g_debug("Monitor lookup by name : %s", name);
1544
1545 g_hash_table_iter_init(&iter, wayland->outputs);
1546 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1547 if (g_strcmp0(output->name, name) == 0) {
1548 return output;
1549 }
1550 }
1551#endif
1552 g_debug("Monitor lookup by name failed: %s", name);
1553
1554 return NULL;
1555}
1557 double retv = -1.0;
1558 if (wayland == 0) {
1559 return -1.0;
1560 }
1561 gsize noutputs = g_hash_table_size(wayland->outputs);
1562 if (noutputs == 1) {
1563 GHashTableIter iter;
1564 wayland_output *output;
1565 g_hash_table_iter_init(&iter, wayland->outputs);
1566 if (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1567 return wayland_output_get_dpi(output, output->current.scale, height);
1568 }
1569 } else if (noutputs > 1 && config.monitor != NULL) {
1570 wayland_output *output = wayland_output_by_name(config.monitor);
1571 if (output != NULL) {
1572 return wayland_output_get_dpi(output, output->current.scale, height);
1573 }
1574 }
1575 return retv;
1576}
1577
1578static void wayland_output_done(void *data, struct wl_output *output) {
1579 wayland_output *self = data;
1580
1581 self->current = self->pending;
1582
1583 g_debug("Output %s: %" PRIi32 "x%" PRIi32 " (%" PRIi32 "x%" PRIi32 "mm)"
1584 " position %" PRIi32 "x%" PRIi32 " scale %" PRIi32
1585 " transform %" PRIi32,
1586 self->name ? self->name : "Unknown", self->current.width,
1587 self->current.height, self->current.physical_width,
1588 self->current.physical_height, self->current.x, self->current.y,
1589 self->current.scale, self->current.transform);
1590}
1591
1592static void wayland_output_geometry(void *data, struct wl_output *output,
1593 int32_t x, int32_t y, int32_t width,
1594 int32_t height, int32_t subpixel,
1595 const char *make, const char *model,
1596 int32_t transform) {
1597 wayland_output *self = data;
1598
1599 self->pending.x = x;
1600 self->pending.y = y;
1601 self->pending.physical_width = width;
1602 self->pending.physical_height = height;
1603 self->pending.transform = transform;
1604}
1605
1606static void wayland_output_mode(void *data, struct wl_output *output,
1607 enum wl_output_mode flags, int32_t width,
1608 int32_t height, int32_t refresh) {
1609 if (flags & WL_OUTPUT_MODE_CURRENT) {
1610 wayland_output *self = data;
1611 self->pending.width = width;
1612 self->pending.height = height;
1613 }
1614}
1615
1616static void wayland_output_scale(void *data, struct wl_output *output,
1617 int32_t scale) {
1618 wayland_output *self = data;
1619
1620 self->pending.scale = scale;
1621}
1622
1623#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1624static void wayland_output_name(void *data, struct wl_output *output,
1625 const char *name) {
1626 wayland_output *self = data;
1627
1628 g_free(self->name);
1629 self->name = g_strdup(name);
1630}
1631#endif
1632
1633#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
1634static void wayland_output_description(void *data, struct wl_output *output,
1635 const char *name) {}
1636#endif
1637
1638static const struct wl_output_listener wayland_output_listener = {
1639 .geometry = wayland_output_geometry,
1640 .mode = wayland_output_mode,
1641 .scale = wayland_output_scale,
1642 .done = wayland_output_done,
1643#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1644 .name = wayland_output_name,
1645#endif
1646#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
1647 .description = wayland_output_description,
1648#endif
1649};
1650
1651static void wayland_registry_handle_global(void *data,
1652 struct wl_registry *registry,
1653 uint32_t name, const char *interface,
1654 uint32_t version) {
1655 g_debug("wayland registry: interface %s", interface);
1656
1657 if (g_strcmp0(interface, wl_compositor_interface.name) == 0) {
1658 wayland->global_names[WAYLAND_GLOBAL_COMPOSITOR] = name;
1659 wayland->compositor =
1660 wl_registry_bind(registry, name, &wl_compositor_interface,
1661 MIN(version, WL_COMPOSITOR_INTERFACE_VERSION));
1662 } else if (g_strcmp0(interface, zwlr_layer_shell_v1_interface.name) == 0) {
1663 wayland->global_names[WAYLAND_GLOBAL_LAYER_SHELL] = name;
1664 wayland->layer_shell =
1665 wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface,
1666 MIN(version, WL_LAYER_SHELL_INTERFACE_VERSION));
1667 } else if (g_strcmp0(
1668 interface,
1669 zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) ==
1670 0) {
1672 wayland->kb_shortcuts_inhibit_manager = wl_registry_bind(
1673 registry, name, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface,
1675 } else if (g_strcmp0(interface, wl_shm_interface.name) == 0) {
1676 wayland->global_names[WAYLAND_GLOBAL_SHM] = name;
1677 wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface,
1678 MIN(version, WL_SHM_INTERFACE_VERSION));
1679 } else if (g_strcmp0(interface, wl_seat_interface.name) == 0) {
1680 if (version < WL_SEAT_INTERFACE_MIN_VERSION) {
1681 g_error("Minimum version of wayland seat interface is %u, got %u",
1683 return;
1684 }
1685 version = MIN(version, WL_SEAT_INTERFACE_MAX_VERSION);
1686
1687 wayland_seat *seat = g_new0(wayland_seat, 1);
1688 seat->context = wayland;
1689 seat->global_name = name;
1690 seat->touch_id = -1;
1691 seat->seat = wl_registry_bind(registry, name, &wl_seat_interface, version);
1692 g_hash_table_insert(wayland->seats, seat->seat, seat);
1693
1694 wl_seat_add_listener(seat->seat, &wayland_seat_listener, seat);
1695 } else if (g_strcmp0(interface, wl_output_interface.name) == 0) {
1696 if (version < WL_OUTPUT_INTERFACE_MIN_VERSION) {
1697 g_error("Minimum version of wayland output interface is %u, got %u",
1699 return;
1700 }
1701 version = MIN(version, WL_OUTPUT_INTERFACE_MAX_VERSION);
1702
1703 wayland_output *output = g_new0(wayland_output, 1);
1704 output->context = wayland;
1705 output->global_name = name;
1706 output->output =
1707 wl_registry_bind(registry, name, &wl_output_interface, version);
1708 output->pending.scale = 1;
1709 output->current = output->pending;
1710
1711 g_hash_table_insert(wayland->outputs, output->output, output);
1712
1713 wl_output_add_listener(output->output, &wayland_output_listener, output);
1714 } else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
1715 wayland->data_device_manager =
1716 wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3);
1717 } else if (strcmp(interface,
1718 zwp_primary_selection_device_manager_v1_interface.name) ==
1719 0) {
1720 wayland->primary_selection_device_manager = wl_registry_bind(
1721 registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
1722 }
1723#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1724 else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
1725 wayland->global_names[WAYLAND_GLOBAL_CURSOR_SHAPE] = name;
1726 wayland->cursor_shape_manager = wl_registry_bind(
1727 registry, name, &wp_cursor_shape_manager_v1_interface, 1);
1728 }
1729#endif
1730 else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
1731 wayland->text_input_manager = wl_registry_bind(
1732 registry, name, &zwp_text_input_manager_v3_interface, 1);
1733 }
1734}
1735
1737 struct wl_registry *registry,
1738 uint32_t name) {
1740 for (i = 0; i < _WAYLAND_GLOBAL_SIZE; ++i) {
1741 if (wayland->global_names[i] != name) {
1742 continue;
1743 }
1744 wayland->global_names[i] = 0;
1745
1746 switch (i) {
1748 wl_compositor_destroy(wayland->compositor);
1749 wayland->compositor = NULL;
1750 break;
1752#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1753 wp_cursor_shape_manager_v1_destroy(wayland->cursor_shape_manager);
1754 wayland->cursor_shape_manager = NULL;
1755#endif
1756 break;
1758 zwlr_layer_shell_v1_destroy(wayland->layer_shell);
1759 wayland->layer_shell = NULL;
1760 break;
1762 zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(
1763 wayland->kb_shortcuts_inhibit_manager);
1764 wayland->kb_shortcuts_inhibit_manager = NULL;
1765 break;
1766 case WAYLAND_GLOBAL_SHM:
1767 wl_shm_destroy(wayland->shm);
1768 wayland->shm = NULL;
1769 break;
1771 g_assert_not_reached();
1772 }
1773 return;
1774 }
1775 if ((wayland->cursor.theme != NULL) &&
1776 ((wayland->compositor == NULL) || (wayland->shm == NULL))) {
1777 if (wayland->cursor.frame_cb != NULL) {
1778 wl_callback_destroy(wayland->cursor.frame_cb);
1779 wayland->cursor.frame_cb = NULL;
1780 }
1781
1782 wl_surface_destroy(wayland->cursor.surface);
1783 wl_cursor_theme_destroy(wayland->cursor.theme);
1784 wayland->cursor.surface = NULL;
1785 wayland->cursor.image = NULL;
1786 wayland->cursor.cursor = NULL;
1787 wayland->cursor.theme = NULL;
1788 wayland->cursor.scale = 0;
1789 }
1790
1791 GHashTableIter iter;
1792
1793 wayland_seat *seat;
1794 g_hash_table_iter_init(&iter, wayland->seats);
1795 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
1796 if (seat->global_name != name) {
1797 continue;
1798 }
1799
1800 g_hash_table_iter_remove(&iter);
1802 return;
1803 }
1804
1805 wayland_output *output;
1806 g_hash_table_iter_init(&iter, wayland->outputs);
1807 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1808 if (output->global_name != name) {
1809 continue;
1810 }
1811
1812 g_hash_table_iter_remove(&iter);
1813 wayland_output_release(output);
1814 return;
1815 }
1816}
1817
1818static const struct wl_registry_listener wayland_registry_listener = {
1821};
1822
1824 void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial,
1825 uint32_t width, uint32_t height) {
1826 wayland->layer_width = width;
1827 wayland->layer_height = height;
1828 zwlr_layer_surface_v1_ack_configure(surface, serial);
1829}
1830
1831static void wayland_surface_destroy(void) {
1832 if (wayland->wlr_surface != NULL) {
1833 zwlr_layer_surface_v1_destroy(wayland->wlr_surface);
1834 wayland->wlr_surface = NULL;
1835 }
1836 if (wayland->surface != NULL) {
1837 wl_surface_destroy(wayland->surface);
1838 wayland->surface = NULL;
1839 }
1840}
1841
1842static void
1844 struct zwlr_layer_surface_v1 *surface) {
1845 g_debug("Layer shell surface closed");
1846
1848
1849 // In this case, we recreate the layer shell surface the best we can and
1850 // re-initialize everything:
1851
1852 // recreate layer shell
1854
1855 // create new buffers with the correct scaled size
1857
1859 if (state != NULL) {
1860 rofi_view_set_size(state, -1, -1);
1861 }
1862}
1863
1864static const struct zwlr_layer_surface_v1_listener
1869
1870static gboolean wayland_error(gpointer user_data) {
1871 g_main_loop_quit(wayland->main_loop);
1872 return G_SOURCE_REMOVE;
1873}
1874
1875static gboolean wayland_cursor_reload_theme(guint scale) {
1876 if (wayland->cursor.theme != NULL) {
1877 if (wayland->cursor.scale == scale)
1878 return TRUE;
1879
1880 wl_cursor_theme_destroy(wayland->cursor.theme);
1881 wayland->cursor.theme = NULL;
1882 wayland->cursor.cursor = NULL;
1883 }
1884
1885 guint64 cursor_size = 24;
1886 char *env_cursor_size = (char *)g_getenv("XCURSOR_SIZE");
1887 if (env_cursor_size && strlen(env_cursor_size) > 0) {
1888 guint64 size = g_ascii_strtoull(env_cursor_size, NULL, 10);
1889 if (0 < size && size < G_MAXUINT64) {
1890 cursor_size = size;
1891 }
1892 }
1893 cursor_size *= scale;
1894
1895 wayland->cursor.theme = wl_cursor_theme_load(wayland->cursor.theme_name,
1896 cursor_size, wayland->shm);
1897 if (wayland->cursor.theme != NULL) {
1898 wayland->cursor.cursor = rofi_cursor_type_to_wl_cursor(
1899 wayland->cursor.theme, wayland->cursor.type);
1900 if (wayland->cursor.cursor == NULL) {
1901 wl_cursor_theme_destroy(wayland->cursor.theme);
1902 wayland->cursor.theme = NULL;
1903 return FALSE;
1904 } else {
1905 wayland->cursor.scale = scale;
1906 return TRUE;
1907 }
1908 }
1909 return FALSE;
1910}
1911
1912static gboolean wayland_display_setup(GMainLoop *main_loop,
1913 NkBindings *bindings) {
1914 wayland->main_loop = main_loop;
1915
1916 char *display = (char *)g_getenv("WAYLAND_DISPLAY");
1917 wayland->main_loop_source = g_water_wayland_source_new(NULL, display);
1918 if (wayland->main_loop_source == NULL) {
1919 g_warning("Could not connect to the Wayland compositor");
1920 return FALSE;
1921 }
1922
1923 g_water_wayland_source_set_error_callback(wayland->main_loop_source,
1924 wayland_error, NULL, NULL);
1925
1926 wayland->buffer_count = 3;
1927 wayland->cursor.type = ROFI_CURSOR_DEFAULT;
1928 wayland->scale = 1;
1929
1930 wayland->outputs = g_hash_table_new(g_direct_hash, g_direct_equal);
1931 wayland->seats = g_hash_table_new(g_direct_hash, g_direct_equal);
1932 wayland->seats_by_name =
1933 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1934
1935 wayland->display =
1936 g_water_wayland_source_get_display(wayland->main_loop_source);
1937 wayland->registry = wl_display_get_registry(wayland->display);
1938 wl_registry_add_listener(wayland->registry, &wayland_registry_listener, NULL);
1939 wl_display_roundtrip(wayland->display);
1940
1941 if (wayland->compositor == NULL || wayland->shm == NULL ||
1942 g_hash_table_size(wayland->outputs) == 0 ||
1943 g_hash_table_size(wayland->seats) == 0) {
1944 g_error("Could not connect to wayland compositor");
1945 return FALSE;
1946 }
1947 if (wayland->layer_shell == NULL) {
1948 g_error("Rofi on wayland requires support for the layer shell protocol");
1949 return FALSE;
1950 }
1951
1952 wayland->bindings_seat = nk_bindings_seat_new(bindings, XKB_CONTEXT_NO_FLAGS);
1953
1954 // Wait for output information
1955 wl_display_roundtrip(wayland->display);
1956
1957 return TRUE;
1958}
1959
1960static gboolean wayland_display_late_setup(void) {
1961 wayland_output *output = wayland_output_by_name(config.monitor);
1962
1963 struct wl_output *wlo = NULL;
1964 if (output != NULL) {
1965 wlo = output->output;
1966 }
1967 wayland->surface = wl_compositor_create_surface(wayland->compositor);
1968
1969 uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
1970 if (strcmp(config.wayland_layer, "overlay") == 0) {
1971 layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
1972 } else if (strcmp(config.wayland_layer, "top") == 0) {
1973 layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
1974 } else if (strcmp(config.wayland_layer, "bottom") == 0) {
1975 layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
1976 } else if (strcmp(config.wayland_layer, "background") == 0) {
1977 layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
1978 } else {
1979 layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
1980 g_warning("Unknown wayland layer: %s, using default overlay",
1981 config.wayland_layer);
1982 }
1983 wayland->wlr_surface = zwlr_layer_shell_v1_get_layer_surface(
1984 wayland->layer_shell, wayland->surface, wlo, layer, "rofi");
1985
1986 // Set size zero and anchor on all corners to get the usable screen size
1987 // see https://github.com/swaywm/wlroots/pull/2422
1988 zwlr_layer_surface_v1_set_anchor(wayland->wlr_surface,
1989 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
1990 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
1991 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
1992 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
1993 zwlr_layer_surface_v1_set_size(wayland->wlr_surface, 0, 0);
1994 zwlr_layer_surface_v1_set_keyboard_interactivity(wayland->wlr_surface, 1);
1995 zwlr_layer_surface_v1_add_listener(
1996 wayland->wlr_surface, &wayland_layer_shell_surface_listener, NULL);
1997
1998 if (config.global_kb && wayland->kb_shortcuts_inhibit_manager) {
1999 g_debug("inhibit shortcuts from compositor");
2000 GHashTableIter iter;
2001 wayland_seat *seat;
2002 g_hash_table_iter_init(&iter, wayland->seats);
2003 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
2004 // we don't need to keep track of these, they will get inactive when the
2005 // surface is destroyed
2006 zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(
2007 wayland->kb_shortcuts_inhibit_manager, wayland->surface, seat->seat);
2008 }
2009 }
2010
2011 wl_surface_add_listener(wayland->surface, &wayland_surface_interface,
2012 wayland);
2013 wl_surface_commit(wayland->surface);
2014 wl_display_roundtrip(wayland->display);
2015 wayland_frame_callback(wayland, wayland->frame_cb, 0);
2016
2017 return TRUE;
2018}
2019
2020gboolean display_get_surface_dimensions(int *width, int *height) {
2021 if (wayland->layer_width != 0) {
2022 if (width != NULL) {
2023 *width = wayland->layer_width;
2024 }
2025 if (height != NULL) {
2026 *height = wayland->layer_height;
2027 }
2028 return TRUE;
2029 }
2030 return FALSE;
2031}
2032
2033/* Click-capture is limited to the current output. If the menu is larger than
2034 * the monitor and visually overflows onto another output, the overflowed area
2035 * will not be part of the capture surface and clicks there will not trigger
2036 * click-to-exit.
2037 */
2038void display_set_surface_dimensions(int width, int height, int x_margin,
2039 int y_margin, int loc) {
2040
2041 wayland->layer_width = width;
2042 wayland->layer_height = height;
2043 zwlr_layer_surface_v1_set_size(wayland->wlr_surface, width, height);
2044
2045 uint32_t wlr_anchor = 0;
2046 switch (loc) {
2047 case WL_NORTH_WEST:
2048 wlr_anchor =
2049 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
2050 break;
2051 case WL_NORTH:
2052 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
2053 break;
2054 case WL_NORTH_EAST:
2055 wlr_anchor =
2056 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
2057 break;
2058 case WL_EAST:
2059 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
2060 break;
2061 case WL_SOUTH_EAST:
2062 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
2063 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
2064 break;
2065 case WL_SOUTH:
2066 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
2067 break;
2068 case WL_SOUTH_WEST:
2069 wlr_anchor =
2070 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
2071 break;
2072 case WL_WEST:
2073 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
2074 break;
2075 case WL_CENTER:
2076 default:
2077 break;
2078 }
2079
2080 if (height == 0) {
2081 wlr_anchor |=
2082 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
2083 }
2084 if (width == 0) {
2085 wlr_anchor |=
2086 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
2087 }
2088
2089 zwlr_layer_surface_v1_set_anchor(wayland->wlr_surface, wlr_anchor);
2090
2091 // NOTE: Setting margin for edges we are not anchored to has no effect, so
2092 // we can safely set contradictory margins (e.g. top vs bottom) - at most
2093 // one of the margins on a given axis will have effect. This also means that
2094 // margin has no effect if the window is centered. :(
2095 zwlr_layer_surface_v1_set_margin(wayland->wlr_surface, y_margin, -x_margin,
2096 -y_margin, x_margin);
2097}
2098
2100 if (wayland->main_loop_source == NULL) {
2101 return;
2102 }
2103
2105 wl_display_flush(wayland->display);
2106}
2107
2108static void wayland_display_cleanup(void) {
2109 if (wayland->main_loop_source == NULL) {
2110 return;
2111 }
2112
2113 nk_bindings_seat_free(wayland->bindings_seat);
2114 g_hash_table_unref(wayland->seats_by_name);
2115 g_hash_table_unref(wayland->seats);
2116 g_hash_table_unref(wayland->outputs);
2117 wl_registry_destroy(wayland->registry);
2118 wl_display_flush(wayland->display);
2119 g_water_wayland_source_free(wayland->main_loop_source);
2120}
2121
2123 int is_term = isatty(fileno(stdout));
2124 GHashTableIter iter;
2125 wayland_output *output;
2126
2127 g_hash_table_iter_init(&iter, wayland->outputs);
2128 printf("Monitor layout:\n");
2129 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
2130 printf("%s ID%s: %" PRIu32, is_term ? color_bold : "",
2131 is_term ? color_reset : "", output->global_name);
2132 printf("\n");
2133 printf("%s name%s: %s\n", is_term ? color_bold : "",
2134 is_term ? color_reset : "", output->name);
2135 printf("%s scale%s: %" PRIi32 "\n", is_term ? color_bold : "",
2136 is_term ? color_reset : "", output->current.scale);
2137 printf("%s position%s: %" PRIi32 ",%" PRIi32 "\n",
2138 is_term ? color_bold : "", is_term ? color_reset : "",
2139 output->current.x, output->current.y);
2140 printf("%s size%s: %" PRIi32 ",%" PRIi32 "\n",
2141 is_term ? color_bold : "", is_term ? color_reset : "",
2142 output->current.width, output->current.height);
2143
2144 if (output->current.physical_width > 0 &&
2145 output->current.physical_height > 0) {
2146 printf("%s size%s: %" PRIi32 "mm,%" PRIi32
2147 "mm dpi: %.0f,%.0f\n",
2148 is_term ? color_bold : "", is_term ? color_reset : "",
2150 wayland_output_get_dpi(output, output->current.scale, width),
2151 wayland_output_get_dpi(output, output->current.scale, height));
2152 }
2153 printf("\n");
2154 }
2155}
2156
2157static void
2159 GSpawnChildSetupFunc *child_setup,
2160 gpointer *user_data) {}
2161
2163 // TODO: do something?
2164 return FALSE;
2165}
2166
2167static void wayland_display_set_input_focus(guint w) {}
2168
2170
2171static const struct _view_proxy *wayland_display_view_proxy(void) {
2172 return wayland_view_proxy;
2173}
2174
2175static guint wayland_display_scale(void) { return wayland->scale; }
2176
2177static void wayland_get_clipboard_data(int cb_type, ClipboardCb callback,
2178 void *user_data) {
2179 clipboard_data *clipboard = &wayland->clipboards[cb_type];
2180
2181 if (clipboard->offer == NULL) {
2182 return;
2183 }
2184
2185 int fds[2];
2186 if (pipe(fds) < 0) {
2187 return;
2188 }
2189
2190 if (cb_type == CLIPBOARD_DEFAULT) {
2191 wl_data_offer_receive(clipboard->offer, "text/plain;charset=utf-8", fds[1]);
2192 } else {
2193 zwp_primary_selection_offer_v1_receive(clipboard->offer,
2194 "text/plain;charset=utf-8", fds[1]);
2195 }
2196 close(fds[1]);
2197
2198 clipboard_read_data(fds[0], callback, user_data);
2199}
2200
2202 if (!wayland->wlr_surface) {
2203 return;
2204 }
2205 zwlr_layer_surface_v1_set_exclusive_zone(wayland->wlr_surface, -1);
2206 zwlr_layer_surface_v1_set_size(wayland->wlr_surface, 0, 0);
2207 wl_surface_commit(wayland->surface);
2208 wl_display_roundtrip(wayland->display);
2209
2211}
2212
2214 .setup = wayland_display_setup,
2215 .late_setup = wayland_display_late_setup,
2216 .early_cleanup = wayland_display_early_cleanup,
2217 .cleanup = wayland_display_cleanup,
2218 .dump_monitor_layout = wayland_display_dump_monitor_layout,
2219 .startup_notification = wayland_display_startup_notification,
2220 .monitor_active = wayland_display_monitor_active,
2221 .set_input_focus = wayland_display_set_input_focus,
2222 .revert_input_focus = wayland_display_revert_input_focus,
2223 .scale = wayland_display_scale,
2224 .get_clipboard_data = wayland_get_clipboard_data,
2225 .set_fullscreen_mode = wayland_set_fullscreen_mode,
2226
2228};
2229
struct _display_proxy display_proxy
void(* ClipboardCb)(const char *clipboard_data, void *user_data)
Definition display.h:130
clipboard_type
Definition display.h:125
@ CLIPBOARD_DEFAULT
Definition display.h:126
@ CLIPBOARD_PRIMARY
Definition display.h:127
struct _workarea workarea
@ WL_SOUTH_EAST
Definition rofi-types.h:249
@ WL_CENTER
Definition rofi-types.h:235
@ WL_NORTH_WEST
Definition rofi-types.h:245
@ WL_SOUTH
Definition rofi-types.h:241
@ WL_NORTH_EAST
Definition rofi-types.h:247
@ WL_WEST
Definition rofi-types.h:243
@ WL_NORTH
Definition rofi-types.h:237
@ WL_EAST
Definition rofi-types.h:239
@ WL_SOUTH_WEST
Definition rofi-types.h:251
char * rofi_force_utf8(const gchar *data, ssize_t length)
Definition helper.c:862
#define color_reset
Definition rofi.h:123
#define color_bold
Definition rofi.h:125
int textbox_get_cursor_x_pos(const textbox *tb)
Definition textbox.c:1160
textbox * rofi_view_get_active_text(void)
Definition view.c:323
RofiViewState * rofi_view_get_active(void)
Definition view.c:321
void rofi_view_handle_text(RofiViewState *state, const char *text)
Definition view.c:1463
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
Definition view.c:1500
unsigned int rofi_view_get_element_pitch(const RofiViewState *state, RofiOrientation orientation)
Definition view.c:418
void rofi_view_frame_callback(void)
Definition view.c:2191
void rofi_view_maybe_update(RofiViewState *state)
Definition view.c:1560
void rofi_view_set_size(RofiViewState *state, gint width, gint height)
Definition view.c:2233
void rofi_view_get_menu_rect(int *x, int *y, int *w, int *h)
Definition view.c:2245
void rofi_view_cancel(RofiViewState *state)
Definition view.c:331
void rofi_view_pool_refresh(void)
Definition view.c:2243
int widget_get_height(widget *wid)
Definition widget.c:437
struct _widget widget
Definition widget.h:49
#define WIDGET(a)
Definition widget.h:117
#define BTN_LEFT
Definition input-codes.h:33
#define BTN_MIDDLE
Definition input-codes.h:41
#define BTN_RIGHT
Definition input-codes.h:37
RofiOrientation
Definition rofi-types.h:139
@ ROFI_ORIENTATION_HORIZONTAL
Definition rofi-types.h:141
@ ROFI_ORIENTATION_VERTICAL
Definition rofi-types.h:140
RofiCursorType
Definition rofi-types.h:147
@ ROFI_CURSOR_POINTER
Definition rofi-types.h:149
@ ROFI_CURSOR_TEXT
Definition rofi-types.h:150
@ ROFI_CURSOR_DEFAULT
Definition rofi-types.h:148
NkBindings * bindings
Definition rofi.c:140
GMainLoop * main_loop
Definition rofi.c:146
Settings config
wayland_buffer * buffers
Definition display.c:114
wayland_stuff * context
Definition display.c:108
wayland_stuff * context
widget_motion_event motion
struct zwp_primary_selection_device_v1 * primary_selection_device
struct wl_data_device * data_device
uint32_t pointer_serial
enum wl_pointer_axis_source axis_source
xkb_keycode_t key
struct wl_pointer * pointer
struct _wayland_seat::@235041143265153055355113143117106150223001225232 wheel
wayland_touch_axis touch_axis
struct wl_keyboard * keyboard
struct zwp_text_input_v3 * text_input
struct _wayland_seat::@344154052066311033002267333364206171130317032013 wheel_continuous
struct _wayland_seat::@310131065064312041011230142331335370005076357136 repeat
widget_button_event button
struct wl_seat * seat
struct wl_touch * touch
struct _widget * parent
ClipboardCb callback
Definition display.c:1169
wayland_buffer_pool * pool
Definition display.c:101
gboolean released
Definition display.c:104
uint8_t * data
Definition display.c:103
struct wl_buffer * buffer
Definition display.c:102
struct wayland_output::@350210014256060275243057267211304066170232245054 current
wayland_stuff * context
Definition display.c:84
int32_t width
Definition display.c:91
int32_t x
Definition display.c:89
int32_t physical_width
Definition display.c:93
gchar * name
Definition display.c:87
int32_t height
Definition display.c:92
int32_t scale
Definition display.c:95
uint32_t global_name
Definition display.c:85
int32_t physical_height
Definition display.c:94
struct wayland_output::@350210014256060275243057267211304066170232245054 pending
struct wl_output * output
Definition display.c:86
int32_t y
Definition display.c:90
int32_t transform
Definition display.c:96
#define WL_LAYER_SHELL_INTERFACE_VERSION
struct _wayland_seat wayland_seat
#define WL_KEYBOARD_SHORTCUTS_INHIBITOR_INTERFACE_VERSION
#define WL_SHM_INTERFACE_VERSION
#define WL_SEAT_INTERFACE_MAX_VERSION
wayland_global_name
@ WAYLAND_GLOBAL_CURSOR_SHAPE
@ WAYLAND_GLOBAL_LAYER_SHELL
@ WAYLAND_GLOBAL_KEYBOARD_SHORTCUTS_INHIBITOR
@ WAYLAND_GLOBAL_COMPOSITOR
@ WAYLAND_GLOBAL_SHM
@ _WAYLAND_GLOBAL_SIZE
#define WL_SEAT_INTERFACE_MIN_VERSION
#define WL_OUTPUT_INTERFACE_MIN_VERSION
@ WAYLAND_TOUCH_AXIS_VERTICAL
@ WAYLAND_TOUCH_AXIS_NONE
@ WAYLAND_TOUCH_AXIS_UNDECIDED
@ WAYLAND_TOUCH_AXIS_HORIZONTAL
#define WL_OUTPUT_INTERFACE_MAX_VERSION
#define WL_COMPOSITOR_INTERFACE_VERSION
static void data_offer_handle_action(void *data, struct wl_data_offer *wl_data_offer, uint32_t dnd_action)
Definition display.c:1261
static void wayland_registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
Definition display.c:1736
static gboolean wayland_key_repeat_delay(void *data)
Definition display.c:457
static void wayland_pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis, wl_fixed_t value)
Definition display.c:904
static void clipboard_handle_selection(enum clipboard_type cb_type, void *offer)
Definition display.c:1294
static void wayland_layer_shell_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface)
Definition display.c:1843
static void wayland_touch_frame(void *data, struct wl_touch *touch)
Definition display.c:1109
static gint wayland_touch_scroll_step(RofiOrientation orientation)
Definition display.c:999
static void wayland_display_dump_monitor_layout(void)
Definition display.c:2122
static const struct wl_buffer_listener wayland_buffer_listener
Definition display.c:191
#define WHEEL_DETENT
Definition display.c:80
static void wayland_touch_shape(void *data, struct wl_touch *touch, int32_t id, wl_fixed_t major, wl_fixed_t minor)
Definition display.c:1126
static void wayland_display_set_input_focus(guint w)
Definition display.c:2167
static void text_input_done(void *data, struct zwp_text_input_v3 *text_input, uint32_t serial)
Definition display.c:1506
static void data_offer_handle_source_actions(void *data, struct wl_data_offer *wl_data_offer, uint32_t source_actions)
Definition display.c:1258
static const struct zwlr_layer_surface_v1_listener wayland_layer_shell_surface_listener
Definition display.c:1865
static void wayland_seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
Definition display.c:1392
static void wayland_display_revert_input_focus(void)
Definition display.c:2169
static const struct wl_registry_listener wayland_registry_listener
Definition display.c:1818
static void wayland_seat_name(void *data, struct wl_seat *seat, const char *name)
Definition display.c:1443
static void wayland_buffer_release(void *data, struct wl_buffer *buffer)
Definition display.c:178
static const struct wl_data_device_listener data_device_listener
Definition display.c:1314
static void wayland_pointer_send_events(wayland_seat *self)
Definition display.c:615
static void wayland_get_clipboard_data(int cb_type, ClipboardCb callback, void *user_data)
Definition display.c:2177
static const struct wl_keyboard_listener wayland_keyboard_listener
Definition display.c:565
static void wayland_surface_destroy(void)
Definition display.c:1831
static void wayland_pointer_axis_stop(void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis)
Definition display.c:932
#define TOUCH_TAP_SLOP
Definition display.c:995
static void wayland_output_scale(void *data, struct wl_output *output, int32_t scale)
Definition display.c:1616
double wayland_get_dpi_estimation(void)
Definition display.c:1556
static void wayland_output_done(void *data, struct wl_output *output)
Definition display.c:1578
void display_surface_commit(cairo_surface_t *surface)
Definition display.c:343
static void wayland_touch_motion(void *data, struct wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
Definition display.c:1057
wayland_stuff * wayland
Definition display.c:120
static void wayland_display_early_cleanup(void)
Definition display.c:2099
static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_device)
Definition display.c:1291
#define CLIPBOARD_READ_INCREMENT
Definition display.c:1163
static const struct zwp_text_input_v3_listener text_input_listener
Definition display.c:123
static void wayland_touch_orientation(void *data, struct wl_touch *touch, int32_t id, wl_fixed_t orientation)
Definition display.c:1129
static const struct wl_callback_listener wayland_frame_wl_callback_listener
Definition display.c:315
static gboolean clipboard_read_data(int fd, ClipboardCb callback, void *user_data)
Definition display.c:1225
static wayland_stuff wayland_
Definition display.c:119
static void wayland_pointer_axis_discrete(void *data, struct wl_pointer *pointer, enum wl_pointer_axis axis, int32_t discrete)
Definition display.c:936
static void wayland_keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, enum wl_keyboard_key_state kstate)
Definition display.c:489
static wayland_output * wayland_output_by_name(const char *name)
Definition display.c:1538
static void wayland_keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
Definition display.c:534
static void wayland_display_startup_notification(RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data)
Definition display.c:2158
cairo_surface_t * display_buffer_pool_get_next_buffer(wayland_buffer_pool *pool)
Definition display.c:320
static void primary_selection_device_handle_selection(void *data, struct zwp_primary_selection_device_v1 *data_device, struct zwp_primary_selection_offer_v1 *offer)
Definition display.c:1340
static void data_device_handle_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
Definition display.c:1308
static const struct wl_data_offer_listener data_offer_listener
Definition display.c:1265
gboolean display_get_surface_dimensions(int *width, int *height)
Definition display.c:2020
static void wayland_pointer_axis_source(void *data, struct wl_pointer *pointer, enum wl_pointer_axis_source axis_source)
Definition display.c:925
static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
Definition display.c:1283
#define TOUCH_SCROLL_STEP
Definition display.c:997
void wayland_display_set_cursor_type(RofiCursorType type)
Definition display.c:835
static gboolean wayland_key_repeat(void *data)
Definition display.c:431
static guint wayland_display_scale(void)
Definition display.c:2175
static gboolean wayland_display_late_setup(void)
Definition display.c:1960
static void wayland_layer_shell_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height)
Definition display.c:1823
static gboolean wayland_cursor_reload_theme(guint scale)
Definition display.c:1875
#define TOUCH_AXIS_LOCK
Definition display.c:996
static void wayland_output_release(wayland_output *self)
Definition display.c:1523
static void data_device_handle_motion(void *data, struct wl_data_device *wl_data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y)
Definition display.c:1286
static void wayland_seat_release(wayland_seat *self)
Definition display.c:1380
static void wayland_buffer_cleanup(wayland_buffer_pool *self)
Definition display.c:153
static void wayland_keyboard_keymap(void *data, struct wl_keyboard *keyboard, enum wl_keyboard_keymap_format format, int32_t fd, uint32_t size)
Definition display.c:377
static void wayland_surface_protocol_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
Definition display.c:272
static const cairo_user_data_key_t wayland_cairo_surface_user_data
Definition display.c:121
static void data_device_handle_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
Definition display.c:1271
static void wayland_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
Definition display.c:1651
static void wayland_pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, enum wl_pointer_button_state state)
Definition display.c:890
static void text_input_enter(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface)
Definition display.c:1459
static const struct wl_pointer_listener wayland_pointer_listener
Definition display.c:971
static display_proxy display_
Definition display.c:2213
static void wayland_cursor_set_image(int i)
Definition display.c:576
static void wayland_cursor_update_for_seat(wayland_seat *seat)
Definition display.c:784
static void wayland_output_geometry(void *data, struct wl_output *output, int32_t x, int32_t y, int32_t width, int32_t height, int32_t subpixel, const char *make, const char *model, int32_t transform)
Definition display.c:1592
static void wayland_touch_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, int32_t id)
Definition display.c:1031
static struct wl_cursor * rofi_cursor_type_to_wl_cursor(struct wl_cursor_theme *theme, RofiCursorType type)
Definition display.c:743
static void wayland_keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
Definition display.c:424
static void primary_selection_device_handle_data_offer(void *data, struct zwp_primary_selection_device_v1 *data_device, struct zwp_primary_selection_offer_v1 *offer)
Definition display.c:1333
static void text_input_commit_string(void *data, struct zwp_text_input_v3 *text_input, const char *text)
Definition display.c:1486
static void primary_selection_handle_offer(void *data, struct zwp_primary_selection_offer_v1 *offer, const char *mime_type)
Definition display.c:1324
static void update_cursor_rectangle(struct zwp_text_input_v3 *text_input)
Definition display.c:125
void display_buffer_pool_free(wayland_buffer_pool *self)
Definition display.c:264
static void wayland_display_cleanup(void)
Definition display.c:2108
static void wayland_pointer_release(wayland_seat *self)
Definition display.c:1352
#define wayland_output_get_dpi(output, scale, dimension)
Definition display.c:72
static gboolean wayland_display_setup(GMainLoop *main_loop, NkBindings *bindings)
Definition display.c:1912
static void wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
Definition display.c:363
static void data_device_handle_enter(void *data, struct wl_data_device *wl_data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id)
Definition display.c:1277
static void text_input_preedit_string(void *data, struct zwp_text_input_v3 *text_input, const char *text, int32_t cursor_begin, int32_t cursor_end)
Definition display.c:1474
static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener
Definition display.c:1347
static void text_input_leave(void *data, struct zwp_text_input_v3 *text_input, struct wl_surface *surface)
Definition display.c:1468
static void wayland_touch_down(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
Definition display.c:1008
static const struct wl_callback_listener wayland_cursor_frame_wl_callback_listener
Definition display.c:595
static void wayland_keyboard_release(wayland_seat *self)
Definition display.c:1142
static void wayland_set_fullscreen_mode(void)
Definition display.c:2201
struct _display_buffer_pool wayland_buffer_pool
Definition display.c:82
static const struct wl_touch_listener wayland_touch_listener
Definition display.c:1132
static void wayland_pointer_frame(void *data, struct wl_pointer *pointer)
Definition display.c:919
static const struct _view_proxy * wayland_display_view_proxy(void)
Definition display.c:2171
static void wayland_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
Definition display.c:552
static const struct wl_output_listener wayland_output_listener
Definition display.c:1638
static const struct wl_surface_listener wayland_surface_interface
Definition display.c:307
static gboolean wayland_error(gpointer user_data)
Definition display.c:1870
static const struct wl_seat_listener wayland_seat_listener
Definition display.c:1454
static void wayland_keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
Definition display.c:408
static void wayland_cursor_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
Definition display.c:599
static void wayland_pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
Definition display.c:869
static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener
Definition display.c:1329
static void wayland_output_mode(void *data, struct wl_output *output, enum wl_output_mode flags, int32_t width, int32_t height, int32_t refresh)
Definition display.c:1606
static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, const char *mime_type)
Definition display.c:1255
static void wayland_touch_release(wayland_seat *self)
Definition display.c:1369
void display_set_surface_dimensions(int width, int height, int x_margin, int y_margin, int loc)
Definition display.c:2038
static void wayland_touch_cancel(void *data, struct wl_touch *touch)
Definition display.c:1116
static gboolean clipboard_read_glib_callback(GIOChannel *channel, GIOCondition condition, gpointer opaque)
Definition display.c:1173
wayland_buffer_pool * display_buffer_pool_new(gint width, gint height)
Definition display.c:194
display_proxy *const wayland_proxy
Definition display.c:2230
static void text_input_delete_surrounding_text(void *data, struct zwp_text_input_v3 *text_input, uint32_t before_length, uint32_t after_length)
Definition display.c:1502
static void wayland_pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
Definition display.c:813
static void wayland_pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y)
Definition display.c:879
static int wayland_display_monitor_active(workarea *mon)
Definition display.c:2162
static void wayland_surface_protocol_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
Definition display.c:303
int menu_y
Definition view.c:93
const view_proxy * wayland_view_proxy
Definition view.c:584
int menu_x
Definition view.c:92
MenuFlags flags
Definition view.c:73
unsigned long long count
Definition view.c:77
GTimer * time
Definition view.c:159
workarea mon
Definition view.c:117