25#define G_LOG_DOMAIN "Wayland"
26#pragma GCC diagnostic ignored "-Wunused-variable"
27#pragma GCC diagnostic ignored "-Wunused-parameter"
41#include <glib/gstdio.h>
42#include <wayland-client.h>
43#include <wayland-cursor.h>
44#include <xkbcommon/xkbcommon-compose.h>
45#include <xkbcommon/xkbcommon.h>
47#include <libgwater-wayland.h>
49#include <nkutils-bindings.h>
63#ifdef HAVE_WAYLAND_CURSOR_SHAPE
64#include "cursor-shape-v1-protocol.h"
66#include "keyboard-shortcuts-inhibit-unstable-v1-protocol.h"
67#include "primary-selection-unstable-v1-protocol.h"
68#include "wlr-layer-shell-unstable-v1-protocol.h"
70#define wayland_output_get_dpi(output, scale, dimension) \
71 ((output)->current.physical_##dimension > 0 && (scale) > 0 \
72 ? round((double)(output)->current.dimension * 25.4 / (scale) / \
73 (output)->current.physical_##dimension) \
123 for (i = 0; i <
wayland->buffer_count; ++i) {
145 for (i = 0; i <
wayland->buffer_count; ++i) {
158 struct wl_shm_pool *wl_pool;
159 struct wl_buffer *buffer;
168 stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
170 g_warning(
"cairo stride width calculation failure");
173 size = (size_t)stride * height;
174 pool_size = size *
wayland->buffer_count;
176 gchar filename[PATH_MAX];
177 g_snprintf(filename, PATH_MAX,
"%s/rofi-wayland-surface",
178 g_get_user_runtime_dir());
179 fd = g_open(filename, O_CREAT | O_RDWR, 0);
182 g_warning(
"creating a buffer file for %zu B failed: %s", pool_size,
186 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
190 if (ftruncate(fd, pool_size) < 0) {
195 data = mmap(NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
196 if (data == MAP_FAILED) {
197 g_warning(
"mmap of size %zu failed: %s", pool_size, g_strerror(errno));
210 wl_pool = wl_shm_create_pool(
wayland->shm, fd, pool_size);
212 for (i = 0; i <
wayland->buffer_count; ++i) {
215 wl_pool, size * i, width, height, stride, WL_SHM_FORMAT_ARGB8888);
221 wl_shm_pool_destroy(wl_pool);
236 struct wl_surface *wl_surface,
237 struct wl_output *wl_output) {
240 output = g_hash_table_lookup(
wayland->outputs, wl_output);
241 if (output == NULL) {
248 g_debug(
"Auto-detected DPI: %d",
config.dpi);
251 wl_surface_set_buffer_scale(wl_surface, output->
current.
scale);
267 struct wl_surface *wl_surface,
268 struct wl_output *wl_output) {}
286 for (i = 0; (buffer == NULL) && (i <
wayland->buffer_count); ++i) {
292 if (buffer == NULL) {
296 cairo_surface_t *surface;
298 surface = cairo_image_surface_create_for_data(
300 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, pool->
width));
307 if (surface == NULL ||
wayland->surface == NULL) {
315 cairo_surface_destroy(surface);
323 wl_surface_commit(
wayland->surface);
327 uint32_t timestamp) {
328 if (
wayland->frame_cb != NULL) {
329 wl_callback_destroy(
wayland->frame_cb);
333 if (
wayland->surface != NULL) {
335 wl_callback_add_listener(
wayland->frame_cb,
341 enum wl_keyboard_keymap_format format,
342 int32_t fd, uint32_t size) {
343 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
348 char *str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
349 if (str == MAP_FAILED) {
354 struct xkb_keymap *keymap = xkb_keymap_new_from_string(
355 nk_bindings_seat_get_context(
wayland->bindings_seat), str,
356 XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
357 if (keymap == NULL) {
358 fprintf(stderr,
"Failed to get Keymap for current keyboard device.\n");
361 struct xkb_state *state = xkb_state_new(keymap);
364 "Failed to get state object for current keyboard device.\n");
368 nk_bindings_seat_update_keymap(
wayland->bindings_seat, keymap, state);
372 uint32_t serial,
struct wl_surface *surface,
373 struct wl_array *keys) {
379 uint32_t *key, *kend;
380 for (key = keys->data, kend = key + keys->size /
sizeof(*key); key < kend;
382 nk_bindings_seat_handle_key(
wayland->bindings_seat, NULL, *key + 8,
383 NK_BINDINGS_KEY_STATE_PRESSED);
389 struct wl_surface *surface) {
399 return G_SOURCE_REMOVE;
402 char *text = nk_bindings_seat_handle_key(
wayland->bindings_seat, NULL,
404 NK_BINDINGS_KEY_STATE_PRESS);
408 return G_SOURCE_REMOVE;
417 return G_SOURCE_CONTINUE;
427 char *text = nk_bindings_seat_handle_key(
wayland->bindings_seat, NULL,
429 NK_BINDINGS_KEY_STATE_PRESS);
433 return G_SOURCE_REMOVE;
440 guint repeat_wait_ms = 30;
445 self->
repeat.
source = g_main_context_find_source_by_id(NULL, source_id);
449 return G_SOURCE_REMOVE;
453 uint32_t serial, uint32_t
time, uint32_t key,
454 enum wl_keyboard_key_state kstate) {
461 xkb_keycode_t keycode = key + 8;
462 if (kstate == WL_KEYBOARD_KEY_STATE_RELEASED) {
470 nk_bindings_seat_handle_key(
wayland->bindings_seat, NULL, keycode,
471 NK_BINDINGS_KEY_STATE_RELEASE);
472 }
else if (kstate == WL_KEYBOARD_KEY_STATE_PRESSED) {
473 gchar *text = nk_bindings_seat_handle_key(
474 wayland->bindings_seat, NULL, keycode, NK_BINDINGS_KEY_STATE_PRESS);
488 self->
repeat.
source = g_main_context_find_source_by_id(NULL, source_id);
498 uint32_t serial, uint32_t mods_depressed,
499 uint32_t mods_latched,
500 uint32_t mods_locked, uint32_t group) {
502 nk_bindings_seat_update_mask(
wayland->bindings_seat, NULL, mods_depressed,
503 mods_latched, mods_locked, 0, 0, group);
512 struct wl_keyboard *keyboard,
513 int32_t rate, int32_t delay) {
536 struct wl_buffer *buffer;
537 struct wl_cursor_image *image;
538 image =
wayland->cursor.cursor->images[i];
541 buffer = wl_cursor_image_get_buffer(
wayland->cursor.image);
542 wl_surface_set_buffer_scale(
wayland->cursor.surface,
wayland->scale);
543 wl_surface_attach(
wayland->cursor.surface, buffer, 0, 0);
544 wl_surface_damage(
wayland->cursor.surface, 0, 0,
wayland->cursor.image->width,
545 wayland->cursor.image->height);
546 wl_surface_commit(
wayland->cursor.surface);
550 struct wl_callback *callback,
553static const struct wl_callback_listener
559 struct wl_callback *callback,
563 if (
wayland->cursor.frame_cb != NULL) {
564 wl_callback_destroy(
wayland->cursor.frame_cb);
566 wayland->cursor.frame_cb = wl_surface_frame(
wayland->cursor.surface);
567 wl_callback_add_listener(
wayland->cursor.frame_cb,
588 NkBindingsMouseButton button = -1;
591 button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
594 button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
597 button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
605 nk_bindings_seat_handle_button(
wayland->bindings_seat, NULL, button,
606 NK_BINDINGS_BUTTON_STATE_PRESS,
609 nk_bindings_seat_handle_button(
wayland->bindings_seat, NULL, button,
610 NK_BINDINGS_BUTTON_STATE_RELEASE,
616 if (self->
axis_source == WL_POINTER_AXIS_SOURCE_FINGER ||
617 self->
axis_source == WL_POINTER_AXIS_SOURCE_CONTINUOUS) {
624 nk_bindings_seat_handle_scroll(
wayland->bindings_seat, NULL,
625 NK_BINDINGS_SCROLL_AXIS_VERTICAL,
636 nk_bindings_seat_handle_scroll(
wayland->bindings_seat, NULL,
637 NK_BINDINGS_SCROLL_AXIS_HORIZONTAL,
653static struct wl_cursor *
656 static const char *
const default_names[] = {
657 "default",
"left_ptr",
"top_left_arrow",
"left-arrow", NULL};
658 static const char *
const pointer_names[] = {
"pointer",
"hand1", NULL};
659 static const char *
const text_names[] = {
"text",
"xterm", NULL};
661 const char *
const *name;
662 struct wl_cursor *cursor = NULL;
666 name = pointer_names;
672 name = default_names;
675 for (; cursor == NULL && *name != NULL; ++name) {
676 cursor = wl_cursor_theme_get_cursor(theme, *name);
681#ifdef HAVE_WAYLAND_CURSOR_SHAPE
682static enum wp_cursor_shape_device_v1_shape
686 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER;
688 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;
690 return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
696#ifdef HAVE_WAYLAND_CURSOR_SHAPE
697 if (seat->cursor_shape_device != NULL) {
698 wp_cursor_shape_device_v1_set_shape(
700 rofi_cursor_type_to_wp_cursor_shape(
wayland->cursor.type));
702 }
else if (
wayland->cursor.theme == NULL) {
708 if (
wayland->cursor.surface == NULL) {
709 wayland->cursor.surface = wl_compositor_create_surface(
wayland->compositor);
712 if (
wayland->cursor.cursor->image_count < 2) {
718 wl_pointer_set_cursor(
725 uint32_t serial,
struct wl_surface *surface,
726 wl_fixed_t x, wl_fixed_t y) {
731#ifdef HAVE_WAYLAND_CURSOR_SHAPE
732 if (
wayland->cursor_shape_manager != NULL) {
733 if (self->cursor_shape_device == NULL) {
734 self->cursor_shape_device = wp_cursor_shape_manager_v1_get_pointer(
735 wayland->cursor_shape_manager, pointer);
749 struct wl_cursor *cursor;
751 if (
wayland->cursor.type == type) {
756#ifdef HAVE_WAYLAND_CURSOR_SHAPE
757 if (
wayland->cursor_shape_manager == NULL)
760 if (
wayland->cursor.theme == NULL) {
765 if (cursor == NULL) {
766 g_info(
"Failed to load cursor type %d", type);
769 wayland->cursor.cursor = cursor;
772 g_hash_table_iter_init(&iter,
wayland->seats);
773 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
781 uint32_t serial,
struct wl_surface *surface) {
784 if (
wayland->cursor.frame_cb != NULL) {
785 wl_callback_destroy(
wayland->cursor.frame_cb);
786 wayland->cursor.frame_cb = NULL;
791 uint32_t
time, wl_fixed_t x, wl_fixed_t y) {
794 self->
button.
x = wl_fixed_to_int(x);
795 self->
button.
y = wl_fixed_to_int(y);
796 self->
motion.
x = wl_fixed_to_int(x);
797 self->
motion.
y = wl_fixed_to_int(y);
802 uint32_t serial, uint32_t
time,
804 enum wl_pointer_button_state state) {
811 self->
button.
pressed = (state == WL_POINTER_BUTTON_STATE_PRESSED);
816 uint32_t
time,
enum wl_pointer_axis axis,
821 case WL_POINTER_AXIS_VERTICAL_SCROLL:
824 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
837 enum wl_pointer_axis_source axis_source) {
845 enum wl_pointer_axis axis) {}
848 struct wl_pointer *pointer,
849 enum wl_pointer_axis axis,
856 case WL_POINTER_AXIS_VERTICAL_SCROLL:
859 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
865#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
866static void wayland_pointer_axis120(
void *data,
struct wl_pointer *wl_pointer,
867 enum wl_pointer_axis axis,
872 case WL_POINTER_AXIS_VERTICAL_SCROLL:
875 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
891#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
892 .axis_value120 = wayland_pointer_axis120,
902 wl_keyboard_release(self->
keyboard);
913#define CLIPBOARD_READ_INCREMENT 1024
924 GIOCondition condition,
930 g_io_channel_read_chars(channel, info->
buffer + info->
size,
933 case G_IO_STATUS_AGAIN:
936 case G_IO_STATUS_NORMAL: {
941 g_io_channel_shutdown(channel, FALSE, NULL);
942 g_io_channel_unref(channel);
952 if (status == G_IO_STATUS_EOF) {
955 g_warning(
"Could not read data from clipboard");
958 g_io_channel_shutdown(channel, FALSE, NULL);
959 g_io_channel_unref(channel);
968 GIOChannel *channel = g_io_channel_unix_new(
fd);
972 g_io_channel_unref(channel);
983 if (info->
buffer == NULL) {
984 g_io_channel_unref(channel);
990 g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR,
997 const char *mime_type) {}
1000 void *data,
struct wl_data_offer *wl_data_offer, uint32_t source_actions) {}
1003 struct wl_data_offer *wl_data_offer,
1004 uint32_t dnd_action) {}
1013 struct wl_data_device *data_device,
1014 struct wl_data_offer *offer) {
1019 struct wl_data_device *wl_data_device,
1021 struct wl_surface *surface, wl_fixed_t x,
1022 wl_fixed_t y,
struct wl_data_offer *
id) {}
1025 struct wl_data_device *wl_data_device) {}
1028 struct wl_data_device *wl_data_device,
1029 uint32_t
time, wl_fixed_t x,
1033 struct wl_data_device *wl_data_device) {}
1039 if (clipboard->
offer != NULL) {
1041 wl_data_offer_destroy(clipboard->
offer);
1043 zwp_primary_selection_offer_v1_destroy(clipboard->
offer);
1046 clipboard->
offer = offer;
1050 struct wl_data_device *data_device,
1051 struct wl_data_offer *offer) {
1066 struct zwp_primary_selection_offer_v1 *offer,
1067 const char *mime_type) {}
1069static const struct zwp_primary_selection_offer_v1_listener
1075 void *data,
struct zwp_primary_selection_device_v1 *data_device,
1076 struct zwp_primary_selection_offer_v1 *offer) {
1077 zwp_primary_selection_offer_v1_add_listener(
1082 void *data,
struct zwp_primary_selection_device_v1 *data_device,
1083 struct zwp_primary_selection_offer_v1 *offer) {
1087static const struct zwp_primary_selection_device_v1_listener
1098#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1099 if (self->cursor_shape_device != NULL) {
1100 wp_cursor_shape_device_v1_destroy(self->cursor_shape_device);
1101 self->cursor_shape_device = NULL;
1105 wl_pointer_release(self->
pointer);
1114 wl_seat_release(self->
seat);
1122 uint32_t capabilities) {
1125 if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) &&
1129 }
else if ((!(capabilities & WL_SEAT_CAPABILITY_POINTER)) &&
1134 if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && (self->
pointer == NULL)) {
1137 }
else if ((!(capabilities & WL_SEAT_CAPABILITY_POINTER)) &&
1142 if (
wayland->data_device_manager != NULL) {
1143 self->
data_device = wl_data_device_manager_get_data_device(
1144 wayland->data_device_manager, seat);
1148 if (
wayland->primary_selection_device_manager != NULL) {
1150 zwp_primary_selection_device_manager_v1_get_device(
1151 wayland->primary_selection_device_manager, seat);
1152 zwp_primary_selection_device_v1_add_listener(
1162 if (self->
name != NULL) {
1163 g_hash_table_remove(
wayland->seats_by_name, self->
name);
1165 self->
name = g_strdup(name);
1166 g_hash_table_insert(
wayland->seats_by_name, self->
name, self);
1175 g_debug(
"Output release: %s", self->
name);
1177 if (wl_output_get_version(self->
output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) {
1178 wl_output_release(self->
output);
1180 wl_output_destroy(self->
output);
1190#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1191 GHashTableIter iter;
1194 g_debug(
"Monitor lookup by name : %s", name);
1196 g_hash_table_iter_init(&iter,
wayland->outputs);
1197 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1198 if (g_strcmp0(output->
name, name) == 0) {
1203 g_debug(
"Monitor lookup by name failed: %s", name);
1212 gsize noutputs = g_hash_table_size(
wayland->outputs);
1213 if ( noutputs == 1) {
1214 GHashTableIter iter;
1216 g_hash_table_iter_init(&iter,
wayland->outputs);
1217 if (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1220 }
else if (noutputs > 1 &&
config.monitor != NULL ) {
1222 if (output != NULL) {
1234 g_debug(
"Output %s: %" PRIi32
"x%" PRIi32
" (%" PRIi32
"x%" PRIi32
"mm)"
1235 " position %" PRIi32
"x%" PRIi32
" scale %" PRIi32
1236 " transform %" PRIi32,
1244 int32_t x, int32_t y, int32_t width,
1245 int32_t height, int32_t subpixel,
1246 const char *make,
const char *model,
1247 int32_t transform) {
1258 enum wl_output_mode
flags, int32_t width,
1259 int32_t height, int32_t refresh) {
1260 if (
flags & WL_OUTPUT_MODE_CURRENT) {
1274#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1275static void wayland_output_name(
void *data,
struct wl_output *output,
1280 self->
name = g_strdup(name);
1284#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
1285static void wayland_output_description(
void *data,
struct wl_output *output,
1286 const char *name) {}
1294#ifdef WL_OUTPUT_NAME_SINCE_VERSION
1295 .name = wayland_output_name,
1297#ifdef WL_OUTPUT_DESCRIPTION_SINCE_VERSION
1298 .description = wayland_output_description,
1303 struct wl_registry *registry,
1304 uint32_t name,
const char *interface,
1306 g_debug(
"wayland registry: interface %s", interface);
1308 if (g_strcmp0(interface, wl_compositor_interface.name) == 0) {
1311 wl_registry_bind(registry, name, &wl_compositor_interface,
1313 }
else if (g_strcmp0(interface, zwlr_layer_shell_v1_interface.name) == 0) {
1316 wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface,
1318 }
else if (g_strcmp0(
1320 zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) ==
1323 wayland->kb_shortcuts_inhibit_manager = wl_registry_bind(
1324 registry, name, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface,
1326 }
else if (g_strcmp0(interface, wl_shm_interface.name) == 0) {
1328 wayland->shm = wl_registry_bind(registry, name, &wl_shm_interface,
1330 }
else if (g_strcmp0(interface, wl_seat_interface.name) == 0) {
1332 g_error(
"Minimum version of wayland seat interface is %u, got %u",
1341 seat->
seat = wl_registry_bind(registry, name, &wl_seat_interface, version);
1342 g_hash_table_insert(
wayland->seats, seat->
seat, seat);
1345 }
else if (g_strcmp0(interface, wl_output_interface.name) == 0) {
1347 g_error(
"Minimum version of wayland output interface is %u, got %u",
1357 wl_registry_bind(registry, name, &wl_output_interface, version);
1361 g_hash_table_insert(
wayland->outputs, output->
output, output);
1364 }
else if (strcmp(interface, wl_data_device_manager_interface.name) == 0) {
1365 wayland->data_device_manager =
1366 wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3);
1367 }
else if (strcmp(interface,
1368 zwp_primary_selection_device_manager_v1_interface.name) ==
1370 wayland->primary_selection_device_manager = wl_registry_bind(
1371 registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
1373#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1374 else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
1376 wayland->cursor_shape_manager = wl_registry_bind(
1377 registry, name, &wp_cursor_shape_manager_v1_interface, 1);
1383 struct wl_registry *registry,
1387 if (
wayland->global_names[i] != name) {
1394 wl_compositor_destroy(
wayland->compositor);
1398#ifdef HAVE_WAYLAND_CURSOR_SHAPE
1399 wp_cursor_shape_manager_v1_destroy(
wayland->cursor_shape_manager);
1400 wayland->cursor_shape_manager = NULL;
1404 zwlr_layer_shell_v1_destroy(
wayland->layer_shell);
1408 zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(
1409 wayland->kb_shortcuts_inhibit_manager);
1410 wayland->kb_shortcuts_inhibit_manager = NULL;
1417 g_assert_not_reached();
1421 if ((
wayland->cursor.theme != NULL) &&
1423 if (
wayland->cursor.frame_cb != NULL) {
1424 wl_callback_destroy(
wayland->cursor.frame_cb);
1425 wayland->cursor.frame_cb = NULL;
1428 wl_surface_destroy(
wayland->cursor.surface);
1429 wl_cursor_theme_destroy(
wayland->cursor.theme);
1430 wayland->cursor.surface = NULL;
1432 wayland->cursor.cursor = NULL;
1437 GHashTableIter iter;
1440 g_hash_table_iter_init(&iter,
wayland->seats);
1441 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
1446 g_hash_table_iter_remove(&iter);
1452 g_hash_table_iter_init(&iter,
wayland->outputs);
1453 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1458 g_hash_table_iter_remove(&iter);
1470 void *data,
struct zwlr_layer_surface_v1 *surface, uint32_t serial,
1471 uint32_t width, uint32_t height) {
1473 wayland->layer_height = height;
1474 zwlr_layer_surface_v1_ack_configure(surface, serial);
1478 if (
wayland->wlr_surface != NULL) {
1479 zwlr_layer_surface_v1_destroy(
wayland->wlr_surface);
1482 if (
wayland->surface != NULL) {
1483 wl_surface_destroy(
wayland->surface);
1490 struct zwlr_layer_surface_v1 *surface) {
1491 g_debug(
"Layer shell surface closed");
1505 if (state != NULL) {
1510static const struct zwlr_layer_surface_v1_listener
1517 g_main_loop_quit(
wayland->main_loop);
1518 return G_SOURCE_REMOVE;
1522 if (
wayland->cursor.theme != NULL) {
1523 if (
wayland->cursor.scale == scale)
1526 wl_cursor_theme_destroy(
wayland->cursor.theme);
1528 wayland->cursor.cursor = NULL;
1531 guint64 cursor_size = 24;
1532 char *env_cursor_size = (
char *)g_getenv(
"XCURSOR_SIZE");
1533 if (env_cursor_size && strlen(env_cursor_size) > 0) {
1534 guint64 size = g_ascii_strtoull(env_cursor_size, NULL, 10);
1535 if (0 < size && size < G_MAXUINT64) {
1539 cursor_size *= scale;
1541 wayland->cursor.theme = wl_cursor_theme_load(
wayland->cursor.theme_name,
1543 if (
wayland->cursor.theme != NULL) {
1546 if (
wayland->cursor.cursor == NULL) {
1547 wl_cursor_theme_destroy(
wayland->cursor.theme);
1551 wayland->cursor.scale = scale;
1562 char *display = (
char *)g_getenv(
"WAYLAND_DISPLAY");
1563 wayland->main_loop_source = g_water_wayland_source_new(NULL, display);
1564 if (
wayland->main_loop_source == NULL) {
1565 g_warning(
"Could not connect to the Wayland compositor");
1569 g_water_wayland_source_set_error_callback(
wayland->main_loop_source,
1576 wayland->outputs = g_hash_table_new(g_direct_hash, g_direct_equal);
1577 wayland->seats = g_hash_table_new(g_direct_hash, g_direct_equal);
1579 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1582 g_water_wayland_source_get_display(
wayland->main_loop_source);
1585 wl_display_roundtrip(
wayland->display);
1588 g_hash_table_size(
wayland->outputs) == 0 ||
1589 g_hash_table_size(
wayland->seats) == 0) {
1590 g_error(
"Could not connect to wayland compositor");
1593 if (
wayland->layer_shell == NULL) {
1594 g_error(
"Rofi on wayland requires support for the layer shell protocol");
1598 wayland->bindings_seat = nk_bindings_seat_new(
bindings, XKB_CONTEXT_NO_FLAGS);
1601 wl_display_roundtrip(
wayland->display);
1609 struct wl_output *wlo = NULL;
1610 if (output != NULL) {
1613 wayland->surface = wl_compositor_create_surface(
wayland->compositor);
1614 wayland->wlr_surface = zwlr_layer_shell_v1_get_layer_surface(
1616 ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
"rofi");
1620 zwlr_layer_surface_v1_set_anchor(
wayland->wlr_surface,
1621 ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
1622 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
1623 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
1624 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
1625 zwlr_layer_surface_v1_set_size(
wayland->wlr_surface, 0, 0);
1626 zwlr_layer_surface_v1_set_keyboard_interactivity(
wayland->wlr_surface, 1);
1627 zwlr_layer_surface_v1_add_listener(
1630 if (
config.global_kb &&
wayland->kb_shortcuts_inhibit_manager) {
1631 g_debug(
"inhibit shortcuts from compositor");
1632 GHashTableIter iter;
1634 g_hash_table_iter_init(&iter,
wayland->seats);
1635 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&seat)) {
1638 zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts(
1645 wl_surface_commit(
wayland->surface);
1646 wl_display_roundtrip(
wayland->display);
1653 if (
wayland->layer_width != 0) {
1654 if (width != NULL) {
1655 *width =
wayland->layer_width;
1657 if (height != NULL) {
1658 *height =
wayland->layer_height;
1666 int y_margin,
int loc) {
1669 wayland->layer_height = height;
1670 zwlr_layer_surface_v1_set_size(
wayland->wlr_surface, width, height);
1672 uint32_t wlr_anchor = 0;
1676 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1679 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1683 ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1686 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
1689 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
1690 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1693 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1697 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
1700 wlr_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
1709 ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
1713 ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
1716 zwlr_layer_surface_v1_set_anchor(
wayland->wlr_surface, wlr_anchor);
1722 zwlr_layer_surface_v1_set_margin(
wayland->wlr_surface, y_margin, -x_margin,
1723 -y_margin, x_margin);
1727 if (
wayland->main_loop_source == NULL) {
1732 wl_display_flush(
wayland->display);
1736 if (
wayland->main_loop_source == NULL) {
1740 nk_bindings_seat_free(
wayland->bindings_seat);
1741 g_hash_table_unref(
wayland->seats_by_name);
1742 g_hash_table_unref(
wayland->seats);
1743 g_hash_table_unref(
wayland->outputs);
1744 wl_registry_destroy(
wayland->registry);
1745 wl_display_flush(
wayland->display);
1746 g_water_wayland_source_free(
wayland->main_loop_source);
1750 int is_term = isatty(fileno(stdout));
1751 GHashTableIter iter;
1754 g_hash_table_iter_init(&iter,
wayland->outputs);
1755 printf(
"Monitor layout:\n");
1756 while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&output)) {
1757 printf(
"%s ID%s: %" PRIu32, is_term ?
color_bold :
"",
1760 printf(
"%s name%s: %s\n", is_term ?
color_bold :
"",
1762 printf(
"%s scale%s: %" PRIi32
"\n", is_term ?
color_bold :
"",
1764 printf(
"%s position%s: %" PRIi32
",%" PRIi32
"\n",
1767 printf(
"%s size%s: %" PRIi32
",%" PRIi32
"\n",
1773 printf(
"%s size%s: %" PRIi32
"mm,%" PRIi32
1774 "mm dpi: %.0f,%.0f\n",
1786 GSpawnChildSetupFunc *child_setup,
1787 gpointer *user_data) {}
1808 if (clipboard->
offer == NULL) {
1813 if (pipe(fds) < 0) {
1818 wl_data_offer_receive(clipboard->
offer,
"text/plain", fds[1]);
1820 zwp_primary_selection_offer_v1_receive(clipboard->
offer,
"text/plain",
1832 zwlr_layer_surface_v1_set_exclusive_zone(
wayland->wlr_surface, -1);
1833 zwlr_layer_surface_v1_set_size(
wayland->wlr_surface, 0, 0);
1834 wl_surface_commit(
wayland->surface);
1835 wl_display_roundtrip(
wayland->display);
struct _display_proxy display_proxy
struct _workarea workarea
void(* ClipboardCb)(char *clipboard_data, void *user_data)
RofiViewState * rofi_view_get_active(void)
void rofi_view_handle_text(RofiViewState *state, char *text)
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
void rofi_view_frame_callback(void)
void rofi_view_maybe_update(RofiViewState *state)
void rofi_view_set_size(RofiViewState *state, gint width, gint height)
void rofi_view_pool_refresh(void)
widget_motion_event motion
struct zwp_primary_selection_device_v1 * primary_selection_device
struct wl_data_device * data_device
enum wl_pointer_axis_source axis_source
struct _wayland_seat::@343227211112372105005173305133123375230264171047 repeat
struct _wayland_seat::@313335272333100233226263113233303355264201246036 wheel_continuous
struct wl_pointer * pointer
struct wl_keyboard * keyboard
struct _wayland_seat::@304276237306320361362211175300054320337005042177 wheel
widget_button_event button
wayland_buffer_pool * pool
struct wl_buffer * buffer
struct wayland_output::@126201033072136362231003373230312354065355150332 pending
struct wayland_output::@126201033072136362231003373230312354065355150332 current
struct wl_output * output
#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_CURSOR_SHAPE
@ WAYLAND_GLOBAL_LAYER_SHELL
@ WAYLAND_GLOBAL_KEYBOARD_SHORTCUTS_INHIBITOR
@ WAYLAND_GLOBAL_COMPOSITOR
#define WL_SEAT_INTERFACE_MIN_VERSION
#define WL_OUTPUT_INTERFACE_MIN_VERSION
#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)
static void wayland_registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
static gboolean wayland_key_repeat_delay(void *data)
static void wayland_pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis, wl_fixed_t value)
static void clipboard_handle_selection(enum clipboard_type cb_type, void *offer)
static void wayland_layer_shell_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface)
static void wayland_display_dump_monitor_layout(void)
static const struct wl_buffer_listener wayland_buffer_listener
static void wayland_display_set_input_focus(guint w)
static void data_offer_handle_source_actions(void *data, struct wl_data_offer *wl_data_offer, uint32_t source_actions)
static const struct zwlr_layer_surface_v1_listener wayland_layer_shell_surface_listener
static void wayland_seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
static void wayland_display_revert_input_focus(void)
static const struct wl_registry_listener wayland_registry_listener
static void wayland_seat_name(void *data, struct wl_seat *seat, const char *name)
static void wayland_buffer_release(void *data, struct wl_buffer *buffer)
static const struct wl_data_device_listener data_device_listener
static void wayland_pointer_send_events(wayland_seat *self)
static void wayland_get_clipboard_data(int cb_type, ClipboardCb callback, void *user_data)
static const struct wl_keyboard_listener wayland_keyboard_listener
static void wayland_surface_destroy(void)
static void wayland_pointer_axis_stop(void *data, struct wl_pointer *pointer, uint32_t time, enum wl_pointer_axis axis)
static void wayland_output_scale(void *data, struct wl_output *output, int32_t scale)
double wayland_get_dpi_estimation(void)
static void wayland_output_done(void *data, struct wl_output *output)
void display_surface_commit(cairo_surface_t *surface)
static void wayland_display_early_cleanup(void)
static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_device)
#define CLIPBOARD_READ_INCREMENT
static const struct wl_callback_listener wayland_frame_wl_callback_listener
static gboolean clipboard_read_data(int fd, ClipboardCb callback, void *user_data)
static wayland_stuff wayland_
static void wayland_pointer_axis_discrete(void *data, struct wl_pointer *pointer, enum wl_pointer_axis axis, int32_t discrete)
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)
static wayland_output * wayland_output_by_name(const char *name)
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)
static void wayland_display_startup_notification(RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data)
cairo_surface_t * display_buffer_pool_get_next_buffer(wayland_buffer_pool *pool)
static void primary_selection_device_handle_selection(void *data, struct zwp_primary_selection_device_v1 *data_device, struct zwp_primary_selection_offer_v1 *offer)
static void data_device_handle_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
static const struct wl_data_offer_listener data_offer_listener
gboolean display_get_surface_dimensions(int *width, int *height)
static void wayland_pointer_axis_source(void *data, struct wl_pointer *pointer, enum wl_pointer_axis_source axis_source)
static void data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
void wayland_display_set_cursor_type(RofiCursorType type)
static gboolean wayland_key_repeat(void *data)
static guint wayland_display_scale(void)
static gboolean wayland_display_late_setup(void)
static void wayland_layer_shell_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t width, uint32_t height)
static gboolean wayland_cursor_reload_theme(guint scale)
static void wayland_output_release(wayland_output *self)
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)
static void wayland_seat_release(wayland_seat *self)
static void wayland_buffer_cleanup(wayland_buffer_pool *self)
static void wayland_keyboard_keymap(void *data, struct wl_keyboard *keyboard, enum wl_keyboard_keymap_format format, int32_t fd, uint32_t size)
static void wayland_surface_protocol_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
static const cairo_user_data_key_t wayland_cairo_surface_user_data
static void data_device_handle_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer)
static void wayland_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
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)
static const struct wl_pointer_listener wayland_pointer_listener
static display_proxy display_
static void wayland_cursor_set_image(int i)
static void wayland_cursor_update_for_seat(wayland_seat *seat)
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)
static struct wl_cursor * rofi_cursor_type_to_wl_cursor(struct wl_cursor_theme *theme, RofiCursorType type)
static void wayland_keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
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)
static void primary_selection_handle_offer(void *data, struct zwp_primary_selection_offer_v1 *offer, const char *mime_type)
void display_buffer_pool_free(wayland_buffer_pool *self)
static void wayland_display_cleanup(void)
static void wayland_pointer_release(wayland_seat *self)
#define wayland_output_get_dpi(output, scale, dimension)
static gboolean wayland_display_setup(GMainLoop *main_loop, NkBindings *bindings)
static void wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
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)
static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener
static const struct wl_callback_listener wayland_cursor_frame_wl_callback_listener
static void wayland_keyboard_release(wayland_seat *self)
static void wayland_set_fullscreen_mode(void)
struct _display_buffer_pool wayland_buffer_pool
static void wayland_pointer_frame(void *data, struct wl_pointer *pointer)
static const struct _view_proxy * wayland_display_view_proxy(void)
static void wayland_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
static const struct wl_output_listener wayland_output_listener
static const struct wl_surface_listener wayland_surface_interface
static gboolean wayland_error(gpointer user_data)
static const struct wl_seat_listener wayland_seat_listener
static void wayland_keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
static void wayland_cursor_frame_callback(void *data, struct wl_callback *callback, uint32_t time)
static void wayland_pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener
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)
static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, const char *mime_type)
void display_set_surface_dimensions(int width, int height, int x_margin, int y_margin, int loc)
static gboolean clipboard_read_glib_callback(GIOChannel *channel, GIOCondition condition, gpointer opaque)
wayland_buffer_pool * display_buffer_pool_new(gint width, gint height)
display_proxy *const wayland_proxy
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)
static void wayland_pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y)
static int wayland_display_monitor_active(workarea *mon)
static void wayland_surface_protocol_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
const view_proxy * wayland_view_proxy