From 17a289e36e920ebf18af6e9215388ee6c20029c7 Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Sun, 27 Feb 2022 22:44:36 +0100 Subject: [PATCH 001/298] render: allow texture creation while rendering This removes an artificial limitation in form of an assert that disallowed the creation of textures while the renderer is rendering. A consumer might run its own rendering pipeline and after start of the renderer still want to create textures for internal usage. --- include/wlr/render/wlr_texture.h | 12 ------------ render/wlr_texture.c | 1 - 2 files changed, 13 deletions(-) diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 1dbcba1de..90bb5de56 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -25,9 +25,6 @@ struct wlr_texture { /** * Create a new texture from raw pixel data. `stride` is in bytes. The returned * texture is mutable. - * - * Should not be called in a rendering block like renderer_begin()/end() or - * between attaching a renderer to an output and committing it. */ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height, @@ -35,9 +32,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, /** * Create a new texture from a DMA-BUF. The returned texture is immutable. - * - * Should not be called in a rendering block like renderer_begin()/end() or - * between attaching a renderer to an output and committing it. */ struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_attributes *attribs); @@ -50,9 +44,6 @@ bool wlr_texture_is_opaque(struct wlr_texture *texture); /** * Update a texture with raw pixels. The texture must be mutable, and the input * data must have the same pixel format that the texture was created with. - * - * Should not be called in a rendering block like renderer_begin()/end() or - * between attaching a renderer to an output and committing it. */ bool wlr_texture_write_pixels(struct wlr_texture *texture, uint32_t stride, uint32_t width, uint32_t height, @@ -66,9 +57,6 @@ void wlr_texture_destroy(struct wlr_texture *texture); /** * Create a new texture from a buffer. - * - * Should not be called in a rendering block like renderer_begin()/end() or - * between attaching a renderer to an output and committing it. */ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, struct wlr_buffer *buffer); diff --git a/render/wlr_texture.c b/render/wlr_texture.c index c4563dd67..2cdf08c59 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -63,7 +63,6 @@ struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, struct wlr_buffer *buffer) { - assert(!renderer->rendering); if (!renderer->impl->texture_from_buffer) { return NULL; } From cdb3e80b3934d740d4702a062bc5e10a67d21f57 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 28 Feb 2022 15:11:31 -0500 Subject: [PATCH 002/298] types/wlr_virtual_keyboard_v1: fix wlr_keyboard destroy sequence --- types/wlr_virtual_keyboard_v1.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 07eeb3678..e40a97e82 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -34,14 +34,7 @@ static void keyboard_release_pressed_keys(struct wlr_keyboard *keyboard) { } static void keyboard_destroy(struct wlr_keyboard *wlr_kb) { - struct wlr_virtual_keyboard_v1 *keyboard = - (struct wlr_virtual_keyboard_v1 *)wlr_kb; - - keyboard_release_pressed_keys(&keyboard->keyboard); - wl_resource_set_user_data(keyboard->resource, NULL); - wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); - wl_list_remove(&keyboard->link); - free(keyboard); + /* no-op, keyboard belongs to the wlr_virtual_keyboard_v1 */ } static const struct wlr_keyboard_impl keyboard_impl = { @@ -138,9 +131,17 @@ static void virtual_keyboard_modifiers(struct wl_client *client, static void virtual_keyboard_destroy_resource(struct wl_resource *resource) { struct wlr_virtual_keyboard_v1 *keyboard = virtual_keyboard_from_resource(resource); - if (keyboard != NULL) { - wlr_keyboard_destroy(&keyboard->keyboard); + if (keyboard == NULL) { + return; } + + /* TODO: rework wlr_keyboard device destruction */ + keyboard_release_pressed_keys(&keyboard->keyboard); + wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); + wlr_keyboard_destroy(&keyboard->keyboard); + wl_resource_set_user_data(keyboard->resource, NULL); + wl_list_remove(&keyboard->link); + free(keyboard); } static void virtual_keyboard_destroy(struct wl_client *client, From c84744321edf3e5f083feb01addd82eae0969e31 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 28 Feb 2022 15:23:56 -0500 Subject: [PATCH 003/298] types/wlr_virtual_pointer_v1: fix wlr_pointer destroy sequence --- types/wlr_virtual_pointer_v1.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index 6215bbfff..8c232c818 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -9,13 +9,7 @@ #include "wlr-virtual-pointer-unstable-v1-protocol.h" static void pointer_destroy(struct wlr_pointer *pointer) { - struct wlr_virtual_pointer_v1 *virtual_pointer = - (struct wlr_virtual_pointer_v1 *)pointer; - - wl_resource_set_user_data(virtual_pointer->resource, NULL); - wlr_signal_emit_safe(&virtual_pointer->events.destroy, virtual_pointer); - wl_list_remove(&virtual_pointer->link); - free(virtual_pointer); + /* no-op, pointer belongs to the wlr_virtual_pointer_v1 */ } static const struct wlr_pointer_impl pointer_impl = { @@ -205,9 +199,16 @@ static void virtual_pointer_axis_discrete(struct wl_client *client, static void virtual_pointer_destroy_resource(struct wl_resource *resource) { struct wlr_virtual_pointer_v1 *pointer = virtual_pointer_from_resource(resource); - if (pointer != NULL) { - wlr_pointer_destroy(&pointer->pointer); + if (pointer == NULL) { + return; } + + /* TODO: rework wlr_pointer device destruction */ + wlr_signal_emit_safe(&pointer->events.destroy, pointer); + wlr_pointer_destroy(&pointer->pointer); + wl_resource_set_user_data(pointer->resource, NULL); + wl_list_remove(&pointer->link); + free(pointer); } static void virtual_pointer_destroy(struct wl_client *client, From 1666e377e280cda1b5783f589566add0f9e36f7d Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 15 Feb 2022 19:33:41 +0900 Subject: [PATCH 004/298] Xwayland: rename notify pipe 'p' to notify_fd --- xwayland/server.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/xwayland/server.c b/xwayland/server.c index d8006c44d..1f8f9feba 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -323,33 +323,33 @@ static bool server_start(struct wlr_xwayland_server *server) { server->client_destroy.notify = handle_client_destroy; wl_client_add_destroy_listener(server->client, &server->client_destroy); - int p[2]; - if (pipe(p) == -1) { + int notify_fd[2]; + if (pipe(notify_fd) == -1) { wlr_log_errno(WLR_ERROR, "pipe failed"); server_finish_process(server); return false; } - if (!set_cloexec(p[1], true) || !set_cloexec(p[0], true)) { + if (!set_cloexec(notify_fd[1], true) || !set_cloexec(notify_fd[0], true)) { wlr_log(WLR_ERROR, "Failed to set CLOEXEC on FD"); server_finish_process(server); return false; } struct wl_event_loop *loop = wl_display_get_event_loop(server->wl_display); - server->pipe_source = wl_event_loop_add_fd(loop, p[0], + server->pipe_source = wl_event_loop_add_fd(loop, notify_fd[0], WL_EVENT_READABLE, xserver_handle_ready, server); server->pid = fork(); if (server->pid < 0) { wlr_log_errno(WLR_ERROR, "fork failed"); - close(p[0]); - close(p[1]); + close(notify_fd[0]); + close(notify_fd[1]); server_finish_process(server); return false; } else if (server->pid == 0) { /* Double-fork, but we need to forward SIGUSR1 once Xserver(1) * is ready, or error if there was one. */ - close(p[0]); + close(notify_fd[0]); sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGUSR1); @@ -359,7 +359,7 @@ static bool server_start(struct wlr_xwayland_server *server) { pid_t pid = fork(); if (pid < 0) { wlr_log_errno(WLR_ERROR, "second fork failed"); - (void)!write(p[1], "\n", 1); + (void)!write(notify_fd[1], "\n", 1); _exit(EXIT_FAILURE); } else if (pid == 0) { exec_xwayland(server); @@ -367,7 +367,7 @@ static bool server_start(struct wlr_xwayland_server *server) { int sig; sigwait(&sigset, &sig); - if (write(p[1], "\n", 1) < 1) { + if (write(notify_fd[1], "\n", 1) < 1) { // Note: if this write failed and we've leaked the write // end of the pipe (due to a race between another thread // exec'ing and our call to fcntl), then our handler will @@ -387,7 +387,7 @@ static bool server_start(struct wlr_xwayland_server *server) { /* close child fds */ /* remain managing x sockets for lazy start */ - close(p[1]); + close(notify_fd[1]); close(server->wl_fd[1]); safe_close(server->wm_fd[1]); server->wl_fd[1] = server->wm_fd[1] = -1; From 4741e9d8410fd66445b45500cb3589f52c5de36b Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 16 Feb 2022 18:44:12 +0900 Subject: [PATCH 005/298] Xwayland: use -displayfd instead of USR1 Using Xwayland -displayfd means we don't need to worry about handling SIGUSR1 to second guess when Xwayland is ready and write to the pipe: just let it do that write when it would be sending SIGUSR1 otherwise. Closes: #3356 --- xwayland/server.c | 91 +++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/xwayland/server.c b/xwayland/server.c index 1f8f9feba..e0cf5aa5e 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -25,7 +25,8 @@ static void safe_close(int fd) { } } -noreturn static void exec_xwayland(struct wlr_xwayland_server *server) { +noreturn static void exec_xwayland(struct wlr_xwayland_server *server, + int notify_fd) { if (!set_cloexec(server->x_fd[0], false) || !set_cloexec(server->x_fd[1], false) || !set_cloexec(server->wl_fd[1], false)) { @@ -37,16 +38,13 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server) { _exit(EXIT_FAILURE); } - /* Make Xwayland signal us when it's ready */ - /* TODO: can we use -displayfd instead? */ - signal(SIGUSR1, SIG_IGN); - char *argv[64] = {0}; size_t i = 0; - char listenfd0[16], listenfd1[16]; + char listenfd0[16], listenfd1[16], displayfd[16]; snprintf(listenfd0, sizeof(listenfd0), "%d", server->x_fd[0]); snprintf(listenfd1, sizeof(listenfd1), "%d", server->x_fd[1]); + snprintf(displayfd, sizeof(displayfd), "%d", notify_fd); argv[i++] = "Xwayland"; argv[i++] = server->display_name; @@ -65,6 +63,8 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server) { argv[i++] = "-listen"; argv[i++] = listenfd1; #endif + argv[i++] = "-displayfd"; + argv[i++] = displayfd; char wmfd[16]; if (server->options.enable_wm) { @@ -219,36 +219,44 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { } static int xserver_handle_ready(int fd, uint32_t mask, void *data) { - // There are three ways in which we can end up here, from server_start: - // 1. the second fork failed - // 2. the exec failed - // 3. Xwayland sent a SIGUSR1 - // - // All three cases result in a write to the pipe, which triggers us. - // - // For the first two cases, the first fork will exit with - // EXIT_FAILURE, notifying us that startup failed. - // - // For the third case, the first fork will exit with EXIT_SUCCESS - // and we'll know that Xwayland started successfully. - - close(fd); struct wlr_xwayland_server *server = data; - int stat_val = -1; - while (waitpid(server->pid, &stat_val, 0) < 0) { + if (mask & WL_EVENT_READABLE) { + /* Xwayland writes to the pipe twice, so if we close it too early + * it's possible the second write will fail and Xwayland shuts down. + * Make sure we read until end of line marker to avoid this. + */ + char buf[64]; + ssize_t n = read(fd, buf, sizeof(buf)); + if (n < 0 && errno != EINTR) { + /* Clear mask to signal start failure after reaping child */ + wlr_log_errno(WLR_ERROR, "read from Xwayland display_fd failed"); + mask = 0; + } else if (n <= 0 || buf[n-1] != '\n') { + /* Returning 1 here means recheck and call us again if required. */ + return 1; + } + } + + while (waitpid(server->pid, NULL, 0) < 0) { if (errno == EINTR) { continue; } wlr_log_errno(WLR_ERROR, "waitpid for Xwayland fork failed"); goto error; } - if (stat_val) { + /* Xwayland will only write on the fd once it has finished its + * initial setup. Getting an event here without READABLE means + * the server end failed. + */ + if (!(mask & WL_EVENT_READABLE)) { + assert(mask & WL_EVENT_HANGUP); wlr_log(WLR_ERROR, "Xwayland startup failed, not setting up xwm"); goto error; } wlr_log(WLR_DEBUG, "Xserver is ready"); + close(fd); wl_event_source_remove(server->pipe_source); server->pipe_source = NULL; @@ -258,13 +266,15 @@ static int xserver_handle_ready(int fd, uint32_t mask, void *data) { }; wlr_signal_emit_safe(&server->events.ready, &event); - return 1; /* wayland event loop dispatcher's count */ + /* We removed the source, so don't need recheck */ + return 0; error: /* clean up */ + close(fd); server_finish_process(server); server_finish_display(server); - return 1; + return 0; } static bool server_start_display(struct wlr_xwayland_server *server, @@ -329,7 +339,7 @@ static bool server_start(struct wlr_xwayland_server *server) { server_finish_process(server); return false; } - if (!set_cloexec(notify_fd[1], true) || !set_cloexec(notify_fd[0], true)) { + if (!set_cloexec(notify_fd[0], true)) { wlr_log(WLR_ERROR, "Failed to set CLOEXEC on FD"); server_finish_process(server); return false; @@ -347,39 +357,12 @@ static bool server_start(struct wlr_xwayland_server *server) { server_finish_process(server); return false; } else if (server->pid == 0) { - /* Double-fork, but we need to forward SIGUSR1 once Xserver(1) - * is ready, or error if there was one. */ - close(notify_fd[0]); - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGUSR1); - sigaddset(&sigset, SIGCHLD); - sigprocmask(SIG_BLOCK, &sigset, NULL); - pid_t pid = fork(); if (pid < 0) { wlr_log_errno(WLR_ERROR, "second fork failed"); - (void)!write(notify_fd[1], "\n", 1); _exit(EXIT_FAILURE); } else if (pid == 0) { - exec_xwayland(server); - } - - int sig; - sigwait(&sigset, &sig); - if (write(notify_fd[1], "\n", 1) < 1) { - // Note: if this write failed and we've leaked the write - // end of the pipe (due to a race between another thread - // exec'ing and our call to fcntl), then our handler will - // never wake up and never notice this failure. Hopefully - // that combination of events is extremely unlikely. This - // applies to the other write, too. - wlr_log_errno(WLR_ERROR, "write to pipe failed"); - _exit(EXIT_FAILURE); - } - if (sig == SIGCHLD) { - waitpid(pid, NULL, 0); - _exit(EXIT_FAILURE); + exec_xwayland(server, notify_fd[1]); } _exit(EXIT_SUCCESS); From 0a5a65cf4819ebffb74c410735ba676b288bb82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 14 Feb 2022 15:27:34 +0100 Subject: [PATCH 006/298] examples/input-method: Don't crash on NULL surrounding text E.g. With e.g. gnome-terminal we never end up in handle_surrouding so it will be NULL. --- examples/input-method.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/input-method.c b/examples/input-method.c index 479c87613..849971b9b 100644 --- a/examples/input-method.c +++ b/examples/input-method.c @@ -194,7 +194,7 @@ static void do_updates(void) { update_stage++; break; case 2: - if (strcmp(current.surrounding.text, "_Commit_") != 0) { + if (current.surrounding.text && strcmp(current.surrounding.text, "_Commit_") != 0) { return; } zwp_input_method_v2_commit_string(input_method, "_CommitNoPreed_"); @@ -203,7 +203,7 @@ static void do_updates(void) { update_stage++; break; case 3: - if (strcmp(current.surrounding.text, "_Commit__CommitNoPreed_") != 0) { + if (current.surrounding.text && strcmp(current.surrounding.text, "_Commit__CommitNoPreed_") != 0) { return; } zwp_input_method_v2_commit_string(input_method, "_WaitNo_"); @@ -212,7 +212,7 @@ static void do_updates(void) { update_stage++; break; case 4: - if (strcmp(current.surrounding.text, "_Commit__WaitNo_") != 0) { + if (current.surrounding.text && strcmp(current.surrounding.text, "_Commit__WaitNo_") != 0) { return; } zwp_input_method_v2_set_preedit_string(input_method, "PreedWithDel", strlen("Preed"), strlen("Preed")); @@ -221,7 +221,7 @@ static void do_updates(void) { update_stage++; break; case 5: - if (strcmp(current.surrounding.text, "_Commit_") != 0) { + if (current.surrounding.text && strcmp(current.surrounding.text, "_Commit_") != 0) { return; } zwp_input_method_v2_delete_surrounding_text(input_method, strlen("mit_"), 0); @@ -229,7 +229,7 @@ static void do_updates(void) { update_stage++; break; case 6: - if (strcmp(current.surrounding.text, "_Com") != 0) { + if (current.surrounding.text && strcmp(current.surrounding.text, "_Com") != 0) { printf("Failed\n"); } update_stage++; From 9dd6e2b90521fd438c90837c646a1fb4092bfe1b Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 22 Feb 2022 16:17:48 -0500 Subject: [PATCH 007/298] backend/libinput: add devices wl_list This commit prepares the ground for a wlr_libinput_input_device refactoring. --- backend/libinput/backend.c | 12 ++++++++++-- backend/libinput/events.c | 10 ++++++++++ include/backend/libinput.h | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 8023807fd..50726ec5a 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -110,9 +110,11 @@ static bool backend_start(struct wlr_backend *wlr_backend) { no_devs = NULL; } } - if (!no_devs && backend->wlr_device_lists.size == 0) { + if (!no_devs && (backend->wlr_device_lists.size == 0 + || wl_list_empty(&backend->devices))) { handle_libinput_readable(libinput_fd, WL_EVENT_READABLE, backend); - if (backend->wlr_device_lists.size == 0) { + if (backend->wlr_device_lists.size == 0 + && wl_list_empty(&backend->devices)) { wlr_log(WLR_ERROR, "libinput initialization failed, no input devices"); wlr_log(WLR_ERROR, "Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check"); return false; @@ -150,6 +152,11 @@ static void backend_destroy(struct wlr_backend *wlr_backend) { free(*wlr_devices_ptr); } + struct wlr_libinput_input_device *dev, *tmp; + wl_list_for_each_safe(dev, tmp, &backend->devices, link) { + destroy_libinput_input_device(dev); + } + wlr_backend_finish(wlr_backend); wl_list_remove(&backend->display_destroy.link); @@ -212,6 +219,7 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, wlr_backend_init(&backend->backend, &backend_impl); wl_array_init(&backend->wlr_device_lists); + wl_list_init(&backend->devices); backend->session = session; backend->display = display; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index e8d99f251..39b3fc000 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -224,6 +224,16 @@ static void handle_device_removed(struct wlr_libinput_backend *backend, int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); wlr_log(WLR_DEBUG, "Removing %s [%d:%d]", name, vendor, product); + + if (!wl_list_empty(&backend->devices)) { + struct wlr_libinput_input_device *dev, *tmp_dev; + wl_list_for_each_safe(dev, tmp_dev, &backend->devices, link) { + if (dev->handle == libinput_dev) { + destroy_libinput_input_device(dev); + } + } + } + if (!wlr_devices) { return; } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 39e6dfe5a..e443c0ec1 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -27,6 +27,7 @@ struct wlr_libinput_backend { struct wl_listener session_signal; struct wl_array wlr_device_lists; // struct wl_list * + struct wl_list devices; // wlr_libinput_device::link }; struct wlr_libinput_input_device { From 5eefda1ffe16bdacd3445259937cfed119409e22 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 23 Feb 2022 10:42:20 -0500 Subject: [PATCH 008/298] backend/libinput: rework keyboard interface The wlr_libinput_input_device now owns its wlr_keyboard, instead of creating a new wlr_libinput_input_device for it. --- backend/libinput/backend.c | 12 +++++-- backend/libinput/events.c | 69 ++++++++++++++++++++++++++----------- backend/libinput/keyboard.c | 60 ++++++++++---------------------- include/backend/libinput.h | 12 ++++--- 4 files changed, 83 insertions(+), 70 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 50726ec5a..bdc365918 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -238,8 +238,16 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, struct libinput_device *wlr_libinput_get_device_handle( struct wlr_input_device *wlr_dev) { - struct wlr_libinput_input_device *dev = - (struct wlr_libinput_input_device *)wlr_dev; + struct wlr_libinput_input_device *dev = NULL; + switch (wlr_dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + dev = device_from_keyboard(wlr_dev->keyboard); + break; + default: + dev = (struct wlr_libinput_input_device *)wlr_dev; + break; + } + return dev->handle; } diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 39b3fc000..8916ef8b2 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -25,6 +25,7 @@ struct wlr_input_device *get_appropriate_device( return NULL; } + void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { /** @@ -34,8 +35,12 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) */ if (dev->wlr_input_device._device) { wlr_input_device_destroy(&dev->wlr_input_device); + wlr_input_device_finish(&dev->wlr_input_device); + } else { + if (dev->keyboard.impl) { + wlr_keyboard_destroy(&dev->keyboard); + } } - wlr_input_device_finish(&dev->wlr_input_device); libinput_device_unref(dev->handle); wl_list_remove(&dev->link); @@ -98,28 +103,46 @@ static void handle_device_added(struct wlr_libinput_backend *backend, int vendor = libinput_device_get_id_vendor(libinput_dev); int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); + wlr_log(WLR_DEBUG, "Added %s [%d:%d]", name, vendor, product); + + struct wlr_libinput_input_device *dev = + calloc(1, sizeof(struct wlr_libinput_input_device)); + if (dev == NULL) { + wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_input_device"); + return; + } + + dev->handle = libinput_dev; + libinput_device_ref(libinput_dev); + libinput_device_set_user_data(libinput_dev, dev); + + bool dev_used = false; + + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { + init_device_keyboard(dev); + + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->keyboard.base); + dev_used = true; + } + + + if (dev_used) { + wl_list_insert(&backend->devices, &dev->link); + return; + } else { + libinput_device_unref(libinput_dev); + free(dev); + } + struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list)); if (!wlr_devices) { wlr_log(WLR_ERROR, "Allocation failed"); return; } wl_list_init(wlr_devices); - wlr_log(WLR_DEBUG, "Added %s [%d:%d]", name, vendor, product); - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_KEYBOARD); - if (!wlr_dev) { - goto fail; - } - wlr_dev->keyboard = create_libinput_keyboard(libinput_dev); - if (!wlr_dev->keyboard) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) { struct wlr_input_device *wlr_dev = allocate_device(backend, @@ -210,30 +233,32 @@ static void handle_device_added(struct wlr_libinput_backend *backend, fail: wlr_log(WLR_ERROR, "Could not allocate new device"); - struct wlr_libinput_input_device *dev, *tmp_dev; - wl_list_for_each_safe(dev, tmp_dev, wlr_devices, link) { - free(dev); + struct wlr_libinput_input_device *device, *tmp; + wl_list_for_each_safe(device, tmp, wlr_devices, link) { + free(device); } free(wlr_devices); } static void handle_device_removed(struct wlr_libinput_backend *backend, struct libinput_device *libinput_dev) { - struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev); int vendor = libinput_device_get_id_vendor(libinput_dev); int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); wlr_log(WLR_DEBUG, "Removing %s [%d:%d]", name, vendor, product); + // TODO: use libinput_device_get_user_data(libinput_dev); if (!wl_list_empty(&backend->devices)) { struct wlr_libinput_input_device *dev, *tmp_dev; wl_list_for_each_safe(dev, tmp_dev, &backend->devices, link) { if (dev->handle == libinput_dev) { destroy_libinput_input_device(dev); + return; } } } + struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev); if (!wlr_devices) { return; } @@ -258,6 +283,8 @@ static void handle_device_removed(struct wlr_libinput_backend *backend, void handle_libinput_event(struct wlr_libinput_backend *backend, struct libinput_event *event) { struct libinput_device *libinput_dev = libinput_event_get_device(event); + struct wlr_libinput_input_device *dev = + libinput_device_get_user_data(libinput_dev); enum libinput_event_type event_type = libinput_event_get_type(event); switch (event_type) { case LIBINPUT_EVENT_DEVICE_ADDED: @@ -267,7 +294,7 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_device_removed(backend, libinput_dev); break; case LIBINPUT_EVENT_KEYBOARD_KEY: - handle_keyboard_key(event, libinput_dev); + handle_keyboard_key(event, &dev->keyboard); break; case LIBINPUT_EVENT_POINTER_MOTION: handle_pointer_motion(event, libinput_dev); diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index 9127217a8..cf6b9836e 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -1,33 +1,24 @@ #include #include #include -#include -#include -#include +#include #include "backend/libinput.h" -struct wlr_libinput_keyboard { - struct wlr_keyboard wlr_keyboard; - struct libinput_device *libinput_dev; -}; +struct wlr_libinput_input_device *device_from_keyboard( + struct wlr_keyboard *kb) { + assert(kb->impl == &libinput_keyboard_impl); -static struct wlr_libinput_keyboard *get_libinput_keyboard_from_keyboard( - struct wlr_keyboard *wlr_kb) { - assert(wlr_kb->impl == &libinput_keyboard_impl); - return (struct wlr_libinput_keyboard *)wlr_kb; + struct wlr_libinput_input_device *dev = wl_container_of(kb, dev, keyboard); + return dev; } static void keyboard_set_leds(struct wlr_keyboard *wlr_kb, uint32_t leds) { - struct wlr_libinput_keyboard *kb = - get_libinput_keyboard_from_keyboard(wlr_kb); - libinput_device_led_update(kb->libinput_dev, leds); + struct wlr_libinput_input_device *dev = device_from_keyboard(wlr_kb); + libinput_device_led_update(dev->handle, leds); } static void keyboard_destroy(struct wlr_keyboard *wlr_kb) { - struct wlr_libinput_keyboard *kb = - get_libinput_keyboard_from_keyboard(wlr_kb); - libinput_device_unref(kb->libinput_dev); - free(kb); + /* wlr_keyboard belongs to the wlr_libinput_input_device */ } const struct wlr_keyboard_impl libinput_keyboard_impl = { @@ -35,33 +26,18 @@ const struct wlr_keyboard_impl libinput_keyboard_impl = { .led_update = keyboard_set_leds }; -struct wlr_keyboard *create_libinput_keyboard( - struct libinput_device *libinput_dev) { - struct wlr_libinput_keyboard *kb = - calloc(1, sizeof(struct wlr_libinput_keyboard)); - if (kb == NULL) { - return NULL; - } - kb->libinput_dev = libinput_dev; - libinput_device_ref(libinput_dev); - libinput_device_led_update(libinput_dev, 0); - struct wlr_keyboard *wlr_kb = &kb->wlr_keyboard; - const char *name = libinput_device_get_name(libinput_dev); +void init_device_keyboard(struct wlr_libinput_input_device *dev) { + const char *name = libinput_device_get_name(dev->handle); + struct wlr_keyboard *wlr_kb = &dev->keyboard; wlr_keyboard_init(wlr_kb, &libinput_keyboard_impl, name); - wlr_kb->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_kb->base.product = libinput_device_get_id_product(libinput_dev); - return wlr_kb; + wlr_kb->base.vendor = libinput_device_get_id_vendor(dev->handle); + wlr_kb->base.product = libinput_device_get_id_product(dev->handle); + + libinput_device_led_update(dev->handle, 0); } void handle_keyboard_key(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_KEYBOARD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a keyboard event for a device with no keyboards?"); - return; - } + struct wlr_keyboard *kb) { struct libinput_event_keyboard *kbevent = libinput_event_get_keyboard_event(event); struct wlr_event_keyboard_key wlr_event = { 0 }; @@ -79,5 +55,5 @@ void handle_keyboard_key(struct libinput_event *event, break; } wlr_event.update_state = true; - wlr_keyboard_notify_key(wlr_dev->keyboard, &wlr_event); + wlr_keyboard_notify_key(kb, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index e443c0ec1..1e1ac8c50 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -32,8 +32,11 @@ struct wlr_libinput_backend { struct wlr_libinput_input_device { struct wlr_input_device wlr_input_device; - struct wl_list link; struct libinput_device *handle; + + struct wlr_keyboard keyboard; + + struct wl_list link; }; uint32_t usec_to_msec(uint64_t usec); @@ -54,10 +57,9 @@ extern const struct wlr_tablet_impl libinput_tablet_impl; extern const struct wlr_tablet_pad_impl libinput_tablet_pad_impl; extern const struct wlr_touch_impl libinput_touch_impl; -struct wlr_keyboard *create_libinput_keyboard( - struct libinput_device *device); -void handle_keyboard_key(struct libinput_event *event, - struct libinput_device *device); +void init_device_keyboard(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_keyboard(struct wlr_keyboard *kb); +void handle_keyboard_key(struct libinput_event *event, struct wlr_keyboard *kb); struct wlr_pointer *create_libinput_pointer( struct libinput_device *device); From d60cdad3ea1fed18bbda542b42d3fd7283c88909 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 28 Feb 2022 11:57:35 -0500 Subject: [PATCH 009/298] backend/libinput: rework pointer interface The wlr_libinput_input_device now owns its wlr_pointer, instead of creating a new wlr_libinput_input_device for it --- backend/libinput/backend.c | 3 + backend/libinput/events.c | 50 +++++----- backend/libinput/pointer.c | 191 ++++++++++++------------------------- include/backend/libinput.h | 29 +++--- 4 files changed, 104 insertions(+), 169 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index bdc365918..e22c4bfa8 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -243,6 +243,9 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_KEYBOARD: dev = device_from_keyboard(wlr_dev->keyboard); break; + case WLR_INPUT_DEVICE_POINTER: + dev = device_from_pointer(wlr_dev->pointer); + break; default: dev = (struct wlr_libinput_input_device *)wlr_dev; break; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 8916ef8b2..a0563ecde 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -40,6 +40,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->keyboard.impl) { wlr_keyboard_destroy(&dev->keyboard); } + if (dev->pointer.impl) { + wlr_pointer_destroy(&dev->pointer); + } } libinput_device_unref(dev->handle); @@ -127,6 +130,15 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) { + init_device_pointer(dev); + + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->pointer.base); + + dev_used = true; + } if (dev_used) { wl_list_insert(&backend->devices, &dev->link); @@ -143,20 +155,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, } wl_list_init(wlr_devices); - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_POINTER); - if (!wlr_dev) { - goto fail; - } - wlr_dev->pointer = create_libinput_pointer(libinput_dev); - if (!wlr_dev->pointer) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) { struct wlr_input_device *wlr_dev = allocate_device(backend, @@ -297,16 +295,16 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_keyboard_key(event, &dev->keyboard); break; case LIBINPUT_EVENT_POINTER_MOTION: - handle_pointer_motion(event, libinput_dev); + handle_pointer_motion(event, &dev->pointer); break; case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - handle_pointer_motion_abs(event, libinput_dev); + handle_pointer_motion_abs(event, &dev->pointer); break; case LIBINPUT_EVENT_POINTER_BUTTON: - handle_pointer_button(event, libinput_dev); + handle_pointer_button(event, &dev->pointer); break; case LIBINPUT_EVENT_POINTER_AXIS: - handle_pointer_axis(event, libinput_dev); + handle_pointer_axis(event, &dev->pointer); break; case LIBINPUT_EVENT_TOUCH_DOWN: handle_touch_down(event, libinput_dev); @@ -348,29 +346,29 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_switch_toggle(event, libinput_dev); break; case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: - handle_pointer_swipe_begin(event, libinput_dev); + handle_pointer_swipe_begin(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: - handle_pointer_swipe_update(event, libinput_dev); + handle_pointer_swipe_update(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_SWIPE_END: - handle_pointer_swipe_end(event, libinput_dev); + handle_pointer_swipe_end(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - handle_pointer_pinch_begin(event, libinput_dev); + handle_pointer_pinch_begin(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - handle_pointer_pinch_update(event, libinput_dev); + handle_pointer_pinch_update(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_PINCH_END: - handle_pointer_pinch_end(event, libinput_dev); + handle_pointer_pinch_end(event, &dev->pointer); break; #if LIBINPUT_HAS_HOLD_GESTURES case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: - handle_pointer_hold_begin(event, libinput_dev); + handle_pointer_hold_begin(event, &dev->pointer); break; case LIBINPUT_EVENT_GESTURE_HOLD_END: - handle_pointer_hold_end(event, libinput_dev); + handle_pointer_hold_end(event, &dev->pointer); break; #endif default: diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 706ace7b5..0ac781d70 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -1,83 +1,70 @@ #include #include -#include -#include -#include -#include +#include #include "backend/libinput.h" #include "util/signal.h" -const struct wlr_pointer_impl libinput_pointer_impl = {0}; +static void pointer_destroy(struct wlr_pointer *pointer) { + /* wlr_pointer belongs to the wlr_libinput_input_device */ +} -struct wlr_pointer *create_libinput_pointer( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_pointer *wlr_pointer = calloc(1, sizeof(struct wlr_pointer)); - if (!wlr_pointer) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_pointer"); - return NULL; - } - const char *name = libinput_device_get_name(libinput_dev); +const struct wlr_pointer_impl libinput_pointer_impl = { + .destroy = pointer_destroy, +}; + +void init_device_pointer(struct wlr_libinput_input_device *dev) { + const char *name = libinput_device_get_name(dev->handle); + struct wlr_pointer *wlr_pointer = &dev->pointer; wlr_pointer_init(wlr_pointer, &libinput_pointer_impl, name); - wlr_pointer->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_pointer->base.product = libinput_device_get_id_product(libinput_dev); - return wlr_pointer; + wlr_pointer->base.vendor = libinput_device_get_id_vendor(dev->handle); + wlr_pointer->base.product = libinput_device_get_id_product(dev->handle); +} + +struct wlr_libinput_input_device *device_from_pointer( + struct wlr_pointer *wlr_pointer) { + assert(wlr_pointer->impl == &libinput_pointer_impl); + + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_pointer, dev, pointer); + return dev; } void handle_pointer_motion(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_motion wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &pointer->base; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.delta_x = libinput_event_pointer_get_dx(pevent); wlr_event.delta_y = libinput_event_pointer_get_dy(pevent); wlr_event.unaccel_dx = libinput_event_pointer_get_dx_unaccelerated(pevent); wlr_event.unaccel_dy = libinput_event_pointer_get_dy_unaccelerated(pevent); - wlr_signal_emit_safe(&wlr_dev->pointer->events.motion, &wlr_event); - wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); + wlr_signal_emit_safe(&pointer->events.motion, &wlr_event); + wlr_signal_emit_safe(&pointer->events.frame, pointer); } void handle_pointer_motion_abs(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_motion_absolute wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &pointer->base; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1); wlr_event.y = libinput_event_pointer_get_absolute_y_transformed(pevent, 1); - wlr_signal_emit_safe(&wlr_dev->pointer->events.motion_absolute, &wlr_event); - wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); + wlr_signal_emit_safe(&pointer->events.motion_absolute, &wlr_event); + wlr_signal_emit_safe(&pointer->events.frame, pointer); } void handle_pointer_button(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_button wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &pointer->base; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.button = libinput_event_pointer_get_button(pevent); @@ -89,22 +76,16 @@ void handle_pointer_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_RELEASED; break; } - wlr_signal_emit_safe(&wlr_dev->pointer->events.button, &wlr_event); - wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); + wlr_signal_emit_safe(&pointer->events.button, &wlr_event); + wlr_signal_emit_safe(&pointer->events.frame, pointer); } void handle_pointer_axis(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); struct wlr_event_pointer_axis wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &pointer->base; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); switch (libinput_event_pointer_get_axis_source(pevent)) { @@ -139,102 +120,72 @@ void handle_pointer_axis(struct libinput_event *event, libinput_event_pointer_get_axis_value(pevent, axes[i]); wlr_event.delta_discrete = libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); - wlr_signal_emit_safe(&wlr_dev->pointer->events.axis, &wlr_event); + wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); } } - wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); + wlr_signal_emit_safe(&pointer->events.frame, pointer); } void handle_pointer_swipe_begin(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_swipe_begin wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_begin, &wlr_event); + wlr_signal_emit_safe(&pointer->events.swipe_begin, &wlr_event); } void handle_pointer_swipe_update(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_swipe_update wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), .dx = libinput_event_gesture_get_dx(gevent), .dy = libinput_event_gesture_get_dy(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_update, &wlr_event); + wlr_signal_emit_safe(&pointer->events.swipe_update, &wlr_event); } void handle_pointer_swipe_end(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_swipe_end wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_end, &wlr_event); + wlr_signal_emit_safe(&pointer->events.swipe_end, &wlr_event); } void handle_pointer_pinch_begin(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_pinch_begin wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_begin, &wlr_event); + wlr_signal_emit_safe(&pointer->events.pinch_begin, &wlr_event); } void handle_pointer_pinch_update(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_pinch_update wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -243,62 +194,44 @@ void handle_pointer_pinch_update(struct libinput_event *event, .scale = libinput_event_gesture_get_scale(gevent), .rotation = libinput_event_gesture_get_angle_delta(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_update, &wlr_event); + wlr_signal_emit_safe(&pointer->events.pinch_update, &wlr_event); } void handle_pointer_pinch_end(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_pinch_end wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_end, &wlr_event); + wlr_signal_emit_safe(&pointer->events.pinch_end, &wlr_event); } void handle_pointer_hold_begin(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_hold_begin wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_begin, &wlr_event); + wlr_signal_emit_safe(&pointer->events.hold_begin, &wlr_event); } void handle_pointer_hold_end(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?"); - return; - } + struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); struct wlr_event_pointer_hold_end wlr_event = { - .device = wlr_dev, + .device = &pointer->base, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_end, &wlr_event); + wlr_signal_emit_safe(&pointer->events.hold_end, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 1e1ac8c50..bcb36a717 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -35,6 +35,7 @@ struct wlr_libinput_input_device { struct libinput_device *handle; struct wlr_keyboard keyboard; + struct wlr_pointer pointer; struct wl_list link; }; @@ -61,32 +62,32 @@ void init_device_keyboard(struct wlr_libinput_input_device *dev); struct wlr_libinput_input_device *device_from_keyboard(struct wlr_keyboard *kb); void handle_keyboard_key(struct libinput_event *event, struct wlr_keyboard *kb); -struct wlr_pointer *create_libinput_pointer( - struct libinput_device *device); +void init_device_pointer(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_pointer(struct wlr_pointer *kb); void handle_pointer_motion(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_motion_abs(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_button(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_axis(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_swipe_begin(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_swipe_update(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_swipe_end(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_pinch_begin(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_pinch_update(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_pinch_end(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_hold_begin(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); void handle_pointer_hold_end(struct libinput_event *event, - struct libinput_device *device); + struct wlr_pointer *pointer); struct wlr_switch *create_libinput_switch( struct libinput_device *device); From d750c5ac676850d93ba7abf0a08476c4535ff1b6 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 23 Feb 2022 13:41:34 -0500 Subject: [PATCH 010/298] backend/libinput: rework switch interface The wlr_libinput_input_device now owns its wlr_switch, instead of creating a new wlr_libinput_input_device for it. --- backend/libinput/backend.c | 3 +++ backend/libinput/events.c | 27 +++++++++----------- backend/libinput/switch.c | 51 ++++++++++++++++++-------------------- include/backend/libinput.h | 8 +++--- 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index e22c4bfa8..92b5effaf 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -246,6 +246,9 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_POINTER: dev = device_from_pointer(wlr_dev->pointer); break; + case WLR_INPUT_DEVICE_SWITCH: + dev = device_from_switch(wlr_dev->switch_device); + break; default: dev = (struct wlr_libinput_input_device *)wlr_dev; break; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index a0563ecde..ad346c4f0 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -43,6 +43,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->pointer.impl) { wlr_pointer_destroy(&dev->pointer); } + if (dev->switch_device.impl) { + wlr_switch_destroy(&dev->switch_device); + } } libinput_device_unref(dev->handle); @@ -140,6 +143,14 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_SWITCH)) { + init_device_switch(dev); + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->switch_device.base); + dev_used = true; + } + if (dev_used) { wl_list_insert(&backend->devices, &dev->link); return; @@ -201,20 +212,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) { // TODO } - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_SWITCH)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_SWITCH); - if (!wlr_dev) { - goto fail; - } - wlr_dev->switch_device = create_libinput_switch(libinput_dev); - if (!wlr_dev->switch_device) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (!wl_list_empty(wlr_devices)) { struct wl_list **dst = wl_array_add(&backend->wlr_device_lists, sizeof(wlr_devices)); @@ -343,7 +340,7 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_tablet_pad_strip(event, libinput_dev); break; case LIBINPUT_EVENT_SWITCH_TOGGLE: - handle_switch_toggle(event, libinput_dev); + handle_switch_toggle(event, &dev->switch_device); break; case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: handle_pointer_swipe_begin(event, &dev->pointer); diff --git a/backend/libinput/switch.c b/backend/libinput/switch.c index 0e710f090..f2d5409b8 100644 --- a/backend/libinput/switch.c +++ b/backend/libinput/switch.c @@ -1,43 +1,40 @@ #include #include -#include -#include #include -#include -#include #include "backend/libinput.h" #include "util/signal.h" -const struct wlr_switch_impl libinput_switch_impl; +static void switch_destroy(struct wlr_switch *wlr_switch) { + /* wlr_switch belongs to the wlr_libinput_input_device */ +} -struct wlr_switch *create_libinput_switch( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_switch *wlr_switch = calloc(1, sizeof(struct wlr_switch)); - if (!wlr_switch) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_switch"); - return NULL; - } - const char *name = libinput_device_get_name(libinput_dev); +const struct wlr_switch_impl libinput_switch_impl = { + .destroy = switch_destroy, +}; + +void init_device_switch(struct wlr_libinput_input_device *dev) { + const char *name = libinput_device_get_name(dev->handle); + struct wlr_switch *wlr_switch = &dev->switch_device; wlr_switch_init(wlr_switch, &libinput_switch_impl, name); - wlr_log(WLR_DEBUG, "Created switch for device %s", name); - wlr_switch->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_switch->base.product = libinput_device_get_id_product(libinput_dev); - return wlr_switch; + wlr_switch->base.vendor = libinput_device_get_id_vendor(dev->handle); + wlr_switch->base.product = libinput_device_get_id_product(dev->handle); +} + +struct wlr_libinput_input_device *device_from_switch( + struct wlr_switch *wlr_switch) { + assert(wlr_switch->impl == &libinput_switch_impl); + + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_switch, dev, switch_device); + return dev; } void handle_switch_toggle(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_SWITCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a switch event for a device with no switch?"); - return; - } + struct wlr_switch *wlr_switch) { struct libinput_event_switch *sevent = libinput_event_get_switch_event (event); struct wlr_event_switch_toggle wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &wlr_switch->base; switch (libinput_event_switch_get_switch(sevent)) { case LIBINPUT_SWITCH_LID: wlr_event.switch_type = WLR_SWITCH_TYPE_LID; @@ -56,5 +53,5 @@ void handle_switch_toggle(struct libinput_event *event, } wlr_event.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)); - wlr_signal_emit_safe(&wlr_dev->switch_device->events.toggle, &wlr_event); + wlr_signal_emit_safe(&wlr_switch->events.toggle, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index bcb36a717..69b30f264 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -36,6 +36,7 @@ struct wlr_libinput_input_device { struct wlr_keyboard keyboard; struct wlr_pointer pointer; + struct wlr_switch switch_device; struct wl_list link; }; @@ -89,10 +90,11 @@ void handle_pointer_hold_begin(struct libinput_event *event, void handle_pointer_hold_end(struct libinput_event *event, struct wlr_pointer *pointer); -struct wlr_switch *create_libinput_switch( - struct libinput_device *device); +void init_device_switch(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_switch( + struct wlr_switch *switch_device); void handle_switch_toggle(struct libinput_event *event, - struct libinput_device *device); + struct wlr_switch *switch_device); struct wlr_touch *create_libinput_touch( struct libinput_device *device); From 4f4dd9522378f4d62a47ee9b1472378c9960b2f2 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 23 Feb 2022 14:06:02 -0500 Subject: [PATCH 011/298] backend/libinput: rework touch interface The wlr_libinput_input_device now owns its wlr_touch, instead of creating a new wlr_libinput_input_device for it. --- backend/libinput/backend.c | 3 ++ backend/libinput/events.c | 35 +++++++------- backend/libinput/touch.c | 96 ++++++++++++++------------------------ include/backend/libinput.h | 16 ++++--- 4 files changed, 63 insertions(+), 87 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 92b5effaf..2e26a269f 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -249,6 +249,9 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_SWITCH: dev = device_from_switch(wlr_dev->switch_device); break; + case WLR_INPUT_DEVICE_TOUCH: + dev = device_from_touch(wlr_dev->touch); + break; default: dev = (struct wlr_libinput_input_device *)wlr_dev; break; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index ad346c4f0..14678dbdf 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -46,6 +46,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->switch_device.impl) { wlr_switch_destroy(&dev->switch_device); } + if (dev->touch.impl) { + wlr_touch_destroy(&dev->touch); + } } libinput_device_unref(dev->handle); @@ -151,6 +154,14 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) { + init_device_touch(dev); + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->touch.base); + dev_used = true; + } + if (dev_used) { wl_list_insert(&backend->devices, &dev->link); return; @@ -166,20 +177,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, } wl_list_init(wlr_devices); - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TOUCH); - if (!wlr_dev) { - goto fail; - } - wlr_dev->touch = create_libinput_touch(libinput_dev); - if (!wlr_dev->touch) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { struct wlr_input_device *wlr_dev = allocate_device(backend, @@ -304,19 +301,19 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_pointer_axis(event, &dev->pointer); break; case LIBINPUT_EVENT_TOUCH_DOWN: - handle_touch_down(event, libinput_dev); + handle_touch_down(event, &dev->touch); break; case LIBINPUT_EVENT_TOUCH_UP: - handle_touch_up(event, libinput_dev); + handle_touch_up(event, &dev->touch); break; case LIBINPUT_EVENT_TOUCH_MOTION: - handle_touch_motion(event, libinput_dev); + handle_touch_motion(event, &dev->touch); break; case LIBINPUT_EVENT_TOUCH_CANCEL: - handle_touch_cancel(event, libinput_dev); + handle_touch_cancel(event, &dev->touch); break; case LIBINPUT_EVENT_TOUCH_FRAME: - handle_touch_frame(event, libinput_dev); + handle_touch_frame(event, &dev->touch); break; case LIBINPUT_EVENT_TABLET_TOOL_AXIS: handle_tablet_tool_axis(event, libinput_dev); diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 2e22a97a3..5b4dcbd6e 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -1,113 +1,87 @@ #include #include -#include -#include #include -#include -#include #include "backend/libinput.h" #include "util/signal.h" -const struct wlr_touch_impl libinput_touch_impl; +static void touch_destroy(struct wlr_touch *touch) { + /* wlr_touch belongs to the wlr_libinput_input_device */ +} -struct wlr_touch *create_libinput_touch( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_touch *wlr_touch = calloc(1, sizeof(struct wlr_touch)); - if (!wlr_touch) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_touch"); - return NULL; - } - const char *name = libinput_device_get_name(libinput_dev); +const struct wlr_touch_impl libinput_touch_impl = { + .destroy = touch_destroy, +}; + +void init_device_touch(struct wlr_libinput_input_device *dev) { + const char *name = libinput_device_get_name(dev->handle); + struct wlr_touch *wlr_touch = &dev->touch; wlr_touch_init(wlr_touch, &libinput_touch_impl, name); - wlr_touch->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_touch->base.product = libinput_device_get_id_product(libinput_dev); - return wlr_touch; + wlr_touch->base.vendor = libinput_device_get_id_vendor(dev->handle); + wlr_touch->base.product = libinput_device_get_id_product(dev->handle); +} + +struct wlr_libinput_input_device *device_from_touch( + struct wlr_touch *wlr_touch) { + assert(wlr_touch->impl == &libinput_touch_impl); + + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_touch, dev, touch); + return dev; } void handle_touch_down(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?"); - return; - } + struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_down wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &touch->base; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1); wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1); - wlr_signal_emit_safe(&wlr_dev->touch->events.down, &wlr_event); + wlr_signal_emit_safe(&touch->events.down, &wlr_event); } void handle_touch_up(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?"); - return; - } + struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_up wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &touch->base; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); - wlr_signal_emit_safe(&wlr_dev->touch->events.up, &wlr_event); + wlr_signal_emit_safe(&touch->events.up, &wlr_event); } void handle_touch_motion(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?"); - return; - } + struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_motion wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &touch->base; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1); wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1); - wlr_signal_emit_safe(&wlr_dev->touch->events.motion, &wlr_event); + wlr_signal_emit_safe(&touch->events.motion, &wlr_event); } void handle_touch_cancel(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?"); - return; - } + struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); struct wlr_event_touch_cancel wlr_event = { 0 }; - wlr_event.device = wlr_dev; + wlr_event.device = &touch->base; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); - wlr_signal_emit_safe(&wlr_dev->touch->events.cancel, &wlr_event); + wlr_signal_emit_safe(&touch->events.cancel, &wlr_event); } void handle_touch_frame(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?"); - return; - } - wlr_signal_emit_safe(&wlr_dev->touch->events.frame, NULL); + struct wlr_touch *touch) { + wlr_signal_emit_safe(&touch->events.frame, NULL); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 69b30f264..c8719af3d 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -37,6 +37,7 @@ struct wlr_libinput_input_device { struct wlr_keyboard keyboard; struct wlr_pointer pointer; struct wlr_switch switch_device; + struct wlr_touch touch; struct wl_list link; }; @@ -96,18 +97,19 @@ struct wlr_libinput_input_device *device_from_switch( void handle_switch_toggle(struct libinput_event *event, struct wlr_switch *switch_device); -struct wlr_touch *create_libinput_touch( - struct libinput_device *device); +void init_device_touch(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_touch( + struct wlr_touch *touch); void handle_touch_down(struct libinput_event *event, - struct libinput_device *device); + struct wlr_touch *touch); void handle_touch_up(struct libinput_event *event, - struct libinput_device *device); + struct wlr_touch *touch); void handle_touch_motion(struct libinput_event *event, - struct libinput_device *device); + struct wlr_touch *touch); void handle_touch_cancel(struct libinput_event *event, - struct libinput_device *device); + struct wlr_touch *touch); void handle_touch_frame(struct libinput_event *event, - struct libinput_device *device); + struct wlr_touch *touch); struct wlr_tablet *create_libinput_tablet( struct libinput_device *device); From c8456086a164fd62c26fe3f3ade5f1e59d25eda0 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 24 Feb 2022 11:00:11 -0500 Subject: [PATCH 012/298] backend/libinput: rework tablet interface The wlr_libinput_device owns its wlr_tablet and its associated wlr_tablet_tools --- backend/libinput/backend.c | 3 + backend/libinput/events.c | 33 ++-- backend/libinput/tablet_tool.c | 278 +++++++++++---------------------- include/backend/libinput.h | 15 +- 4 files changed, 116 insertions(+), 213 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 2e26a269f..111ebf3e6 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -252,6 +252,9 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_TOUCH: dev = device_from_touch(wlr_dev->touch); break; + case WLR_INPUT_DEVICE_TABLET_TOOL: + dev = device_from_tablet(wlr_dev->tablet); + break; default: dev = (struct wlr_libinput_input_device *)wlr_dev; break; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 14678dbdf..76e7709c2 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -49,6 +49,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->touch.impl) { wlr_touch_destroy(&dev->touch); } + if (dev->tablet.impl) { + wlr_tablet_destroy(&dev->tablet); + } } libinput_device_unref(dev->handle); @@ -162,6 +165,14 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability(libinput_dev, + LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { + init_device_tablet(dev); + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->tablet.base); + dev_used = true; + } + if (dev_used) { wl_list_insert(&backend->devices, &dev->link); return; @@ -177,20 +188,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, } wl_list_init(wlr_devices); - if (libinput_device_has_capability(libinput_dev, - LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_TOOL); - if (!wlr_dev) { - goto fail; - } - wlr_dev->tablet = create_libinput_tablet(libinput_dev); - if (!wlr_dev->tablet) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { struct wlr_input_device *wlr_dev = allocate_device(backend, @@ -316,16 +313,16 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_touch_frame(event, &dev->touch); break; case LIBINPUT_EVENT_TABLET_TOOL_AXIS: - handle_tablet_tool_axis(event, libinput_dev); + handle_tablet_tool_axis(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: - handle_tablet_tool_proximity(event, libinput_dev); + handle_tablet_tool_proximity(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_TOOL_TIP: - handle_tablet_tool_tip(event, libinput_dev); + handle_tablet_tool_tip(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: - handle_tablet_tool_button(event, libinput_dev); + handle_tablet_tool_button(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_PAD_BUTTON: handle_tablet_pad_button(event, libinput_dev); diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index 373f87d7b..af2122181 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -1,92 +1,60 @@ -#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif #include #include #include #include -#include -#include #include -#include #include #include "backend/libinput.h" -#include "util/array.h" #include "util/signal.h" -static bool tablet_is_libinput(struct wlr_tablet *tablet) { - return tablet->impl == &libinput_tablet_impl; -} - -struct wlr_libinput_tablet_tool { +struct tablet_tool { struct wlr_tablet_tool wlr_tool; - - struct libinput_tablet_tool *libinput_tool; - - bool unique; - // Refcount for destroy + release - size_t pad_refs; + struct libinput_tablet_tool *handle; + struct wl_list link; // wlr_libinput_input_device::tablet_tools }; -struct wlr_libinput_tablet { - struct wlr_tablet wlr_tablet; - struct wl_array tools; // struct wlr_libinput_tablet_tool * -}; - -static void destroy_tool(struct wlr_libinput_tablet_tool *tool) { +static void tool_destroy(struct tablet_tool *tool) { wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); - libinput_tablet_tool_ref(tool->libinput_tool); - libinput_tablet_tool_set_user_data(tool->libinput_tool, NULL); + libinput_tablet_tool_unref(tool->handle); + libinput_tablet_tool_set_user_data(tool->handle, NULL); + wl_list_remove(&tool->link); free(tool); } -static void destroy_tablet(struct wlr_tablet *wlr_tablet) { - assert(tablet_is_libinput(wlr_tablet)); - struct wlr_libinput_tablet *tablet = - wl_container_of(wlr_tablet, tablet, wlr_tablet); - - struct wlr_libinput_tablet_tool **tool_ptr; - wl_array_for_each(tool_ptr, &tablet->tools) { - struct wlr_libinput_tablet_tool *tool = *tool_ptr; - if (--tool->pad_refs == 0) { - destroy_tool(tool); - } +static void tablet_destroy(struct wlr_tablet *wlr_tablet) { + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool, *tmp; + wl_list_for_each_safe(tool, tmp, &dev->tablet_tools, link) { + tool_destroy(tool); } - wl_array_release(&tablet->tools); - - free(tablet); } const struct wlr_tablet_impl libinput_tablet_impl = { - .destroy = destroy_tablet, + .destroy = tablet_destroy, }; -struct wlr_tablet *create_libinput_tablet( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_libinput_tablet *libinput_tablet = - calloc(1, sizeof(struct wlr_libinput_tablet)); - if (!libinput_tablet) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_tablet_tool"); - return NULL; - } - - struct wlr_tablet *wlr_tablet = &libinput_tablet->wlr_tablet; - const char *name = libinput_device_get_name(libinput_dev); - +void init_device_tablet(struct wlr_libinput_input_device *dev) { + const char *name = libinput_device_get_name(dev->handle); + struct wlr_tablet *wlr_tablet = &dev->tablet; wlr_tablet_init(wlr_tablet, &libinput_tablet_impl, name); - wlr_tablet->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_tablet->base.product = libinput_device_get_id_product(libinput_dev); + wlr_tablet->base.vendor = libinput_device_get_id_vendor(dev->handle); + wlr_tablet->base.product = libinput_device_get_id_product(dev->handle); - struct udev_device *udev = libinput_device_get_udev_device(libinput_dev); + struct udev_device *udev = libinput_device_get_udev_device(dev->handle); char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); - wlr_tablet->name = strdup(libinput_device_get_name(libinput_dev)); + wl_list_init(&dev->tablet_tools); +} - wl_array_init(&libinput_tablet->tools); +struct wlr_libinput_input_device *device_from_tablet( + struct wlr_tablet *wlr_tablet) { + assert(wlr_tablet->impl == &libinput_tablet_impl); - return wlr_tablet; + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_tablet, dev, tablet); + return dev; } static enum wlr_tablet_tool_type wlr_type_from_libinput_type( @@ -112,87 +80,55 @@ static enum wlr_tablet_tool_type wlr_type_from_libinput_type( abort(); // unreachable } -static struct wlr_libinput_tablet_tool *get_wlr_tablet_tool( - struct libinput_tablet_tool *tool) { - struct wlr_libinput_tablet_tool *ret = - libinput_tablet_tool_get_user_data(tool); - - if (ret) { - return ret; +static struct tablet_tool *get_tablet_tool( + struct wlr_libinput_input_device *dev, + struct libinput_tablet_tool *libinput_tool) { + struct tablet_tool *tool = + libinput_tablet_tool_get_user_data(libinput_tool); + if (tool) { + return tool; } - ret = calloc(1, sizeof(struct wlr_libinput_tablet_tool)); - if (!ret) { + tool = calloc(1, sizeof(struct tablet_tool)); + if (tool == NULL) { + wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool"); return NULL; } - ret->libinput_tool = libinput_tablet_tool_ref(tool); - ret->wlr_tool.pressure = libinput_tablet_tool_has_pressure(tool); - ret->wlr_tool.distance = libinput_tablet_tool_has_distance(tool); - ret->wlr_tool.tilt = libinput_tablet_tool_has_tilt(tool); - ret->wlr_tool.rotation = libinput_tablet_tool_has_rotation(tool); - ret->wlr_tool.slider = libinput_tablet_tool_has_slider(tool); - ret->wlr_tool.wheel = libinput_tablet_tool_has_wheel(tool); + tool->wlr_tool.type = wlr_type_from_libinput_type( + libinput_tablet_tool_get_type(libinput_tool)); + tool->wlr_tool.hardware_serial = + libinput_tablet_tool_get_serial(libinput_tool); + tool->wlr_tool.hardware_wacom = + libinput_tablet_tool_get_tool_id(libinput_tool); - ret->wlr_tool.hardware_serial = libinput_tablet_tool_get_serial(tool); - ret->wlr_tool.hardware_wacom = libinput_tablet_tool_get_tool_id(tool); - ret->wlr_tool.type = wlr_type_from_libinput_type( - libinput_tablet_tool_get_type(tool)); + tool->wlr_tool.pressure = libinput_tablet_tool_has_pressure(libinput_tool); + tool->wlr_tool.distance = libinput_tablet_tool_has_distance(libinput_tool); + tool->wlr_tool.tilt = libinput_tablet_tool_has_tilt(libinput_tool); + tool->wlr_tool.rotation = libinput_tablet_tool_has_rotation(libinput_tool); + tool->wlr_tool.slider = libinput_tablet_tool_has_slider(libinput_tool); + tool->wlr_tool.wheel = libinput_tablet_tool_has_wheel(libinput_tool); - ret->unique = libinput_tablet_tool_is_unique(tool); + wl_signal_init(&tool->wlr_tool.events.destroy); - wl_signal_init(&ret->wlr_tool.events.destroy); + tool->handle = libinput_tablet_tool_ref(libinput_tool); + libinput_tablet_tool_set_user_data(libinput_tool, tool); - libinput_tablet_tool_set_user_data(tool, ret); - return ret; -} - -static void ensure_tool_reference(struct wlr_libinput_tablet_tool *tool, - struct wlr_tablet *wlr_dev) { - assert(tablet_is_libinput(wlr_dev)); - struct wlr_libinput_tablet *tablet = - wl_container_of(wlr_dev, tablet, wlr_tablet); - - struct wlr_libinput_tablet_tool **tool_ptr; - wl_array_for_each(tool_ptr, &tablet->tools) { - if (*tool_ptr == tool) { // We already have a ref - // XXX: We *could* optimize the tool to the front of - // the list here, since we will probably get the next - // couple of events from the same tool. - // BUT the list should always be rather short (probably - // single digit amount of tools) so it might be more - // work than it saves - return; - } - } - - struct wlr_libinput_tablet_tool **dst = - wl_array_add(&tablet->tools, sizeof(tool)); - if (!dst) { - wlr_log(WLR_ERROR, "Failed to allocate memory for tracking tablet tool"); - return; - } - *dst = tool; - ++tool->pad_refs; + wl_list_insert(&dev->tablet_tools, &tool->link); + return tool; } void handle_tablet_tool_axis(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet tool event for a device with no tablet tools?"); - return; - } + struct wlr_tablet *wlr_tablet) { struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); - struct wlr_event_tablet_tool_axis wlr_event = { 0 }; - struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool( - libinput_event_tablet_tool_get_tool(tevent)); - ensure_tool_reference(tool, wlr_dev->tablet); + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool = + get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - wlr_event.device = wlr_dev; + struct wlr_event_tablet_tool_axis wlr_event = { 0 }; + + wlr_event.device = &wlr_tablet->base; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); @@ -234,27 +170,20 @@ void handle_tablet_tool_axis(struct libinput_event *event, wlr_event.updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL; wlr_event.wheel_delta = libinput_event_tablet_tool_get_wheel_delta(tevent); } - wlr_signal_emit_safe(&wlr_dev->tablet->events.axis, &wlr_event); + wlr_signal_emit_safe(&wlr_tablet->events.axis, &wlr_event); } void handle_tablet_tool_proximity(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet tool event for a device with no tablet tools?"); - return; - } + struct wlr_tablet *wlr_tablet) { struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); - struct wlr_event_tablet_tool_proximity wlr_event = { 0 }; - struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool( - libinput_event_tablet_tool_get_tool(tevent)); - ensure_tool_reference(tool, wlr_dev->tablet); + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool = + get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); + struct wlr_event_tablet_tool_proximity wlr_event = { 0 }; wlr_event.tool = &tool->wlr_tool; - wlr_event.device = wlr_dev; + wlr_event.device = &wlr_tablet->base; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); wlr_event.x = libinput_event_tablet_tool_get_x_transformed(tevent, 1); @@ -268,56 +197,34 @@ void handle_tablet_tool_proximity(struct libinput_event *event, wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN; break; } - wlr_signal_emit_safe(&wlr_dev->tablet->events.proximity, &wlr_event); + wlr_signal_emit_safe(&wlr_tablet->events.proximity, &wlr_event); if (libinput_event_tablet_tool_get_proximity_state(tevent) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) { - handle_tablet_tool_axis(event, libinput_dev); + handle_tablet_tool_axis(event, wlr_tablet); } // If the tool is not unique, libinput will not find it again after the // proximity out, so we should destroy it - if (!tool->unique && - libinput_event_tablet_tool_get_proximity_state(tevent) == + if (!libinput_tablet_tool_is_unique(tool->handle) + && libinput_event_tablet_tool_get_proximity_state(tevent) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) { // The tool isn't unique, it can't be on multiple tablets - assert(tool->pad_refs == 1); - assert(tablet_is_libinput(wlr_dev->tablet)); - struct wlr_libinput_tablet *tablet = - wl_container_of(wlr_dev->tablet, tablet, wlr_tablet); - - size_t i = 0; - struct wlr_libinput_tablet_tool **tool_ptr; - wl_array_for_each(tool_ptr, &tablet->tools) { - if (*tool_ptr == tool) { - array_remove_at(&tablet->tools, i * sizeof(tool), sizeof(tool)); - break; - } - i++; - } - - destroy_tool(tool); + tool_destroy(tool); } } void handle_tablet_tool_tip(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet tool event for a device with no tablet tools?"); - return; - } - handle_tablet_tool_axis(event, libinput_dev); + struct wlr_tablet *wlr_tablet) { + handle_tablet_tool_axis(event, wlr_tablet); struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); - struct wlr_event_tablet_tool_tip wlr_event = { 0 }; - struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool( - libinput_event_tablet_tool_get_tool(tevent)); - ensure_tool_reference(tool, wlr_dev->tablet); + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool = + get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - wlr_event.device = wlr_dev; + struct wlr_event_tablet_tool_tip wlr_event = { 0 }; + wlr_event.device = &wlr_tablet->base; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); @@ -332,27 +239,20 @@ void handle_tablet_tool_tip(struct libinput_event *event, wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN; break; } - wlr_signal_emit_safe(&wlr_dev->tablet->events.tip, &wlr_event); + wlr_signal_emit_safe(&wlr_tablet->events.tip, &wlr_event); } void handle_tablet_tool_button(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet tool event for a device with no tablet tools?"); - return; - } - handle_tablet_tool_axis(event, libinput_dev); + struct wlr_tablet *wlr_tablet) { + handle_tablet_tool_axis(event, wlr_tablet); struct libinput_event_tablet_tool *tevent = libinput_event_get_tablet_tool_event(event); - struct wlr_event_tablet_tool_button wlr_event = { 0 }; - struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool( - libinput_event_tablet_tool_get_tool(tevent)); - ensure_tool_reference(tool, wlr_dev->tablet); + struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); + struct tablet_tool *tool = + get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - wlr_event.device = wlr_dev; + struct wlr_event_tablet_tool_button wlr_event = { 0 }; + wlr_event.device = &wlr_tablet->base; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); @@ -365,5 +265,5 @@ void handle_tablet_tool_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_PRESSED; break; } - wlr_signal_emit_safe(&wlr_dev->tablet->events.button, &wlr_event); + wlr_signal_emit_safe(&wlr_tablet->events.button, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index c8719af3d..808da1015 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -38,6 +38,8 @@ struct wlr_libinput_input_device { struct wlr_pointer pointer; struct wlr_switch switch_device; struct wlr_touch touch; + struct wlr_tablet tablet; + struct wl_list tablet_tools; // see backend/libinput/tablet_tool.c struct wl_list link; }; @@ -111,16 +113,17 @@ void handle_touch_cancel(struct libinput_event *event, void handle_touch_frame(struct libinput_event *event, struct wlr_touch *touch); -struct wlr_tablet *create_libinput_tablet( - struct libinput_device *device); +void init_device_tablet(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_tablet( + struct wlr_tablet *tablet); void handle_tablet_tool_axis(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet *tablet); void handle_tablet_tool_proximity(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet *tablet); void handle_tablet_tool_tip(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet *tablet); void handle_tablet_tool_button(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet *tablet); struct wlr_tablet_pad *create_libinput_tablet_pad( struct libinput_device *device); From 0d21496e53e88a65347ae7ffab3d4a20403f838a Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 24 Feb 2022 15:30:26 -0500 Subject: [PATCH 013/298] backend/libinput: rework tablet_pad interface The wlr_libinput_input_device now owns its wlr_tablet_pad, instead of creating a new wlr_libinput_input_device for it. --- backend/libinput/backend.c | 5 +- backend/libinput/events.c | 58 ++++------------ backend/libinput/tablet_pad.c | 121 ++++++++++++++++++++-------------- include/backend/libinput.h | 12 ++-- 4 files changed, 94 insertions(+), 102 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 111ebf3e6..68e6a0e85 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -255,11 +255,10 @@ struct libinput_device *wlr_libinput_get_device_handle( case WLR_INPUT_DEVICE_TABLET_TOOL: dev = device_from_tablet(wlr_dev->tablet); break; - default: - dev = (struct wlr_libinput_input_device *)wlr_dev; + case WLR_INPUT_DEVICE_TABLET_PAD: + dev = device_from_tablet_pad(wlr_dev->tablet_pad); break; } - return dev->handle; } diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 76e7709c2..44800d363 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -52,6 +52,9 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) if (dev->tablet.impl) { wlr_tablet_destroy(&dev->tablet); } + if (dev->tablet_pad.impl) { + wlr_tablet_pad_destroy(&dev->tablet_pad); + } } libinput_device_unref(dev->handle); @@ -59,32 +62,6 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) free(dev); } -static struct wlr_input_device *allocate_device( - struct wlr_libinput_backend *backend, - struct libinput_device *libinput_dev, struct wl_list *wlr_devices, - enum wlr_input_device_type type) { - const char *name = libinput_device_get_name(libinput_dev); - struct wlr_libinput_input_device *dev = - calloc(1, sizeof(struct wlr_libinput_input_device)); - if (dev == NULL) { - return NULL; - } - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - libinput_device_get_size(libinput_dev, - &wlr_dev->width_mm, &wlr_dev->height_mm); - const char *output_name = libinput_device_get_output_name(libinput_dev); - if (output_name != NULL) { - wlr_dev->output_name = strdup(output_name); - } - wl_list_insert(wlr_devices, &dev->link); - dev->handle = libinput_dev; - libinput_device_ref(libinput_dev); - wlr_input_device_init(wlr_dev, type, name); - wlr_dev->vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_dev->product = libinput_device_get_id_product(libinput_dev); - return wlr_dev; -} - bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) { switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: @@ -173,6 +150,14 @@ static void handle_device_added(struct wlr_libinput_backend *backend, dev_used = true; } + if (libinput_device_has_capability( + libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { + init_device_tablet_pad(dev); + wlr_signal_emit_safe(&backend->backend.events.new_input, + &dev->tablet_pad.base); + dev_used = true; + } + if (dev_used) { wl_list_insert(&backend->devices, &dev->link); return; @@ -187,21 +172,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, return; } wl_list_init(wlr_devices); - - if (libinput_device_has_capability( - libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { - struct wlr_input_device *wlr_dev = allocate_device(backend, - libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_PAD); - if (!wlr_dev) { - goto fail; - } - wlr_dev->tablet_pad = create_libinput_tablet_pad(libinput_dev); - if (!wlr_dev->tablet_pad) { - free(wlr_dev); - goto fail; - } - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); - } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) { // TODO @@ -325,13 +295,13 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_tablet_tool_button(event, &dev->tablet); break; case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - handle_tablet_pad_button(event, libinput_dev); + handle_tablet_pad_button(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_TABLET_PAD_RING: - handle_tablet_pad_ring(event, libinput_dev); + handle_tablet_pad_ring(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_TABLET_PAD_STRIP: - handle_tablet_pad_strip(event, libinput_dev); + handle_tablet_pad_strip(event, &dev->tablet_pad); break; case LIBINPUT_EVENT_SWITCH_TOGGLE: handle_switch_toggle(event, &dev->switch_device); diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 50b8ad6e7..ba9885574 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -1,17 +1,20 @@ -#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif #include #include #include #include -#include #include -#include #include #include "backend/libinput.h" #include "util/signal.h" +static void group_destroy(struct wlr_tablet_pad_group *group) { + free(group->buttons); + free(group->strips); + free(group->rings); + free(group); +} + // FIXME: Decide on how to alloc/count here static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, struct libinput_device *device, unsigned int index) { @@ -20,6 +23,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, struct wlr_tablet_pad_group *group = calloc(1, sizeof(struct wlr_tablet_pad_group)); if (!group) { + wlr_log_errno(WLR_ERROR, "failed to allocate wlr_tablet_pad_group"); return; } @@ -29,6 +33,10 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->rings = calloc(sizeof(unsigned int), group->ring_count); + if (group->rings == NULL) { + goto group_fail; + } + size_t ring = 0; for (size_t i = 0; i < pad->ring_count; ++i) { if (libinput_tablet_pad_mode_group_has_ring(li_group, i)) { @@ -42,6 +50,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->strips = calloc(sizeof(unsigned int), group->strip_count); + if (group->strips == NULL) { + goto group_fail; + } size_t strip = 0; for (size_t i = 0; i < pad->strip_count; ++i) { if (libinput_tablet_pad_mode_group_has_strip(li_group, i)) { @@ -55,6 +66,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } } group->buttons = calloc(sizeof(unsigned int), group->button_count); + if (group->buttons == NULL) { + goto group_fail; + } size_t button = 0; for (size_t i = 0; i < pad->button_count; ++i) { if (libinput_tablet_pad_mode_group_has_button(li_group, i)) { @@ -63,53 +77,74 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, } group->mode_count = libinput_tablet_pad_mode_group_get_num_modes(li_group); + + libinput_tablet_pad_mode_group_ref(li_group); + wl_list_insert(&pad->groups, &group->link); + return; + +group_fail: + wlr_log(WLR_ERROR, "failed to configure wlr_tablet_pad_group"); + group_destroy(group); } -const struct wlr_tablet_pad_impl libinput_tablet_pad_impl; +static void tablet_pad_destroy(struct wlr_tablet_pad *wlr_tablet_pad) { + struct wlr_libinput_input_device *dev = + device_from_tablet_pad(wlr_tablet_pad); -struct wlr_tablet_pad *create_libinput_tablet_pad( - struct libinput_device *libinput_dev) { - assert(libinput_dev); - struct wlr_tablet_pad *wlr_tablet_pad = - calloc(1, sizeof(struct wlr_tablet_pad)); - if (!wlr_tablet_pad) { - wlr_log(WLR_ERROR, "Unable to allocate wlr_tablet_pad"); - return NULL; + struct wlr_tablet_pad_group *group, *tmp; + wl_list_for_each_safe(group, tmp, &wlr_tablet_pad->groups, link) { + group_destroy(group); } - const char *name = libinput_device_get_name(libinput_dev); + + int groups = libinput_device_tablet_pad_get_num_mode_groups(dev->handle); + for (int i = 0; i < groups; ++i) { + struct libinput_tablet_pad_mode_group *li_group = + libinput_device_tablet_pad_get_mode_group(dev->handle, i); + libinput_tablet_pad_mode_group_unref(li_group); + } +} + +const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = { + .destroy = tablet_pad_destroy, +}; + +void init_device_tablet_pad(struct wlr_libinput_input_device *dev) { + struct libinput_device *handle = dev->handle; + const char *name = libinput_device_get_name(handle); + struct wlr_tablet_pad *wlr_tablet_pad = &dev->tablet_pad; wlr_tablet_pad_init(wlr_tablet_pad, &libinput_tablet_pad_impl, name); - wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(libinput_dev); - wlr_tablet_pad->base.product = libinput_device_get_id_product(libinput_dev); + wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(handle); + wlr_tablet_pad->base.product = libinput_device_get_id_product(handle); wlr_tablet_pad->button_count = - libinput_device_tablet_pad_get_num_buttons(libinput_dev); + libinput_device_tablet_pad_get_num_buttons(handle); wlr_tablet_pad->ring_count = - libinput_device_tablet_pad_get_num_rings(libinput_dev); + libinput_device_tablet_pad_get_num_rings(handle); wlr_tablet_pad->strip_count = - libinput_device_tablet_pad_get_num_strips(libinput_dev); + libinput_device_tablet_pad_get_num_strips(handle); - struct udev_device *udev = libinput_device_get_udev_device(libinput_dev); + struct udev_device *udev = libinput_device_get_udev_device(handle); char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); - int groups = libinput_device_tablet_pad_get_num_mode_groups(libinput_dev); + int groups = libinput_device_tablet_pad_get_num_mode_groups(handle); for (int i = 0; i < groups; ++i) { - add_pad_group_from_libinput(wlr_tablet_pad, libinput_dev, i); + add_pad_group_from_libinput(wlr_tablet_pad, handle, i); } +} - return wlr_tablet_pad; +struct wlr_libinput_input_device *device_from_tablet_pad( + struct wlr_tablet_pad *wlr_tablet_pad) { + assert(wlr_tablet_pad->impl == &libinput_tablet_pad_impl); + + struct wlr_libinput_input_device *dev = + wl_container_of(wlr_tablet_pad, dev, tablet_pad); + return dev; } void handle_tablet_pad_button(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_button wlr_event = { 0 }; @@ -127,18 +162,11 @@ void handle_tablet_pad_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_RELEASED; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.button, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.button, &wlr_event); } void handle_tablet_pad_ring(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_ring wlr_event = { 0 }; @@ -155,18 +183,11 @@ void handle_tablet_pad_ring(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_RING_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.ring, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.ring, &wlr_event); } void handle_tablet_pad_strip(struct libinput_event *event, - struct libinput_device *libinput_dev) { - struct wlr_input_device *wlr_dev = - get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev); - if (!wlr_dev) { - wlr_log(WLR_DEBUG, - "Got a tablet pad event for a device with no tablet pad?"); - return; - } + struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); struct wlr_event_tablet_pad_strip wlr_event = { 0 }; @@ -183,5 +204,5 @@ void handle_tablet_pad_strip(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_STRIP_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.strip, &wlr_event); + wlr_signal_emit_safe(&tablet_pad->events.strip, &wlr_event); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 808da1015..6579b1afd 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -40,6 +40,7 @@ struct wlr_libinput_input_device { struct wlr_touch touch; struct wlr_tablet tablet; struct wl_list tablet_tools; // see backend/libinput/tablet_tool.c + struct wlr_tablet_pad tablet_pad; struct wl_list link; }; @@ -125,13 +126,14 @@ void handle_tablet_tool_tip(struct libinput_event *event, void handle_tablet_tool_button(struct libinput_event *event, struct wlr_tablet *tablet); -struct wlr_tablet_pad *create_libinput_tablet_pad( - struct libinput_device *device); +void init_device_tablet_pad(struct wlr_libinput_input_device *dev); +struct wlr_libinput_input_device *device_from_tablet_pad( + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_button(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_ring(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_strip(struct libinput_event *event, - struct libinput_device *device); + struct wlr_tablet_pad *tablet_pad); #endif From d0718a9b32dc9d80b35eae269b60a22caa9c268f Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 24 Feb 2022 15:53:54 -0500 Subject: [PATCH 014/298] backend/libinput: public API cleanup --- backend/libinput/backend.c | 17 +--- backend/libinput/events.c | 159 ++++++++----------------------------- include/backend/libinput.h | 19 ++--- 3 files changed, 40 insertions(+), 155 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 68e6a0e85..60f456cc1 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -110,11 +110,9 @@ static bool backend_start(struct wlr_backend *wlr_backend) { no_devs = NULL; } } - if (!no_devs && (backend->wlr_device_lists.size == 0 - || wl_list_empty(&backend->devices))) { + if (!no_devs && wl_list_empty(&backend->devices)) { handle_libinput_readable(libinput_fd, WL_EVENT_READABLE, backend); - if (backend->wlr_device_lists.size == 0 - && wl_list_empty(&backend->devices)) { + if (wl_list_empty(&backend->devices)) { wlr_log(WLR_ERROR, "libinput initialization failed, no input devices"); wlr_log(WLR_ERROR, "Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check"); return false; @@ -143,15 +141,6 @@ static void backend_destroy(struct wlr_backend *wlr_backend) { struct wlr_libinput_backend *backend = get_libinput_backend_from_backend(wlr_backend); - struct wl_list **wlr_devices_ptr; - wl_array_for_each(wlr_devices_ptr, &backend->wlr_device_lists) { - struct wlr_libinput_input_device *dev, *tmp; - wl_list_for_each_safe(dev, tmp, *wlr_devices_ptr, link) { - destroy_libinput_input_device(dev); - } - free(*wlr_devices_ptr); - } - struct wlr_libinput_input_device *dev, *tmp; wl_list_for_each_safe(dev, tmp, &backend->devices, link) { destroy_libinput_input_device(dev); @@ -163,7 +152,6 @@ static void backend_destroy(struct wlr_backend *wlr_backend) { wl_list_remove(&backend->session_destroy.link); wl_list_remove(&backend->session_signal.link); - wl_array_release(&backend->wlr_device_lists); if (backend->input_event) { wl_event_source_remove(backend->input_event); } @@ -218,7 +206,6 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, } wlr_backend_init(&backend->backend, &backend_impl); - wl_array_init(&backend->wlr_device_lists); wl_list_init(&backend->devices); backend->session = session; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 44800d363..af5bb1843 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -1,60 +1,36 @@ #define _POSIX_C_SOURCE 200809L -#include + #include #include -#include #include +#include +#include +#include +#include +#include +#include #include #include "backend/libinput.h" -#include "util/array.h" #include "util/signal.h" -struct wlr_input_device *get_appropriate_device( - enum wlr_input_device_type desired_type, - struct libinput_device *libinput_dev) { - struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev); - if (!wlr_devices) { - return NULL; +void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { + if (dev->keyboard.impl) { + wlr_keyboard_destroy(&dev->keyboard); } - struct wlr_libinput_input_device *dev; - wl_list_for_each(dev, wlr_devices, link) { - if (dev->wlr_input_device.type == desired_type) { - return &dev->wlr_input_device; - } + if (dev->pointer.impl) { + wlr_pointer_destroy(&dev->pointer); } - return NULL; -} - - -void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) -{ - /** - * TODO remove the redundant wlr_input_device from wlr_libinput_input_device - * wlr_libinput_input_device::wlr_input_device is not owned by its input - * device type, which means we have 2 wlr_input_device to cleanup - */ - if (dev->wlr_input_device._device) { - wlr_input_device_destroy(&dev->wlr_input_device); - wlr_input_device_finish(&dev->wlr_input_device); - } else { - if (dev->keyboard.impl) { - wlr_keyboard_destroy(&dev->keyboard); - } - if (dev->pointer.impl) { - wlr_pointer_destroy(&dev->pointer); - } - if (dev->switch_device.impl) { - wlr_switch_destroy(&dev->switch_device); - } - if (dev->touch.impl) { - wlr_touch_destroy(&dev->touch); - } - if (dev->tablet.impl) { - wlr_tablet_destroy(&dev->tablet); - } - if (dev->tablet_pad.impl) { - wlr_tablet_pad_destroy(&dev->tablet_pad); - } + if (dev->switch_device.impl) { + wlr_switch_destroy(&dev->switch_device); + } + if (dev->touch.impl) { + wlr_touch_destroy(&dev->touch); + } + if (dev->tablet.impl) { + wlr_tablet_destroy(&dev->tablet); + } + if (dev->tablet_pad.impl) { + wlr_tablet_pad_destroy(&dev->tablet_pad); } libinput_device_unref(dev->handle); @@ -83,16 +59,10 @@ bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) { static void handle_device_added(struct wlr_libinput_backend *backend, struct libinput_device *libinput_dev) { - /* - * Note: the wlr API exposes only devices with a single capability, because - * that meshes better with how Wayland does things and is a bit simpler. - * However, libinput devices often have multiple capabilities - in such - * cases we have to create several devices. - */ int vendor = libinput_device_get_id_vendor(libinput_dev); int product = libinput_device_get_id_product(libinput_dev); const char *name = libinput_device_get_name(libinput_dev); - wlr_log(WLR_DEBUG, "Added %s [%d:%d]", name, vendor, product); + wlr_log(WLR_DEBUG, "Adding %s [%d:%d]", name, vendor, product); struct wlr_libinput_input_device *dev = calloc(1, sizeof(struct wlr_libinput_input_device)); @@ -105,7 +75,7 @@ static void handle_device_added(struct wlr_libinput_backend *backend, libinput_device_ref(libinput_dev); libinput_device_set_user_data(libinput_dev, dev); - bool dev_used = false; + wl_list_insert(&backend->devices, &dev->link); if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { @@ -113,7 +83,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->keyboard.base); - dev_used = true; } if (libinput_device_has_capability( @@ -122,8 +91,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->pointer.base); - - dev_used = true; } if (libinput_device_has_capability( @@ -131,7 +98,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, init_device_switch(dev); wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->switch_device.base); - dev_used = true; } if (libinput_device_has_capability( @@ -139,7 +105,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, init_device_touch(dev); wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->touch.base); - dev_used = true; } if (libinput_device_has_capability(libinput_dev, @@ -147,7 +112,6 @@ static void handle_device_added(struct wlr_libinput_backend *backend, init_device_tablet(dev); wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->tablet.base); - dev_used = true; } if (libinput_device_has_capability( @@ -155,48 +119,12 @@ static void handle_device_added(struct wlr_libinput_backend *backend, init_device_tablet_pad(dev); wlr_signal_emit_safe(&backend->backend.events.new_input, &dev->tablet_pad.base); - dev_used = true; } - if (dev_used) { - wl_list_insert(&backend->devices, &dev->link); - return; - } else { - libinput_device_unref(libinput_dev); - free(dev); - } - - struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list)); - if (!wlr_devices) { - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - wl_list_init(wlr_devices); if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) { - // TODO + wlr_log(WLR_DEBUG, "libinput gesture not handled"); } - - if (!wl_list_empty(wlr_devices)) { - struct wl_list **dst = wl_array_add(&backend->wlr_device_lists, sizeof(wlr_devices)); - if (!dst) { - goto fail; - } - *dst = wlr_devices; - - libinput_device_set_user_data(libinput_dev, wlr_devices); - } else { - free(wlr_devices); - } - return; - -fail: - wlr_log(WLR_ERROR, "Could not allocate new device"); - struct wlr_libinput_input_device *device, *tmp; - wl_list_for_each_safe(device, tmp, wlr_devices, link) { - free(device); - } - free(wlr_devices); } static void handle_device_removed(struct wlr_libinput_backend *backend, @@ -206,37 +134,14 @@ static void handle_device_removed(struct wlr_libinput_backend *backend, const char *name = libinput_device_get_name(libinput_dev); wlr_log(WLR_DEBUG, "Removing %s [%d:%d]", name, vendor, product); - // TODO: use libinput_device_get_user_data(libinput_dev); - if (!wl_list_empty(&backend->devices)) { - struct wlr_libinput_input_device *dev, *tmp_dev; - wl_list_for_each_safe(dev, tmp_dev, &backend->devices, link) { - if (dev->handle == libinput_dev) { - destroy_libinput_input_device(dev); - return; - } - } - } - - struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev); - if (!wlr_devices) { + struct wlr_libinput_input_device *dev = + libinput_device_get_user_data(libinput_dev); + if (dev == NULL) { + wlr_log(WLR_ERROR, "libinput_device has no wlr_libinput_input_device"); return; } - struct wlr_libinput_input_device *dev, *tmp_dev; - wl_list_for_each_safe(dev, tmp_dev, wlr_devices, link) { - destroy_libinput_input_device(dev); - } - size_t i = 0; - struct wl_list **ptr; - wl_array_for_each(ptr, &backend->wlr_device_lists) { - struct wl_list *iter = *ptr; - if (iter == wlr_devices) { - array_remove_at(&backend->wlr_device_lists, - i * sizeof(struct wl_list *), sizeof(struct wl_list *)); - break; - } - i++; - } - free(wlr_devices); + + destroy_libinput_input_device(dev); } void handle_libinput_event(struct wlr_libinput_backend *backend, diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 6579b1afd..f22e7761c 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -5,13 +5,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include struct wlr_libinput_backend { struct wlr_backend backend; @@ -26,12 +25,10 @@ struct wlr_libinput_backend { struct wl_listener session_destroy; struct wl_listener session_signal; - struct wl_array wlr_device_lists; // struct wl_list * struct wl_list devices; // wlr_libinput_device::link }; struct wlr_libinput_input_device { - struct wlr_input_device wlr_input_device; struct libinput_device *handle; struct wlr_keyboard keyboard; @@ -50,10 +47,6 @@ uint32_t usec_to_msec(uint64_t usec); void handle_libinput_event(struct wlr_libinput_backend *state, struct libinput_event *event); -struct wlr_input_device *get_appropriate_device( - enum wlr_input_device_type desired_type, - struct libinput_device *device); - void destroy_libinput_input_device(struct wlr_libinput_input_device *dev); extern const struct wlr_keyboard_impl libinput_keyboard_impl; From 39b68ea47a661b1f7562ce283652de08f222b2be Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 3 Mar 2022 15:38:26 +0100 Subject: [PATCH 015/298] buffer: extract interface to separate header Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3389 --- include/wlr/interfaces/wlr_buffer.h | 48 +++++++++++++++++++++++++++++ include/wlr/types/wlr_buffer.h | 32 ------------------- render/allocator/allocator.c | 1 + render/allocator/drm_dumb.c | 1 + render/allocator/gbm.c | 1 + render/allocator/shm.c | 1 + types/wlr_buffer.c | 1 + types/wlr_drm.c | 1 + types/wlr_linux_dmabuf_v1.c | 1 + 9 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 include/wlr/interfaces/wlr_buffer.h diff --git a/include/wlr/interfaces/wlr_buffer.h b/include/wlr/interfaces/wlr_buffer.h new file mode 100644 index 000000000..05ccc1e7e --- /dev/null +++ b/include/wlr/interfaces/wlr_buffer.h @@ -0,0 +1,48 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_INTERFACES_WLR_BUFFER_H +#define WLR_INTERFACES_WLR_BUFFER_H + +#include + +struct wlr_buffer_impl { + void (*destroy)(struct wlr_buffer *buffer); + bool (*get_dmabuf)(struct wlr_buffer *buffer, + struct wlr_dmabuf_attributes *attribs); + bool (*get_shm)(struct wlr_buffer *buffer, + struct wlr_shm_attributes *attribs); + bool (*begin_data_ptr_access)(struct wlr_buffer *buffer, uint32_t flags, + void **data, uint32_t *format, size_t *stride); + void (*end_data_ptr_access)(struct wlr_buffer *buffer); +}; + +struct wlr_buffer_resource_interface { + const char *name; + bool (*is_instance)(struct wl_resource *resource); + struct wlr_buffer *(*from_resource)(struct wl_resource *resource); +}; + +/** + * Initialize a buffer. This function should be called by producers. The + * initialized buffer is referenced: once the producer is done with the buffer + * they should call wlr_buffer_drop. + */ +void wlr_buffer_init(struct wlr_buffer *buffer, + const struct wlr_buffer_impl *impl, int width, int height); + +/** + * Allows the registration of a wl_resource implementation. + * + * The matching function will be called for the wl_resource when creating a + * wlr_buffer from a wl_resource. + */ +void wlr_buffer_register_resource_interface( + const struct wlr_buffer_resource_interface *iface); + +#endif diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 60dbb5c38..604dc17a3 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -24,17 +24,6 @@ struct wlr_shm_attributes { off_t offset; }; -struct wlr_buffer_impl { - void (*destroy)(struct wlr_buffer *buffer); - bool (*get_dmabuf)(struct wlr_buffer *buffer, - struct wlr_dmabuf_attributes *attribs); - bool (*get_shm)(struct wlr_buffer *buffer, - struct wlr_shm_attributes *attribs); - bool (*begin_data_ptr_access)(struct wlr_buffer *buffer, uint32_t flags, - void **data, uint32_t *format, size_t *stride); - void (*end_data_ptr_access)(struct wlr_buffer *buffer); -}; - /** * Buffer capabilities. * @@ -72,19 +61,6 @@ struct wlr_buffer { struct wlr_addon_set addons; }; -struct wlr_buffer_resource_interface { - const char *name; - bool (*is_instance)(struct wl_resource *resource); - struct wlr_buffer *(*from_resource)(struct wl_resource *resource); -}; - -/** - * Initialize a buffer. This function should be called by producers. The - * initialized buffer is referenced: once the producer is done with the buffer - * they should call wlr_buffer_drop. - */ -void wlr_buffer_init(struct wlr_buffer *buffer, - const struct wlr_buffer_impl *impl, int width, int height); /** * Unreference the buffer. This function should be called by producers when * they are done with the buffer. @@ -121,14 +97,6 @@ bool wlr_buffer_get_dmabuf(struct wlr_buffer *buffer, */ bool wlr_buffer_get_shm(struct wlr_buffer *buffer, struct wlr_shm_attributes *attribs); -/** - * Allows the registration of a wl_resource implementation. - * - * The matching function will be called for the wl_resource when creating a - * wlr_buffer from a wl_resource. - */ -void wlr_buffer_register_resource_interface( - const struct wlr_buffer_resource_interface *iface); /** * Transforms a wl_resource into a wlr_buffer and locks it. Once the caller is * done with the buffer, they must call wlr_buffer_unlock. diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 5108ad043..0597cf256 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/render/allocator/drm_dumb.c b/render/allocator/drm_dumb.c index 5b47462bc..e2812ecb6 100644 --- a/render/allocator/drm_dumb.c +++ b/render/allocator/drm_dumb.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/render/allocator/gbm.c b/render/allocator/gbm.c index 8f73862a2..8c670774b 100644 --- a/render/allocator/gbm.c +++ b/render/allocator/gbm.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/render/allocator/shm.c b/render/allocator/shm.c index 044d5eb12..9e49a1445 100644 --- a/render/allocator/shm.c +++ b/render/allocator/shm.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index fa281c682..0e091f569 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/types/wlr_drm.c b/types/wlr_drm.c index a02fba841..0d50138cc 100644 --- a/types/wlr_drm.c +++ b/types/wlr_drm.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index 5138e469f..69aa64b78 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include From 7dc4a3ecd71cf41dd1800c6afd3b16c83a90f031 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 1 Mar 2022 14:49:30 -0500 Subject: [PATCH 016/298] interface/wlr_keyboard: rework destroy sequence The destroy member in wlr_keyboard_impl has been removed. The function `wlr_keyboard_finish` has been introduce to clean up the resources owned by a wlr_keyboard. `wlr_input_device_destroy` no longer destroys the wlr_keyboard, attempting to destroy a wlr_keyboard will result in a no-op. The field `name` has been added to the wlr_keyboard_impl to be able to identify a given wlr_keyboard device. --- backend/libinput/events.c | 2 +- backend/libinput/keyboard.c | 6 +---- backend/wayland/seat.c | 15 +++++++++-- backend/x11/backend.c | 5 ++-- backend/x11/input_device.c | 6 +---- include/wlr/interfaces/wlr_keyboard.h | 11 +++++--- types/wlr_input_device.c | 3 +-- types/wlr_keyboard.c | 25 ++++++++++++------- types/wlr_keyboard_group.c | 16 +++--------- types/wlr_virtual_keyboard_v1.c | 36 ++++----------------------- 10 files changed, 52 insertions(+), 73 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index af5bb1843..af54177c9 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -15,7 +15,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { if (dev->keyboard.impl) { - wlr_keyboard_destroy(&dev->keyboard); + wlr_keyboard_finish(&dev->keyboard); } if (dev->pointer.impl) { wlr_pointer_destroy(&dev->pointer); diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index cf6b9836e..210fd4501 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -17,12 +17,8 @@ static void keyboard_set_leds(struct wlr_keyboard *wlr_kb, uint32_t leds) { libinput_device_led_update(dev->handle, leds); } -static void keyboard_destroy(struct wlr_keyboard *wlr_kb) { - /* wlr_keyboard belongs to the wlr_libinput_input_device */ -} - const struct wlr_keyboard_impl libinput_keyboard_impl = { - .destroy = keyboard_destroy, + .name = "libinput-keyboard", .led_update = keyboard_set_leds }; diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 28466bb33..e2a61bd48 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -24,7 +24,9 @@ #include "util/time.h" static const struct wlr_pointer_impl pointer_impl; -static const struct wlr_keyboard_impl keyboard_impl; +static const struct wlr_keyboard_impl keyboard_impl = { + .name = "wl-keyboard", +}; static const struct wlr_touch_impl touch_impl; static struct wlr_wl_pointer *output_get_pointer( @@ -506,7 +508,16 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { */ wlr_input_device_finish(&dev->wlr_input_device); if (dev->wlr_input_device._device) { - wlr_input_device_destroy(&dev->wlr_input_device); + struct wlr_input_device *wlr_dev = &dev->wlr_input_device; + switch (wlr_dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + wlr_keyboard_finish(wlr_dev->keyboard); + free(wlr_dev->keyboard); + break; + default: + wlr_input_device_destroy(wlr_dev); + break; + } } wl_list_remove(&dev->link); free(dev); diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 64bcf475b..dbbd74e89 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -185,7 +185,7 @@ static void backend_destroy(struct wlr_backend *backend) { wlr_output_destroy(&output->wlr_output); } - wlr_keyboard_destroy(&x11->keyboard); + wlr_keyboard_finish(&x11->keyboard); wlr_backend_finish(backend); @@ -637,7 +637,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, } #endif - wlr_keyboard_init(&x11->keyboard, &x11_keyboard_impl, "x11-keyboard"); + wlr_keyboard_init(&x11->keyboard, &x11_keyboard_impl, + x11_keyboard_impl.name); x11->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(display, &x11->display_destroy); diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index f87f53a0d..3bbbe594a 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -285,12 +285,8 @@ void handle_x11_xinput_event(struct wlr_x11_backend *x11, } } -static void keyboard_destroy(struct wlr_keyboard *wlr_keyboard) { - // Don't free the keyboard, it's on the stack -} - const struct wlr_keyboard_impl x11_keyboard_impl = { - .destroy = keyboard_destroy, + .name = "x11-keyboard", }; static void pointer_destroy(struct wlr_pointer *wlr_pointer) { diff --git a/include/wlr/interfaces/wlr_keyboard.h b/include/wlr/interfaces/wlr_keyboard.h index 4bcef57b2..3f4c42552 100644 --- a/include/wlr/interfaces/wlr_keyboard.h +++ b/include/wlr/interfaces/wlr_keyboard.h @@ -13,13 +13,18 @@ #include struct wlr_keyboard_impl { - void (*destroy)(struct wlr_keyboard *keyboard); + const char *name; void (*led_update)(struct wlr_keyboard *keyboard, uint32_t leds); }; void wlr_keyboard_init(struct wlr_keyboard *keyboard, - const struct wlr_keyboard_impl *impl, const char *name); -void wlr_keyboard_destroy(struct wlr_keyboard *keyboard); + const struct wlr_keyboard_impl *impl, const char *name); + +/** + * Cleans up all of the resources owned by wlr_keyboard. + */ +void wlr_keyboard_finish(struct wlr_keyboard *keyboard); + void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, struct wlr_event_keyboard_key *event); void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 6897febed..4a9ef806e 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -41,7 +40,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { if (dev->_device) { switch (dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - wlr_keyboard_destroy(dev->keyboard); + wlr_log(WLR_ERROR, "wlr_keyboard will not be destroyed"); break; case WLR_INPUT_DEVICE_POINTER: wlr_pointer_destroy(dev->pointer); diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index afa689b12..372efcb58 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -11,6 +11,7 @@ #include "util/array.h" #include "util/shm.h" #include "util/signal.h" +#include "util/time.h" void keyboard_led_update(struct wlr_keyboard *keyboard) { if (keyboard->xkb_state == NULL) { @@ -132,25 +133,31 @@ void wlr_keyboard_init(struct wlr_keyboard *kb, kb->repeat_info.delay = 600; } -void wlr_keyboard_destroy(struct wlr_keyboard *kb) { - if (kb == NULL) { - return; +void wlr_keyboard_finish(struct wlr_keyboard *kb) { + /* Release pressed keys */ + size_t orig_num_keycodes = kb->num_keycodes; + for (size_t i = 0; i < orig_num_keycodes; ++i) { + assert(kb->num_keycodes == orig_num_keycodes - i); + struct wlr_event_keyboard_key event = { + .time_msec = get_current_time_msec(), + .keycode = kb->keycodes[orig_num_keycodes - i - 1], + .update_state = false, + .state = WL_KEYBOARD_KEY_STATE_RELEASED, + }; + wlr_keyboard_notify_key(kb, &event); // updates num_keycodes } + wlr_signal_emit_safe(&kb->events.destroy, kb); + wlr_input_device_finish(&kb->base); + /* Finish xkbcommon resources */ xkb_state_unref(kb->xkb_state); xkb_keymap_unref(kb->keymap); free(kb->keymap_string); if (kb->keymap_fd >= 0) { close(kb->keymap_fd); } - if (kb->impl && kb->impl->destroy) { - kb->impl->destroy(kb); - } else { - wl_list_remove(&kb->events.key.listener_list); - free(kb); - } } void wlr_keyboard_led_update(struct wlr_keyboard *kb, uint32_t leds) { diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c index 35fc54702..465e9944f 100644 --- a/types/wlr_keyboard_group.c +++ b/types/wlr_keyboard_group.c @@ -37,18 +37,8 @@ static void keyboard_set_leds(struct wlr_keyboard *kb, uint32_t leds) { } } -static void keyboard_destroy(struct wlr_keyboard *kb) { - // Just remove the event listeners. The keyboard will be freed as part of - // the wlr_keyboard_group in wlr_keyboard_group_destroy. - wl_list_remove(&kb->events.key.listener_list); - wl_list_remove(&kb->events.modifiers.listener_list); - wl_list_remove(&kb->events.keymap.listener_list); - wl_list_remove(&kb->events.repeat_info.listener_list); - wl_list_remove(&kb->events.destroy.listener_list); -} - static const struct wlr_keyboard_impl impl = { - .destroy = keyboard_destroy, + .name = "keyboard-group", .led_update = keyboard_set_leds }; @@ -60,7 +50,7 @@ struct wlr_keyboard_group *wlr_keyboard_group_create(void) { return NULL; } - wlr_keyboard_init(&group->keyboard, &impl, "keyboard-group"); + wlr_keyboard_init(&group->keyboard, &impl, "wlr_keyboard_group"); wl_list_init(&group->devices); wl_list_init(&group->keys); @@ -325,7 +315,7 @@ void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) { wl_list_for_each_safe(device, tmp, &group->devices, link) { wlr_keyboard_group_remove_keyboard(group, device->keyboard); } - wlr_keyboard_destroy(&group->keyboard); + wlr_keyboard_finish(&group->keyboard); wl_list_remove(&group->events.enter.listener_list); wl_list_remove(&group->events.leave.listener_list); free(group); diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index e40a97e82..5a5ce6308 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -9,36 +9,10 @@ #include #include #include "util/signal.h" -#include "util/time.h" #include "virtual-keyboard-unstable-v1-protocol.h" -/** - * Send release event for each pressed key to bring the keyboard back to - * neutral state. - * - * This may be needed for virtual keyboards. For physical devices, kernel - * or libinput will deal with the removal of devices. - */ -static void keyboard_release_pressed_keys(struct wlr_keyboard *keyboard) { - size_t orig_num_keycodes = keyboard->num_keycodes; - for (size_t i = 0; i < orig_num_keycodes; ++i) { - assert(keyboard->num_keycodes == orig_num_keycodes - i); - struct wlr_event_keyboard_key event = { - .time_msec = get_current_time_msec(), - .keycode = keyboard->keycodes[orig_num_keycodes - i - 1], - .update_state = false, - .state = WL_KEYBOARD_KEY_STATE_RELEASED, - }; - wlr_keyboard_notify_key(keyboard, &event); // updates num_keycodes - } -} - -static void keyboard_destroy(struct wlr_keyboard *wlr_kb) { - /* no-op, keyboard belongs to the wlr_virtual_keyboard_v1 */ -} - static const struct wlr_keyboard_impl keyboard_impl = { - .destroy = keyboard_destroy, + .name = "virtual-keyboard", }; static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl; @@ -135,10 +109,10 @@ static void virtual_keyboard_destroy_resource(struct wl_resource *resource) { return; } - /* TODO: rework wlr_keyboard device destruction */ - keyboard_release_pressed_keys(&keyboard->keyboard); wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); - wlr_keyboard_destroy(&keyboard->keyboard); + + wlr_keyboard_finish(&keyboard->keyboard); + wl_resource_set_user_data(keyboard->resource, NULL); wl_list_remove(&keyboard->link); free(keyboard); @@ -179,7 +153,7 @@ static void virtual_keyboard_manager_create_virtual_keyboard( } wlr_keyboard_init(&virtual_keyboard->keyboard, &keyboard_impl, - "virtual-keyboard"); + "wlr_virtual_keyboard_v1"); struct wl_resource *keyboard_resource = wl_resource_create(client, &zwp_virtual_keyboard_v1_interface, wl_resource_get_version(resource), From 51cd3c07264e1c4967c5baea3f6629ac01334e97 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 13:57:28 -0500 Subject: [PATCH 017/298] interface/wlr_pointer: rework destroy sequence The destroy callback in wlr_pointer_impl has been removed. The function `wlr_pointer_finish` has been introduced to clean up the resources owned by a wlr_pointer. `wlr_input_device_destroy` no longer destroys the wlr_pointer, attempting to destroy a wlr_pointer will result in a no-op. The field `name` has been added to the wlr_pointer_impl to be able to identify a given wlr_pointer device. --- backend/libinput/events.c | 2 +- backend/libinput/pointer.c | 6 +--- backend/wayland/seat.c | 53 ++++++++++++++-------------- backend/x11/input_device.c | 6 +--- backend/x11/output.c | 2 +- include/wlr/interfaces/wlr_pointer.h | 4 +-- types/wlr_input_device.c | 3 +- types/wlr_pointer.c | 10 +----- types/wlr_virtual_pointer_v1.c | 13 +++---- 9 files changed, 40 insertions(+), 59 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index af54177c9..22fdab556 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -18,7 +18,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { wlr_keyboard_finish(&dev->keyboard); } if (dev->pointer.impl) { - wlr_pointer_destroy(&dev->pointer); + wlr_pointer_finish(&dev->pointer); } if (dev->switch_device.impl) { wlr_switch_destroy(&dev->switch_device); diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 0ac781d70..8daf20057 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -4,12 +4,8 @@ #include "backend/libinput.h" #include "util/signal.h" -static void pointer_destroy(struct wlr_pointer *pointer) { - /* wlr_pointer belongs to the wlr_libinput_input_device */ -} - const struct wlr_pointer_impl libinput_pointer_impl = { - .destroy = pointer_destroy, + .name = "libinput-pointer", }; void init_device_pointer(struct wlr_libinput_input_device *dev) { diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index e2a61bd48..1edd0f2c0 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -500,29 +500,6 @@ struct wlr_wl_input_device *create_wl_input_device( return dev; } -void destroy_wl_input_device(struct wlr_wl_input_device *dev) { - /** - * TODO remove the redundant wlr_input_device from wlr_wl_input_device - * wlr_wl_input_device::wlr_input_device is not owned by its input device - * type, which means we have 2 wlr_input_device to cleanup - */ - wlr_input_device_finish(&dev->wlr_input_device); - if (dev->wlr_input_device._device) { - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - switch (wlr_dev->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - wlr_keyboard_finish(wlr_dev->keyboard); - free(wlr_dev->keyboard); - break; - default: - wlr_input_device_destroy(wlr_dev); - break; - } - } - wl_list_remove(&dev->link); - free(dev); -} - struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer) { assert(wlr_pointer->impl == &pointer_impl); return (struct wlr_wl_pointer *)wlr_pointer; @@ -555,13 +532,37 @@ static void pointer_destroy(struct wlr_pointer *wlr_pointer) { zwp_relative_pointer_v1_destroy(pointer->relative_pointer); } + wlr_pointer_finish(&pointer->wlr_pointer); wl_list_remove(&pointer->output_destroy.link); free(pointer); } -static const struct wlr_pointer_impl pointer_impl = { - .destroy = pointer_destroy, -}; +void destroy_wl_input_device(struct wlr_wl_input_device *dev) { + /** + * TODO remove the redundant wlr_input_device from wlr_wl_input_device + * wlr_wl_input_device::wlr_input_device is not owned by its input device + * type, which means we have 2 wlr_input_device to cleanup + */ + wlr_input_device_finish(&dev->wlr_input_device); + if (dev->wlr_input_device._device) { + struct wlr_input_device *wlr_dev = &dev->wlr_input_device; + switch (wlr_dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + wlr_keyboard_finish(wlr_dev->keyboard); + free(wlr_dev->keyboard); + break; + case WLR_INPUT_DEVICE_POINTER: + /* Owned by wlr_wl_pointer */ + pointer_destroy(wlr_dev->pointer); + break; + default: + wlr_input_device_destroy(wlr_dev); + break; + } + } + wl_list_remove(&dev->link); + free(dev); +} static void gesture_swipe_begin(void *data, struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 3bbbe594a..9182ba8e0 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -289,12 +289,8 @@ const struct wlr_keyboard_impl x11_keyboard_impl = { .name = "x11-keyboard", }; -static void pointer_destroy(struct wlr_pointer *wlr_pointer) { - // Don't free the pointer, it's on the stack -} - const struct wlr_pointer_impl x11_pointer_impl = { - .destroy = pointer_destroy, + .name = "x11-pointer", }; static void touch_destroy(struct wlr_touch *wlr_touch) { diff --git a/backend/x11/output.c b/backend/x11/output.c index 7037c36cc..24c08fceb 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -76,7 +76,7 @@ static void output_destroy(struct wlr_output *wlr_output) { pixman_region32_fini(&output->exposed); - wlr_pointer_destroy(&output->pointer); + wlr_pointer_finish(&output->pointer); wlr_touch_destroy(&output->touch); struct wlr_x11_buffer *buffer, *buffer_tmp; diff --git a/include/wlr/interfaces/wlr_pointer.h b/include/wlr/interfaces/wlr_pointer.h index e39500175..74e0feafe 100644 --- a/include/wlr/interfaces/wlr_pointer.h +++ b/include/wlr/interfaces/wlr_pointer.h @@ -12,11 +12,11 @@ #include struct wlr_pointer_impl { - void (*destroy)(struct wlr_pointer *pointer); + const char *name; }; void wlr_pointer_init(struct wlr_pointer *pointer, const struct wlr_pointer_impl *impl, const char *name); -void wlr_pointer_destroy(struct wlr_pointer *pointer); +void wlr_pointer_finish(struct wlr_pointer *pointer); #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 4a9ef806e..6bf42de97 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { wlr_log(WLR_ERROR, "wlr_keyboard will not be destroyed"); break; case WLR_INPUT_DEVICE_POINTER: - wlr_pointer_destroy(dev->pointer); + wlr_log(WLR_ERROR, "wlr_pointer will not be destroyed"); break; case WLR_INPUT_DEVICE_SWITCH: wlr_switch_destroy(dev->switch_device); diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index caabec1b3..9f07e2903 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -25,14 +25,6 @@ void wlr_pointer_init(struct wlr_pointer *pointer, wl_signal_init(&pointer->events.hold_end); } -void wlr_pointer_destroy(struct wlr_pointer *pointer) { - if (!pointer) { - return; - } +void wlr_pointer_finish(struct wlr_pointer *pointer) { wlr_input_device_finish(&pointer->base); - if (pointer->impl && pointer->impl->destroy) { - pointer->impl->destroy(pointer); - } else { - free(pointer); - } } diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index 8c232c818..21eeee60e 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -8,12 +8,8 @@ #include "util/signal.h" #include "wlr-virtual-pointer-unstable-v1-protocol.h" -static void pointer_destroy(struct wlr_pointer *pointer) { - /* no-op, pointer belongs to the wlr_virtual_pointer_v1 */ -} - static const struct wlr_pointer_impl pointer_impl = { - .destroy = pointer_destroy, + .name = "virtual-pointer", }; static const struct zwlr_virtual_pointer_v1_interface virtual_pointer_impl; @@ -203,9 +199,10 @@ static void virtual_pointer_destroy_resource(struct wl_resource *resource) { return; } - /* TODO: rework wlr_pointer device destruction */ wlr_signal_emit_safe(&pointer->events.destroy, pointer); - wlr_pointer_destroy(&pointer->pointer); + + wlr_pointer_finish(&pointer->pointer); + wl_resource_set_user_data(pointer->resource, NULL); wl_list_remove(&pointer->link); free(pointer); @@ -251,7 +248,7 @@ static void virtual_pointer_manager_create_virtual_pointer_with_output( } wlr_pointer_init(&virtual_pointer->pointer, &pointer_impl, - "virtual-pointer"); + "wlr_virtual_pointer_v1"); struct wl_resource *pointer_resource = wl_resource_create(client, &zwlr_virtual_pointer_v1_interface, wl_resource_get_version(resource), From 0d2be496a899a0c6736dc504ba482e647bd3aa03 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 14:17:31 -0500 Subject: [PATCH 018/298] interface/wlr_switch: rework destroy sequence The destroy callback in wlr_switch_impl has been removed. The function `wlr_switch_finish` has been introduced to clean up the resources owned by a wlr_switch. `wlr_input_device_destroy` no longer destroys the wlr_switch, attempting to destroy a wlr_switch will result in a no-op. The field `name` has been added to the wlr_switch_impl to be able to identify a given wlr_switch device. --- backend/libinput/events.c | 2 +- backend/libinput/switch.c | 6 +----- backend/wayland/seat.c | 4 ++++ include/wlr/interfaces/wlr_switch.h | 4 ++-- types/wlr_input_device.c | 3 +-- types/wlr_switch.c | 10 +--------- 6 files changed, 10 insertions(+), 19 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 22fdab556..dcf46bee8 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -21,7 +21,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { wlr_pointer_finish(&dev->pointer); } if (dev->switch_device.impl) { - wlr_switch_destroy(&dev->switch_device); + wlr_switch_finish(&dev->switch_device); } if (dev->touch.impl) { wlr_touch_destroy(&dev->touch); diff --git a/backend/libinput/switch.c b/backend/libinput/switch.c index f2d5409b8..586ec0c80 100644 --- a/backend/libinput/switch.c +++ b/backend/libinput/switch.c @@ -4,12 +4,8 @@ #include "backend/libinput.h" #include "util/signal.h" -static void switch_destroy(struct wlr_switch *wlr_switch) { - /* wlr_switch belongs to the wlr_libinput_input_device */ -} - const struct wlr_switch_impl libinput_switch_impl = { - .destroy = switch_destroy, + .name = "libinput-switch", }; void init_device_switch(struct wlr_libinput_input_device *dev) { diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 1edd0f2c0..02d4d874c 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -555,6 +556,9 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { /* Owned by wlr_wl_pointer */ pointer_destroy(wlr_dev->pointer); break; + case WLR_INPUT_DEVICE_SWITCH: + wlr_switch_finish(wlr_dev->switch_device); + break; default: wlr_input_device_destroy(wlr_dev); break; diff --git a/include/wlr/interfaces/wlr_switch.h b/include/wlr/interfaces/wlr_switch.h index fbf5e6cb9..793ed25c2 100644 --- a/include/wlr/interfaces/wlr_switch.h +++ b/include/wlr/interfaces/wlr_switch.h @@ -12,11 +12,11 @@ #include struct wlr_switch_impl { - void (*destroy)(struct wlr_switch *switch_device); + const char *name; }; void wlr_switch_init(struct wlr_switch *switch_device, const struct wlr_switch_impl *impl, const char *name); -void wlr_switch_destroy(struct wlr_switch *switch_device); +void wlr_switch_finish(struct wlr_switch *switch_device); #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 6bf42de97..7a323df34 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -45,7 +44,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { wlr_log(WLR_ERROR, "wlr_pointer will not be destroyed"); break; case WLR_INPUT_DEVICE_SWITCH: - wlr_switch_destroy(dev->switch_device); + wlr_log(WLR_ERROR, "wlr_switch will not be destroyed"); break; case WLR_INPUT_DEVICE_TOUCH: wlr_touch_destroy(dev->touch); diff --git a/types/wlr_switch.c b/types/wlr_switch.c index 42611da96..b6972eea3 100644 --- a/types/wlr_switch.c +++ b/types/wlr_switch.c @@ -13,14 +13,6 @@ void wlr_switch_init(struct wlr_switch *switch_device, wl_signal_init(&switch_device->events.toggle); } -void wlr_switch_destroy(struct wlr_switch *switch_device) { - if (!switch_device) { - return; - } +void wlr_switch_finish(struct wlr_switch *switch_device) { wlr_input_device_finish(&switch_device->base); - if (switch_device->impl && switch_device->impl->destroy) { - switch_device->impl->destroy(switch_device); - } else { - free(switch_device); - } } From a5b032cb1e9a3510d7722640a8970532be4d7b57 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 15:11:25 -0500 Subject: [PATCH 019/298] interface/wlr_tablet_pad: rework destroy sequence The destroy callback in wlr_tablet_pad_impl has been removed. The function `wlr_tablet_pad_finish` has been introduced to clean up the resources owned by a wlr_tablet_pad. `wlr_input_device_destroy` no longer destroys the wlr_tablet_pad, attempting to destroy a wlr_tablet_pad will result in a no-op. The field `name` has been added to the wlr_tablet_pad_impl to be able to identify a given wlr_tablet_pad device. --- backend/libinput/events.c | 2 +- backend/libinput/tablet_pad.c | 42 ++++++++++++------------- backend/wayland/seat.c | 4 +++ backend/wayland/tablet_v2.c | 24 ++++++-------- include/backend/libinput.h | 1 + include/wlr/interfaces/wlr_tablet_pad.h | 10 ++++-- types/wlr_input_device.c | 3 +- types/wlr_tablet_pad.c | 15 ++++----- 8 files changed, 51 insertions(+), 50 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index dcf46bee8..35c58b53f 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -30,7 +30,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { wlr_tablet_destroy(&dev->tablet); } if (dev->tablet_pad.impl) { - wlr_tablet_pad_destroy(&dev->tablet_pad); + finish_device_tablet_pad(dev); } libinput_device_unref(dev->handle); diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index ba9885574..87abd454a 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -8,6 +8,10 @@ #include "backend/libinput.h" #include "util/signal.h" +const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = { + .name = "libinput-tablet-pad", +}; + static void group_destroy(struct wlr_tablet_pad_group *group) { free(group->buttons); free(group->strips); @@ -15,7 +19,6 @@ static void group_destroy(struct wlr_tablet_pad_group *group) { free(group); } -// FIXME: Decide on how to alloc/count here static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad, struct libinput_device *device, unsigned int index) { struct libinput_tablet_pad_mode_group *li_group = @@ -88,27 +91,6 @@ group_fail: group_destroy(group); } -static void tablet_pad_destroy(struct wlr_tablet_pad *wlr_tablet_pad) { - struct wlr_libinput_input_device *dev = - device_from_tablet_pad(wlr_tablet_pad); - - struct wlr_tablet_pad_group *group, *tmp; - wl_list_for_each_safe(group, tmp, &wlr_tablet_pad->groups, link) { - group_destroy(group); - } - - int groups = libinput_device_tablet_pad_get_num_mode_groups(dev->handle); - for (int i = 0; i < groups; ++i) { - struct libinput_tablet_pad_mode_group *li_group = - libinput_device_tablet_pad_get_mode_group(dev->handle, i); - libinput_tablet_pad_mode_group_unref(li_group); - } -} - -const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = { - .destroy = tablet_pad_destroy, -}; - void init_device_tablet_pad(struct wlr_libinput_input_device *dev) { struct libinput_device *handle = dev->handle; const char *name = libinput_device_get_name(handle); @@ -134,6 +116,22 @@ void init_device_tablet_pad(struct wlr_libinput_input_device *dev) { } } +void finish_device_tablet_pad(struct wlr_libinput_input_device *dev) { + struct wlr_tablet_pad_group *group, *tmp; + wl_list_for_each_safe(group, tmp, &dev->tablet_pad.groups, link) { + group_destroy(group); + } + + wlr_tablet_pad_finish(&dev->tablet_pad); + + int groups = libinput_device_tablet_pad_get_num_mode_groups(dev->handle); + for (int i = 0; i < groups; ++i) { + struct libinput_tablet_pad_mode_group *li_group = + libinput_device_tablet_pad_get_mode_group(dev->handle, i); + libinput_tablet_pad_mode_group_unref(li_group); + } +} + struct wlr_libinput_input_device *device_from_tablet_pad( struct wlr_tablet_pad *wlr_tablet_pad) { assert(wlr_tablet_pad->impl == &libinput_tablet_pad_impl); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 02d4d874c..7bf7d863b 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -559,6 +559,10 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { case WLR_INPUT_DEVICE_SWITCH: wlr_switch_finish(wlr_dev->switch_device); break; + case WLR_INPUT_DEVICE_TABLET_PAD: + wlr_tablet_pad_finish(wlr_dev->tablet_pad); + free(wlr_dev->tablet_pad); + break; default: wlr_input_device_destroy(wlr_dev); break; diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index 95cdd119d..0a8f3c8df 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -289,10 +289,11 @@ static void handle_tablet_pad_group_removed( zwp_tablet_pad_group_v2_destroy(group->pad_group); - /* While I'm pretty sure we have control over this as well, it's - * outside the scope of a single function, so better be safe than - * sorry */ + free(group->group.buttons); + free(group->group.strips); + free(group->group.rings); wl_list_remove(&group->group.link); + free(group); } @@ -396,22 +397,15 @@ static void handle_tablet_pad_leave(void *data, static void handle_tablet_pad_removed(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { struct wlr_wl_input_device *dev = data; + struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - - /* This doesn't free anything, but emits the destroy signal */ - wlr_input_device_destroy(&dev->wlr_input_device); - /* This is a bit ugly, but we need to remove it from our list */ - wl_list_remove(&dev->link); - struct wlr_wl_tablet_pad_group *group, *it; wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { handle_tablet_pad_group_removed(group); } - /* This frees */ - wlr_tablet_pad_destroy(tablet_pad); zwp_tablet_pad_v2_destroy(dev->resource); - free(dev); + destroy_wl_input_device(dev); } static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { @@ -425,7 +419,9 @@ static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { .removed = handle_tablet_pad_removed, }; -const struct wlr_tablet_pad_impl tablet_pad_impl = {0}; +const struct wlr_tablet_pad_impl tablet_pad_impl = { + .name = "wl-tablet-pad", +}; static void handle_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, @@ -454,7 +450,7 @@ static void handle_pad_added(void *data, zwp_tablet_pad_v2_destroy(id); return; } - wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, wlr_dev->name); + wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, "wlr_tablet_v2"); zwp_tablet_pad_v2_add_listener(id, &tablet_pad_listener, dev); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index f22e7761c..faf48591a 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -120,6 +120,7 @@ void handle_tablet_tool_button(struct libinput_event *event, struct wlr_tablet *tablet); void init_device_tablet_pad(struct wlr_libinput_input_device *dev); +void finish_device_tablet_pad(struct wlr_libinput_input_device *dev); struct wlr_libinput_input_device *device_from_tablet_pad( struct wlr_tablet_pad *tablet_pad); void handle_tablet_pad_button(struct libinput_event *event, diff --git a/include/wlr/interfaces/wlr_tablet_pad.h b/include/wlr/interfaces/wlr_tablet_pad.h index ff5c93594..e052dd837 100644 --- a/include/wlr/interfaces/wlr_tablet_pad.h +++ b/include/wlr/interfaces/wlr_tablet_pad.h @@ -12,11 +12,17 @@ #include struct wlr_tablet_pad_impl { - void (*destroy)(struct wlr_tablet_pad *pad); + const char *name; }; void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name); -void wlr_tablet_pad_destroy(struct wlr_tablet_pad *pad); + +/** + * Cleans up the resources owned by a wlr_tablet_pad. + * This function will not clean the memory allocated by wlr_tablet_pad_group, + * it's the responsibility of the caller to clean it. + */ +void wlr_tablet_pad_finish(struct wlr_tablet_pad *pad); #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 7a323df34..1da7d1320 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -53,7 +52,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { wlr_tablet_destroy(dev->tablet); break; case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_tablet_pad_destroy(dev->tablet_pad); + wlr_log(WLR_ERROR, "wlr_tablet_pad will not be destroyed"); break; } } else { diff --git a/types/wlr_tablet_pad.c b/types/wlr_tablet_pad.c index 663ccd39e..73dd625cb 100644 --- a/types/wlr_tablet_pad.c +++ b/types/wlr_tablet_pad.c @@ -3,6 +3,7 @@ #include #include #include +#include void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name) { @@ -19,10 +20,8 @@ void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, wl_array_init(&pad->paths); } -void wlr_tablet_pad_destroy(struct wlr_tablet_pad *pad) { - if (!pad) { - return; - } +void wlr_tablet_pad_finish(struct wlr_tablet_pad *pad) { + wlr_input_device_finish(&pad->base); char **path_ptr; wl_array_for_each(path_ptr, &pad->paths) { @@ -30,10 +29,8 @@ void wlr_tablet_pad_destroy(struct wlr_tablet_pad *pad) { } wl_array_release(&pad->paths); - wlr_input_device_finish(&pad->base); - if (pad->impl && pad->impl->destroy) { - pad->impl->destroy(pad); - } else { - free(pad); + /* TODO: wlr_tablet_pad should own its wlr_tablet_pad_group */ + if (!wl_list_empty(&pad->groups)) { + wlr_log(WLR_ERROR, "wlr_tablet_pad groups is not empty"); } } From 8d3cb94b41b3c21350e16e38a00f4e33941c33d5 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 15:58:44 -0500 Subject: [PATCH 020/298] interface/wlr_tablet_tool: rework destroy sequence The destroy callback in wlr_tablet_tool_impl has been removed. The function `wlr_tablet_tool_finish` has been introduced to clean up the resources owned by a wlr_tablet_tool. `wlr_input_device_destroy` no longer destroys the wlr_tablet_tool, attempting to destroy a wlr_tablet_tool will result in a no-op. The field `name` has been added to the wlr_tablet_tool_impl to be able to identify a given wlr_tablet_tool device. --- backend/libinput/events.c | 2 +- backend/libinput/tablet_tool.c | 35 ++++++++++++------------ backend/wayland/seat.c | 4 +++ backend/wayland/tablet_v2.c | 13 ++++----- include/backend/libinput.h | 1 + include/wlr/interfaces/wlr_tablet_tool.h | 4 +-- types/wlr_input_device.c | 3 +- types/wlr_tablet_tool.c | 13 ++------- 8 files changed, 34 insertions(+), 41 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index 35c58b53f..f032b4a52 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -27,7 +27,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { wlr_touch_destroy(&dev->touch); } if (dev->tablet.impl) { - wlr_tablet_destroy(&dev->tablet); + finish_device_tablet(dev); } if (dev->tablet_pad.impl) { finish_device_tablet_pad(dev); diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index af2122181..c778ccc21 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -14,24 +14,8 @@ struct tablet_tool { struct wl_list link; // wlr_libinput_input_device::tablet_tools }; -static void tool_destroy(struct tablet_tool *tool) { - wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); - libinput_tablet_tool_unref(tool->handle); - libinput_tablet_tool_set_user_data(tool->handle, NULL); - wl_list_remove(&tool->link); - free(tool); -} - -static void tablet_destroy(struct wlr_tablet *wlr_tablet) { - struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet); - struct tablet_tool *tool, *tmp; - wl_list_for_each_safe(tool, tmp, &dev->tablet_tools, link) { - tool_destroy(tool); - } -} - const struct wlr_tablet_impl libinput_tablet_impl = { - .destroy = tablet_destroy, + .name = "libinput-tablet-tool", }; void init_device_tablet(struct wlr_libinput_input_device *dev) { @@ -48,6 +32,23 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) { wl_list_init(&dev->tablet_tools); } +static void tool_destroy(struct tablet_tool *tool) { + wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); + libinput_tablet_tool_unref(tool->handle); + libinput_tablet_tool_set_user_data(tool->handle, NULL); + wl_list_remove(&tool->link); + free(tool); +} + +void finish_device_tablet(struct wlr_libinput_input_device *dev) { + struct tablet_tool *tool, *tmp; + wl_list_for_each_safe(tool, tmp, &dev->tablet_tools, link) { + tool_destroy(tool); + } + + wlr_tablet_finish(&dev->tablet); +} + struct wlr_libinput_input_device *device_from_tablet( struct wlr_tablet *wlr_tablet) { assert(wlr_tablet->impl == &libinput_tablet_impl); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 7bf7d863b..cf1bba91e 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -563,6 +563,10 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_tablet_pad_finish(wlr_dev->tablet_pad); free(wlr_dev->tablet_pad); break; + case WLR_INPUT_DEVICE_TABLET_TOOL: + wlr_tablet_finish(wlr_dev->tablet); + free(wlr_dev->tablet); + break; default: wlr_input_device_destroy(wlr_dev); break; diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index 0a8f3c8df..dfebd463e 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -867,13 +867,8 @@ static void handle_tablet_removed(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { struct wlr_wl_input_device *dev = data; - /* This doesn't free anything, but emits the destroy signal */ - wlr_input_device_destroy(&dev->wlr_input_device); - /* This is a bit ugly, but we need to remove it from our list */ - wl_list_remove(&dev->link); - zwp_tablet_v2_destroy(dev->resource); - free(dev); + destroy_wl_input_device(dev); } static const struct zwp_tablet_v2_listener tablet_listener = { @@ -884,7 +879,9 @@ static const struct zwp_tablet_v2_listener tablet_listener = { .removed = handle_tablet_removed, }; -const struct wlr_tablet_impl tablet_impl = {0}; +const struct wlr_tablet_impl tablet_impl = { + .name = "wl-tablet-tool", +}; static void handle_tab_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, @@ -908,7 +905,7 @@ static void handle_tab_added(void *data, return; } zwp_tablet_v2_set_user_data(id, wlr_dev->tablet); - wlr_tablet_init(wlr_dev->tablet, &tablet_impl, wlr_dev->name); + wlr_tablet_init(wlr_dev->tablet, &tablet_impl, "wlr_tablet_v2"); zwp_tablet_v2_add_listener(id, &tablet_listener, dev); } diff --git a/include/backend/libinput.h b/include/backend/libinput.h index faf48591a..7c1dc30aa 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -108,6 +108,7 @@ void handle_touch_frame(struct libinput_event *event, struct wlr_touch *touch); void init_device_tablet(struct wlr_libinput_input_device *dev); +void finish_device_tablet(struct wlr_libinput_input_device *dev); struct wlr_libinput_input_device *device_from_tablet( struct wlr_tablet *tablet); void handle_tablet_tool_axis(struct libinput_event *event, diff --git a/include/wlr/interfaces/wlr_tablet_tool.h b/include/wlr/interfaces/wlr_tablet_tool.h index de7430a2f..68bf8cf74 100644 --- a/include/wlr/interfaces/wlr_tablet_tool.h +++ b/include/wlr/interfaces/wlr_tablet_tool.h @@ -12,11 +12,11 @@ #include struct wlr_tablet_impl { - void (*destroy)(struct wlr_tablet *tablet); + const char *name; }; void wlr_tablet_init(struct wlr_tablet *tablet, const struct wlr_tablet_impl *impl, const char *name); -void wlr_tablet_destroy(struct wlr_tablet *tablet); +void wlr_tablet_finish(struct wlr_tablet *tablet); #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 1da7d1320..067c0b0d4 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -49,7 +48,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { wlr_touch_destroy(dev->touch); break; case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_tablet_destroy(dev->tablet); + wlr_log(WLR_ERROR, "wlr_tablet_tool will not be destroyed"); break; case WLR_INPUT_DEVICE_TABLET_PAD: wlr_log(WLR_ERROR, "wlr_tablet_pad will not be destroyed"); diff --git a/types/wlr_tablet_tool.c b/types/wlr_tablet_tool.c index e50d29d1a..8718abe91 100644 --- a/types/wlr_tablet_tool.c +++ b/types/wlr_tablet_tool.c @@ -17,21 +17,12 @@ void wlr_tablet_init(struct wlr_tablet *tablet, wl_array_init(&tablet->paths); } -void wlr_tablet_destroy(struct wlr_tablet *tablet) { - if (!tablet) { - return; - } +void wlr_tablet_finish(struct wlr_tablet *tablet) { + wlr_input_device_finish(&tablet->base); char **path_ptr; wl_array_for_each(path_ptr, &tablet->paths) { free(*path_ptr); } wl_array_release(&tablet->paths); - - wlr_input_device_finish(&tablet->base); - if (tablet->impl && tablet->impl->destroy) { - tablet->impl->destroy(tablet); - } else { - free(tablet); - } } From 10cbb9fbe141ee8f5c766783bde645ae19998d22 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 16:07:40 -0500 Subject: [PATCH 021/298] interface/wlr_touch: rework destroy sequence The destroy callback in wlr_touch_impl has been removed. The function `wlr_touch_finish` has been introduced to clean up the resources owned by a wlr_touch. `wlr_input_device_destroy` no longer destroys the wlr_touch, attempting to destroy a wlr_touch will result in a no-op. The field `name` has been added to the wlr_touch_impl to be able to identify a given wlr_touch device. --- backend/libinput/events.c | 2 +- backend/libinput/touch.c | 6 +----- backend/wayland/seat.c | 4 ++++ backend/x11/input_device.c | 6 +----- backend/x11/output.c | 2 +- include/wlr/interfaces/wlr_touch.h | 4 ++-- types/wlr_input_device.c | 3 +-- types/wlr_touch.c | 7 +------ 8 files changed, 12 insertions(+), 22 deletions(-) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index f032b4a52..e52dbd956 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -24,7 +24,7 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { wlr_switch_finish(&dev->switch_device); } if (dev->touch.impl) { - wlr_touch_destroy(&dev->touch); + wlr_touch_finish(&dev->touch); } if (dev->tablet.impl) { finish_device_tablet(dev); diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 5b4dcbd6e..481a57874 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -4,12 +4,8 @@ #include "backend/libinput.h" #include "util/signal.h" -static void touch_destroy(struct wlr_touch *touch) { - /* wlr_touch belongs to the wlr_libinput_input_device */ -} - const struct wlr_touch_impl libinput_touch_impl = { - .destroy = touch_destroy, + .name = "libinput-touch", }; void init_device_touch(struct wlr_libinput_input_device *dev) { diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index cf1bba91e..de756d80b 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -567,6 +567,10 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_tablet_finish(wlr_dev->tablet); free(wlr_dev->tablet); break; + case WLR_INPUT_DEVICE_TOUCH: + wlr_touch_finish(wlr_dev->touch); + free(wlr_dev->touch); + break; default: wlr_input_device_destroy(wlr_dev); break; diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 9182ba8e0..77edf8ad3 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -293,12 +293,8 @@ const struct wlr_pointer_impl x11_pointer_impl = { .name = "x11-pointer", }; -static void touch_destroy(struct wlr_touch *wlr_touch) { - // Don't free the touch, it's on the stack -} - const struct wlr_touch_impl x11_touch_impl = { - .destroy = touch_destroy, + .name = "x11-touch", }; void update_x11_pointer_position(struct wlr_x11_output *output, diff --git a/backend/x11/output.c b/backend/x11/output.c index 24c08fceb..1b51b629a 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -77,7 +77,7 @@ static void output_destroy(struct wlr_output *wlr_output) { pixman_region32_fini(&output->exposed); wlr_pointer_finish(&output->pointer); - wlr_touch_destroy(&output->touch); + wlr_touch_finish(&output->touch); struct wlr_x11_buffer *buffer, *buffer_tmp; wl_list_for_each_safe(buffer, buffer_tmp, &output->buffers, link) { diff --git a/include/wlr/interfaces/wlr_touch.h b/include/wlr/interfaces/wlr_touch.h index 2b95d2bf8..e48a92f22 100644 --- a/include/wlr/interfaces/wlr_touch.h +++ b/include/wlr/interfaces/wlr_touch.h @@ -12,11 +12,11 @@ #include struct wlr_touch_impl { - void (*destroy)(struct wlr_touch *touch); + const char *name; }; void wlr_touch_init(struct wlr_touch *touch, const struct wlr_touch_impl *impl, const char *name); -void wlr_touch_destroy(struct wlr_touch *touch); +void wlr_touch_finish(struct wlr_touch *touch); #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 067c0b0d4..69c1536a6 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include "util/signal.h" @@ -45,7 +44,7 @@ void wlr_input_device_destroy(struct wlr_input_device *dev) { wlr_log(WLR_ERROR, "wlr_switch will not be destroyed"); break; case WLR_INPUT_DEVICE_TOUCH: - wlr_touch_destroy(dev->touch); + wlr_log(WLR_ERROR, "wlr_touch will not be destroyed"); break; case WLR_INPUT_DEVICE_TABLET_TOOL: wlr_log(WLR_ERROR, "wlr_tablet_tool will not be destroyed"); diff --git a/types/wlr_touch.c b/types/wlr_touch.c index 366191101..de288347e 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -17,11 +17,6 @@ void wlr_touch_init(struct wlr_touch *touch, wl_signal_init(&touch->events.frame); } -void wlr_touch_destroy(struct wlr_touch *touch) { +void wlr_touch_finish(struct wlr_touch *touch) { wlr_input_device_finish(&touch->base); - if (touch && touch->impl && touch->impl->destroy) { - touch->impl->destroy(touch); - } else { - free(touch); - } } From 9d8dc026e50e9497b9268be40b5a7d2766cffe72 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 7 Mar 2022 11:01:49 -0500 Subject: [PATCH 022/298] tinywl: destroy keyboard on wlr_input_device event --- tinywl/tinywl.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index a4fcc2626..2abcfb11f 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -95,6 +95,7 @@ struct tinywl_keyboard { struct wl_listener modifiers; struct wl_listener key; + struct wl_listener destroy; }; static void focus_view(struct tinywl_view *view, struct wlr_surface *surface) { @@ -216,6 +217,20 @@ static void keyboard_handle_key( } } +static void keyboard_handle_destroy(struct wl_listener *listener, void *data) { + /* This event is raised by the keyboard base wlr_input_device to signal + * the destruction of the wlr_keyboard. It will no longer receive events + * and should be destroyed. + */ + struct tinywl_keyboard *keyboard = + wl_container_of(listener, keyboard, destroy); + wl_list_remove(&keyboard->modifiers.link); + wl_list_remove(&keyboard->key.link); + wl_list_remove(&keyboard->destroy.link); + wl_list_remove(&keyboard->link); + free(keyboard); +} + static void server_new_keyboard(struct tinywl_server *server, struct wlr_input_device *device) { struct tinywl_keyboard *keyboard = @@ -239,6 +254,8 @@ static void server_new_keyboard(struct tinywl_server *server, wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifiers); keyboard->key.notify = keyboard_handle_key; wl_signal_add(&device->keyboard->events.key, &keyboard->key); + keyboard->destroy.notify = keyboard_handle_destroy; + wl_signal_add(&device->events.destroy, &keyboard->destroy); wlr_seat_set_keyboard(server->seat, device); From 1bb2631c5c05e4b74c1a3163ab030ae42c7d8fe8 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 2 Mar 2022 16:48:57 -0500 Subject: [PATCH 023/298] types/wlr_input_device: remove wlr_input_device_destroy --- backend/wayland/seat.c | 3 --- include/wlr/types/wlr_input_device.h | 7 ------ types/wlr_input_device.c | 37 +++------------------------- 3 files changed, 3 insertions(+), 44 deletions(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index de756d80b..e9785d9a7 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -571,9 +571,6 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_touch_finish(wlr_dev->touch); free(wlr_dev->touch); break; - default: - wlr_input_device_destroy(wlr_dev); - break; } } wl_list_remove(&dev->link); diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 1690a5b92..73d90fa50 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -61,11 +61,4 @@ void wlr_input_device_init(struct wlr_input_device *wlr_device, */ void wlr_input_device_finish(struct wlr_input_device *wlr_device); -/** - * Calls the specialized input device destroy function. - * If the wlr_input_device is not owned by a specialized input device, the - * function will finish the wlr_input_device and free it. - */ -void wlr_input_device_destroy(struct wlr_input_device *dev); - #endif diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 69c1536a6..23ee4177a 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -1,9 +1,8 @@ #define _POSIX_C_SOURCE 200809L + #include #include -#include #include -#include #include "util/signal.h" void wlr_input_device_init(struct wlr_input_device *dev, @@ -23,38 +22,8 @@ void wlr_input_device_finish(struct wlr_input_device *wlr_device) { wlr_signal_emit_safe(&wlr_device->events.destroy, wlr_device); + wl_list_remove(&wlr_device->events.destroy.listener_list); + free(wlr_device->name); free(wlr_device->output_name); } - -void wlr_input_device_destroy(struct wlr_input_device *dev) { - if (!dev) { - return; - } - - if (dev->_device) { - switch (dev->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - wlr_log(WLR_ERROR, "wlr_keyboard will not be destroyed"); - break; - case WLR_INPUT_DEVICE_POINTER: - wlr_log(WLR_ERROR, "wlr_pointer will not be destroyed"); - break; - case WLR_INPUT_DEVICE_SWITCH: - wlr_log(WLR_ERROR, "wlr_switch will not be destroyed"); - break; - case WLR_INPUT_DEVICE_TOUCH: - wlr_log(WLR_ERROR, "wlr_touch will not be destroyed"); - break; - case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_log(WLR_ERROR, "wlr_tablet_tool will not be destroyed"); - break; - case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_log(WLR_ERROR, "wlr_tablet_pad will not be destroyed"); - break; - } - } else { - wlr_input_device_finish(dev); - free(dev); - } -} From cfed039c9a353cff5d8c3c678d7eb272c887de77 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 3 Mar 2022 09:43:38 -0500 Subject: [PATCH 024/298] types/wlr_input_device: move init and finish function to private API --- backend/wayland/seat.c | 1 + include/interfaces/wlr_input_device.h | 20 ++++++++++++++++++++ include/wlr/backend/headless.h | 1 - include/wlr/backend/libinput.h | 3 ++- include/wlr/backend/wayland.h | 3 ++- include/wlr/backend/x11.h | 3 ++- include/wlr/types/wlr_cursor.h | 3 ++- include/wlr/types/wlr_input_device.h | 10 ---------- include/wlr/types/wlr_tablet_v2.h | 3 ++- types/seat/wlr_seat.c | 1 - types/seat/wlr_seat_keyboard.c | 1 - types/seat/wlr_seat_pointer.c | 1 - types/seat/wlr_seat_touch.c | 1 - types/wlr_input_device.c | 2 +- types/wlr_keyboard.c | 2 +- types/wlr_pointer.c | 2 ++ types/wlr_switch.c | 2 ++ types/wlr_tablet_pad.c | 2 ++ types/wlr_tablet_tool.c | 2 ++ types/wlr_touch.c | 2 ++ 20 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 include/interfaces/wlr_input_device.h diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index e9785d9a7..c1eddcd78 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -20,6 +20,7 @@ #include "pointer-gestures-unstable-v1-client-protocol.h" #include "relative-pointer-unstable-v1-client-protocol.h" +#include "interfaces/wlr_input_device.h" #include "backend/wayland.h" #include "util/signal.h" #include "util/time.h" diff --git a/include/interfaces/wlr_input_device.h b/include/interfaces/wlr_input_device.h new file mode 100644 index 000000000..c24b53662 --- /dev/null +++ b/include/interfaces/wlr_input_device.h @@ -0,0 +1,20 @@ +#ifndef INTERFACES_INPUT_DEVICE_H +#define INTERFACES_INPUT_DEVICE_H + +#include + +/** + * Initializes a given wlr_input_device. Allocates memory for the name and sets + * its vendor and product id to 0. + * wlr_device must be non-NULL. + */ +void wlr_input_device_init(struct wlr_input_device *wlr_device, + enum wlr_input_device_type type, const char *name); + +/** + * Cleans up all the memory owned by a given wlr_input_device and signals + * the destroy event. + */ +void wlr_input_device_finish(struct wlr_input_device *wlr_device); + +#endif diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h index f47354830..ff55746ff 100644 --- a/include/wlr/backend/headless.h +++ b/include/wlr/backend/headless.h @@ -10,7 +10,6 @@ #define WLR_BACKEND_HEADLESS_H #include -#include #include /** diff --git a/include/wlr/backend/libinput.h b/include/wlr/backend/libinput.h index 50faaf7dc..94197b7ab 100644 --- a/include/wlr/backend/libinput.h +++ b/include/wlr/backend/libinput.h @@ -13,7 +13,8 @@ #include #include #include -#include + +struct wlr_input_device; struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, struct wlr_session *session); diff --git a/include/wlr/backend/wayland.h b/include/wlr/backend/wayland.h index a32a682a1..0aed3aa14 100644 --- a/include/wlr/backend/wayland.h +++ b/include/wlr/backend/wayland.h @@ -4,9 +4,10 @@ #include #include #include -#include #include +struct wlr_input_device; + /** * Creates a new wlr_wl_backend. This backend will be created with no outputs; * you must use wlr_wl_output_create to add them. diff --git a/include/wlr/backend/x11.h b/include/wlr/backend/x11.h index 90918f3f8..c6aaaf80a 100644 --- a/include/wlr/backend/x11.h +++ b/include/wlr/backend/x11.h @@ -6,9 +6,10 @@ #include #include -#include #include +struct wlr_input_device; + /** * Creates a new wlr_x11_backend. This backend will be created with no outputs; * you must use wlr_x11_output_create to add them. diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 7dd73c48e..95a3e37f3 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -10,10 +10,11 @@ #define WLR_TYPES_WLR_CURSOR_H #include -#include #include #include +struct wlr_input_device; + /** * wlr_cursor implements the behavior of the "cursor", that is, the image on the * screen typically moved about with a mouse or so. It provides tracking for diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 73d90fa50..0ca64341b 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -25,8 +25,6 @@ enum wlr_input_device_type { WLR_INPUT_DEVICE_SWITCH, }; -struct wlr_input_device_impl; - struct wlr_input_device { enum wlr_input_device_type type; unsigned int vendor, product; @@ -53,12 +51,4 @@ struct wlr_input_device { void *data; }; -void wlr_input_device_init(struct wlr_input_device *wlr_device, - enum wlr_input_device_type type, const char *name); - -/** - * Clean up all of the provided wlr_input_device resources - */ -void wlr_input_device_finish(struct wlr_input_device *wlr_device); - #endif diff --git a/include/wlr/types/wlr_tablet_v2.h b/include/wlr/types/wlr_tablet_v2.h index 4483a578e..c05015b2d 100644 --- a/include/wlr/types/wlr_tablet_v2.h +++ b/include/wlr/types/wlr_tablet_v2.h @@ -11,13 +11,14 @@ #include #include -#include #include "tablet-unstable-v2-protocol.h" /* This can probably be even lower,the tools don't have a lot of buttons */ #define WLR_TABLET_V2_TOOL_BUTTONS_CAP 16 +struct wlr_input_device; + struct wlr_tablet_pad_v2_grab_interface; struct wlr_tablet_pad_v2_grab { diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index 4933133c6..f2fd04c12 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c index 9ed5fb345..1bad8ff62 100644 --- a/types/seat/wlr_seat_keyboard.c +++ b/types/seat/wlr_seat_keyboard.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "types/wlr_data_device.h" #include "types/wlr_seat.h" diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index ce4ca54e2..ef058999b 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "types/wlr_seat.h" #include "util/signal.h" diff --git a/types/seat/wlr_seat_touch.c b/types/seat/wlr_seat_touch.c index 99c50cf88..65a8c7c06 100644 --- a/types/seat/wlr_seat_touch.c +++ b/types/seat/wlr_seat_touch.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include "types/wlr_seat.h" #include "util/signal.h" diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 23ee4177a..d376582ed 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -2,7 +2,7 @@ #include #include -#include +#include "interfaces/wlr_input_device.h" #include "util/signal.h" void wlr_input_device_init(struct wlr_input_device *dev, diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 372efcb58..1d6090943 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include "interfaces/wlr_input_device.h" #include "types/wlr_keyboard.h" #include "util/array.h" #include "util/shm.h" diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index 9f07e2903..737d36ec6 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -4,6 +4,8 @@ #include #include +#include "interfaces/wlr_input_device.h" + void wlr_pointer_init(struct wlr_pointer *pointer, const struct wlr_pointer_impl *impl, const char *name) { wlr_input_device_init(&pointer->base, WLR_INPUT_DEVICE_POINTER, name); diff --git a/types/wlr_switch.c b/types/wlr_switch.c index b6972eea3..8e84841d5 100644 --- a/types/wlr_switch.c +++ b/types/wlr_switch.c @@ -4,6 +4,8 @@ #include #include +#include "interfaces/wlr_input_device.h" + void wlr_switch_init(struct wlr_switch *switch_device, const struct wlr_switch_impl *impl, const char *name) { wlr_input_device_init(&switch_device->base, WLR_INPUT_DEVICE_SWITCH, name); diff --git a/types/wlr_tablet_pad.c b/types/wlr_tablet_pad.c index 73dd625cb..df389c465 100644 --- a/types/wlr_tablet_pad.c +++ b/types/wlr_tablet_pad.c @@ -5,6 +5,8 @@ #include #include +#include "interfaces/wlr_input_device.h" + void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name) { wlr_input_device_init(&pad->base, WLR_INPUT_DEVICE_TABLET_PAD, name); diff --git a/types/wlr_tablet_tool.c b/types/wlr_tablet_tool.c index 8718abe91..a5c9d44fa 100644 --- a/types/wlr_tablet_tool.c +++ b/types/wlr_tablet_tool.c @@ -4,6 +4,8 @@ #include #include +#include "interfaces/wlr_input_device.h" + void wlr_tablet_init(struct wlr_tablet *tablet, const struct wlr_tablet_impl *impl, const char *name) { wlr_input_device_init(&tablet->base, WLR_INPUT_DEVICE_TABLET_TOOL, name); diff --git a/types/wlr_touch.c b/types/wlr_touch.c index de288347e..612efcda8 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -4,6 +4,8 @@ #include #include +#include "interfaces/wlr_input_device.h" + void wlr_touch_init(struct wlr_touch *touch, const struct wlr_touch_impl *impl, const char *name) { wlr_input_device_init(&touch->base, WLR_INPUT_DEVICE_TOUCH, name); From 4792446ee8f50104bd207d9ccd8558a7e4eb4514 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sat, 26 Feb 2022 18:25:19 +0100 Subject: [PATCH 025/298] wlr_switch: remove WLR_SWITCH_STATE_TOGGLE This was originally added in 810c7b7 for use in rootston's input config handling. It has never actually been part of the wlroots API and shouldn't exist. --- include/wlr/types/wlr_switch.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_switch.h b/include/wlr/types/wlr_switch.h index 31811ec33..8e7230327 100644 --- a/include/wlr/types/wlr_switch.h +++ b/include/wlr/types/wlr_switch.h @@ -34,8 +34,7 @@ enum wlr_switch_type { enum wlr_switch_state { WLR_SWITCH_STATE_OFF = 0, - WLR_SWITCH_STATE_ON, - WLR_SWITCH_STATE_TOGGLE + WLR_SWITCH_STATE_ON }; struct wlr_event_switch_toggle { From fbd4d40318c437508342bbbc41a0f90173462160 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 26 Feb 2022 21:50:41 -0500 Subject: [PATCH 026/298] wlr_output_damage: Use wlr_output_damage_add for wlr_output_damage_add_box --- types/wlr_output_damage.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index 6d24a4bf4..08f11207f 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -206,12 +206,9 @@ void wlr_output_damage_add_whole(struct wlr_output_damage *output_damage) { void wlr_output_damage_add_box(struct wlr_output_damage *output_damage, struct wlr_box *box) { - int width, height; - wlr_output_transformed_resolution(output_damage->output, &width, &height); - - pixman_region32_union_rect(&output_damage->current, &output_damage->current, + pixman_region32_t damage; + pixman_region32_init_rect(&damage, box->x, box->y, box->width, box->height); - pixman_region32_intersect_rect(&output_damage->current, - &output_damage->current, 0, 0, width, height); - wlr_output_schedule_frame(output_damage->output); + wlr_output_damage_add(output_damage, &damage); + pixman_region32_fini(&damage); } From f330759ba43ba55696c8e378fedfa2d1448ae12f Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 26 Feb 2022 21:51:53 -0500 Subject: [PATCH 027/298] wlr_output_damage: Don't schedule a new frame if damage region does not intersect with output This fixed adaptive sync issues with wlr_scene. Scenes don't check if the damage region intersects with an output when calling wlr_output_damage_add. This is especially important for multi output. --- types/wlr_output_damage.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index 08f11207f..f9aabc312 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -187,11 +187,17 @@ void wlr_output_damage_add(struct wlr_output_damage *output_damage, int width, height; wlr_output_transformed_resolution(output_damage->output, &width, &height); - pixman_region32_union(&output_damage->current, &output_damage->current, - damage); - pixman_region32_intersect_rect(&output_damage->current, - &output_damage->current, 0, 0, width, height); - wlr_output_schedule_frame(output_damage->output); + pixman_region32_t clipped_damage; + pixman_region32_init(&clipped_damage); + pixman_region32_intersect_rect(&clipped_damage, damage, 0, 0, width, height); + + if (pixman_region32_not_empty(&clipped_damage)) { + pixman_region32_union(&output_damage->current, &output_damage->current, + &clipped_damage); + wlr_output_schedule_frame(output_damage->output); + } + + pixman_region32_fini(&clipped_damage); } void wlr_output_damage_add_whole(struct wlr_output_damage *output_damage) { From 2dd121235ea4c3f37c83ef19bb87aa11448fb40d Mon Sep 17 00:00:00 2001 From: Moon Sungjoon Date: Sun, 6 Mar 2022 00:33:28 +0900 Subject: [PATCH 028/298] xcursor: support XDG Base Directory Specification This patch adds ~/.local/share/icons to the search path, so user-specific themes can be loaded through the API provided by libwayland-cursor. Use this PR as reference: https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/112 --- xcursor/xcursor.c | 51 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/xcursor/xcursor.c b/xcursor/xcursor.c index 293d6e9d8..b0c424f4c 100644 --- a/xcursor/xcursor.c +++ b/xcursor/xcursor.c @@ -622,18 +622,43 @@ XcursorFileLoadImages (FILE *file, int size) #define XCURSORPATH "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR #endif -static const char * +#define XDG_DATA_HOME_FALLBACK "~/.local/share" +#define CURSORDIR "/icons" + +/** Get search path for cursor themes + * + * This function builds the list of directories to look for cursor + * themes in. The format is PATH-like: directories are separated by + * colons. + * + * The memory block returned by this function is allocated on the heap + * and must be freed by the caller. + */ +static char * XcursorLibraryPath (void) { - static const char *path; + const char *env_var; + char *path = NULL; + int pathlen = 0; - if (!path) - { - path = getenv ("XCURSOR_PATH"); - if (!path) - path = XCURSORPATH; - } - return path; + env_var = getenv("XCURSOR_PATH"); + if (env_var) { + path = strdup(env_var); + } + else { + env_var = getenv("XDG_DATA_HOME"); + if (env_var) { + pathlen = strlen(env_var) + + strlen(CURSORDIR ":" XCURSORPATH) + 1; + path = malloc(pathlen); + snprintf(path, pathlen, "%s%s", env_var, + CURSORDIR ":" XCURSORPATH); + } + else { + path = strdup(XDG_DATA_HOME_FALLBACK ":" XCURSORPATH); + } + } + return path; } static void @@ -866,14 +891,13 @@ xcursor_load_theme(const char *theme, int size, { char *full, *dir; char *inherits = NULL; + char *xcursor_path = NULL; const char *path, *i; if (!theme) theme = "default"; - - for (path = XcursorLibraryPath(); - path; - path = _XcursorNextPath(path)) { + xcursor_path = XcursorLibraryPath(); + for (path = xcursor_path; path; path = _XcursorNextPath(path)) { dir = _XcursorBuildThemeDir(path, theme); if (!dir) continue; @@ -902,4 +926,5 @@ xcursor_load_theme(const char *theme, int size, if (inherits) free(inherits); + free(xcursor_path); } From 13fcdba75cf5f21cfd49c1a05f4fa62f77619b40 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Sat, 5 Mar 2022 08:00:39 +0100 Subject: [PATCH 029/298] wlr_output_layout_contains_point: handle outputs that aren't in the layout Instead of crashing, return `false` when the specified output isn't part of the layout, as we can be sure that it doesn't contain the specified point. --- types/wlr_output_layout.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 28d91e8d4..ef6e2850c 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -231,6 +231,9 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, if (reference) { struct wlr_output_layout_output *l_output = wlr_output_layout_get(layout, reference); + if (!l_output) { + return false; + } struct wlr_box output_box; output_layout_output_get_box(l_output, &output_box); return wlr_box_contains_point(&output_box, lx, ly); From 7a2c96dcbd170d6b9811af944bc905cf1376e987 Mon Sep 17 00:00:00 2001 From: David96 Date: Fri, 11 Mar 2022 11:47:56 +0100 Subject: [PATCH 030/298] types/wlr_tablet_tool: remove name ambiguity It wasn't clear in the backend whether to use name or base.name, change it so base.name has to be used. Fixes https://github.com/swaywm/sway/issues/6884 --- backend/wayland/tablet_v2.c | 4 ++-- include/wlr/types/wlr_tablet_tool.h | 1 - types/tablet_v2/wlr_tablet_v2_tablet.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index dfebd463e..dc7f50fd9 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -836,8 +836,8 @@ static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, struct wlr_wl_input_device *dev = data; struct wlr_tablet *tablet = dev->wlr_input_device.tablet; - free(tablet->name); - tablet->name = strdup(name); + free(tablet->base.name); + tablet->base.name = strdup(name); } static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index b8b4000f7..c7d612a33 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -71,7 +71,6 @@ struct wlr_tablet { struct wl_signal button; } events; - char *name; struct wl_array paths; // char * void *data; diff --git a/types/tablet_v2/wlr_tablet_v2_tablet.c b/types/tablet_v2/wlr_tablet_v2_tablet.c index 1d3c08fd4..b9189a26a 100644 --- a/types/tablet_v2/wlr_tablet_v2_tablet.c +++ b/types/tablet_v2/wlr_tablet_v2_tablet.c @@ -108,9 +108,9 @@ void add_tablet_client(struct wlr_tablet_seat_client_v2 *seat, zwp_tablet_seat_v2_send_tablet_added(seat->resource, client->resource); // Send the expected events - if (tablet->wlr_tablet->name) { + if (tablet->wlr_tablet->base.name) { zwp_tablet_v2_send_name(client->resource, - tablet->wlr_tablet->name); + tablet->wlr_tablet->base.name); } zwp_tablet_v2_send_id(client->resource, tablet->wlr_device->vendor, tablet->wlr_device->product); From eae8952e176fcb63fe611d73f1459ab0f24252c9 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 15:53:21 -0500 Subject: [PATCH 031/298] types/wlr_keyboard: remove destroy event The destroy event from the base wlr_input_device must be used --- include/wlr/types/wlr_keyboard.h | 1 - types/wlr_input_method_v2.c | 2 +- types/wlr_keyboard.c | 3 --- types/wlr_keyboard_group.c | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index b3be053a5..063d6e3f6 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -89,7 +89,6 @@ struct wlr_keyboard { struct wl_signal modifiers; struct wl_signal keymap; struct wl_signal repeat_info; - struct wl_signal destroy; } events; void *data; diff --git a/types/wlr_input_method_v2.c b/types/wlr_input_method_v2.c index 559927eb1..fe1568690 100644 --- a/types/wlr_input_method_v2.c +++ b/types/wlr_input_method_v2.c @@ -410,7 +410,7 @@ void wlr_input_method_keyboard_grab_v2_set_keyboard( &keyboard_grab->keyboard_repeat_info); keyboard_grab->keyboard_destroy.notify = handle_keyboard_destroy; - wl_signal_add(&keyboard->events.destroy, + wl_signal_add(&keyboard->base.events.destroy, &keyboard_grab->keyboard_destroy); wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 1d6090943..52d9a06d7 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -124,7 +124,6 @@ void wlr_keyboard_init(struct wlr_keyboard *kb, wl_signal_init(&kb->events.modifiers); wl_signal_init(&kb->events.keymap); wl_signal_init(&kb->events.repeat_info); - wl_signal_init(&kb->events.destroy); kb->keymap_fd = -1; @@ -147,8 +146,6 @@ void wlr_keyboard_finish(struct wlr_keyboard *kb) { wlr_keyboard_notify_key(kb, &event); // updates num_keycodes } - wlr_signal_emit_safe(&kb->events.destroy, kb); - wlr_input_device_finish(&kb->base); /* Finish xkbcommon resources */ diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c index 465e9944f..7f575810e 100644 --- a/types/wlr_keyboard_group.c +++ b/types/wlr_keyboard_group.c @@ -279,7 +279,7 @@ bool wlr_keyboard_group_add_keyboard(struct wlr_keyboard_group *group, wl_signal_add(&keyboard->events.repeat_info, &device->repeat_info); device->repeat_info.notify = handle_keyboard_repeat_info; - wl_signal_add(&keyboard->events.destroy, &device->destroy); + wl_signal_add(&keyboard->base.events.destroy, &device->destroy); device->destroy.notify = handle_keyboard_destroy; struct wlr_keyboard *group_kb = &group->keyboard; From 45c877173577cf450f0932c6899b740cacb4254f Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 15:54:38 -0500 Subject: [PATCH 032/298] types/wlr_virtual_keyboard_v1: remove destroy event The destroy event from the keyboard base wlr_input_device must be used --- include/wlr/types/wlr_virtual_keyboard_v1.h | 4 ---- types/wlr_virtual_keyboard_v1.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/include/wlr/types/wlr_virtual_keyboard_v1.h b/include/wlr/types/wlr_virtual_keyboard_v1.h index a818f1416..8350f4134 100644 --- a/include/wlr/types/wlr_virtual_keyboard_v1.h +++ b/include/wlr/types/wlr_virtual_keyboard_v1.h @@ -31,10 +31,6 @@ struct wlr_virtual_keyboard_v1 { bool has_keymap; struct wl_list link; - - struct { - struct wl_signal destroy; // struct wlr_virtual_keyboard_v1* - } events; }; struct wlr_virtual_keyboard_manager_v1* wlr_virtual_keyboard_manager_v1_create( diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 5a5ce6308..01f7d6dc2 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -109,8 +109,6 @@ static void virtual_keyboard_destroy_resource(struct wl_resource *resource) { return; } - wlr_signal_emit_safe(&keyboard->events.destroy, keyboard); - wlr_keyboard_finish(&keyboard->keyboard); wl_resource_set_user_data(keyboard->resource, NULL); @@ -171,7 +169,6 @@ static void virtual_keyboard_manager_create_virtual_keyboard( virtual_keyboard->resource = keyboard_resource; virtual_keyboard->seat = seat_client->seat; - wl_signal_init(&virtual_keyboard->events.destroy); wl_list_insert(&manager->virtual_keyboards, &virtual_keyboard->link); From 4c8ecfcd4ab84d67a0677967d1fc98d5062ab6ae Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 15:56:28 -0500 Subject: [PATCH 033/298] types/wlr_virtual_pointer_v1: remove destroy event The destroy event from the pointer base wlr_input_device must be used --- include/wlr/types/wlr_virtual_pointer_v1.h | 4 ---- types/wlr_virtual_pointer_v1.c | 3 --- 2 files changed, 7 deletions(-) diff --git a/include/wlr/types/wlr_virtual_pointer_v1.h b/include/wlr/types/wlr_virtual_pointer_v1.h index 307d61586..656ca371f 100644 --- a/include/wlr/types/wlr_virtual_pointer_v1.h +++ b/include/wlr/types/wlr_virtual_pointer_v1.h @@ -35,10 +35,6 @@ struct wlr_virtual_pointer_v1 { bool axis_valid[2]; struct wl_list link; - - struct { - struct wl_signal destroy; // struct wlr_virtual_pointer_v1* - } events; }; struct wlr_virtual_pointer_v1_new_pointer_event { diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index 21eeee60e..22aa903ec 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -199,8 +199,6 @@ static void virtual_pointer_destroy_resource(struct wl_resource *resource) { return; } - wlr_signal_emit_safe(&pointer->events.destroy, pointer); - wlr_pointer_finish(&pointer->pointer); wl_resource_set_user_data(pointer->resource, NULL); @@ -278,7 +276,6 @@ static void virtual_pointer_manager_create_virtual_pointer_with_output( } virtual_pointer->resource = pointer_resource; - wl_signal_init(&virtual_pointer->events.destroy); wl_list_insert(&manager->virtual_pointers, &virtual_pointer->link); wlr_signal_emit_safe(&manager->events.new_virtual_pointer, &event); From 5c17452ae008d001b2529a6437916ea17403588d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20=C4=8Cavoj?= Date: Sun, 13 Mar 2022 12:28:55 +0100 Subject: [PATCH 034/298] Pass O_CLOEXEC to drmModeCreateLease calls The lease_fd is currently being leaked to child processes Link: https://github.com/swaywm/sway/issues/4286#issuecomment-1065987957 --- backend/drm/drm.c | 2 +- render/allocator/allocator.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 43de54e55..2b573295c 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1629,7 +1629,7 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs, wl_signal_init(&lease->events.destroy); wlr_log(WLR_DEBUG, "Issuing DRM lease with %d objects", n_objects); - int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0, + int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, O_CLOEXEC, &lease->lessee_id); if (lease_fd < 0) { free(lease); diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 0597cf256..2c75421f1 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -30,7 +30,7 @@ static int reopen_drm_node(int drm_fd, bool allow_render_node) { if (drmIsMaster(drm_fd)) { // Only recent kernels support empty leases uint32_t lessee_id; - int lease_fd = drmModeCreateLease(drm_fd, NULL, 0, 0, &lessee_id); + int lease_fd = drmModeCreateLease(drm_fd, NULL, 0, O_CLOEXEC, &lessee_id); if (lease_fd >= 0) { return lease_fd; } else if (lease_fd != -EINVAL && lease_fd != -EOPNOTSUPP) { From 104060fec57bec2a282c52f7e849f40fd1b1b45e Mon Sep 17 00:00:00 2001 From: Dean Date: Mon, 14 Mar 2022 05:55:50 +0000 Subject: [PATCH 035/298] Free drmDevice in get_egl_device_from_drm_fd() --- render/egl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/render/egl.c b/render/egl.c index d5d6cfb7d..81ce3b260 100644 --- a/render/egl.c +++ b/render/egl.c @@ -440,6 +440,7 @@ static EGLDeviceEXT get_egl_device_from_drm_fd(struct wlr_egl *egl, } } + drmFreeDevice(&device); free(devices); return egl_device; From 2d623724c3571b35cd95cf907df0435f29a3c88c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 15 Mar 2022 20:57:23 +0300 Subject: [PATCH 036/298] xdg-positioner: fix sliding regression This commit fixes a regression introduced in 511f137f8fb245e4877d83a0846294091373eba1 where GTK tooltips wouldn't be unconstrained due to no gravity on x axis being set, in which case the behavior is ambiguous, by sliding to the right/bottom. --- types/xdg_shell/wlr_xdg_positioner.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/types/xdg_shell/wlr_xdg_positioner.c b/types/xdg_shell/wlr_xdg_positioner.c index 6fa1ed991..eff81ea33 100644 --- a/types/xdg_shell/wlr_xdg_positioner.c +++ b/types/xdg_shell/wlr_xdg_positioner.c @@ -343,13 +343,10 @@ static bool xdg_positioner_rules_unconstrain_by_slide( struct constraint_offsets *offsets) { uint32_t gravity = xdg_positioner_gravity_to_wlr_edges(rules->gravity); - // We can only slide if there is gravity on this axis bool slide_x = (offsets->left > 0 || offsets->right > 0) && - (rules->constraint_adjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X) && - (gravity & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)); + (rules->constraint_adjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X); bool slide_y = (offsets->top > 0 || offsets->bottom > 0) && - (rules->constraint_adjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y) && - (gravity & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)); + (rules->constraint_adjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y); if (!slide_x && !slide_y) { return false; @@ -363,9 +360,13 @@ static bool xdg_positioner_rules_unconstrain_by_slide( // the box is bigger than the anchor rect and completely includes it. // In this case, the second slide will fail immediately, so simply // slide towards the direction of the gravity. + // Note that the protocol doesn't specify the behavior when there is no + // gravity on the axis (which is what e.g. GTK tooltips use). In this + // case, fall back to sliding the box to the right/bottom, which is what + // GTK X11 popup adjustment code does. if (gravity & WLR_EDGE_LEFT) { box->x -= offsets->right; - } else if (gravity & WLR_EDGE_RIGHT) { + } else { box->x += offsets->left; } } else { @@ -386,7 +387,7 @@ static bool xdg_positioner_rules_unconstrain_by_slide( if (offsets->top > 0 && offsets->bottom > 0) { if (gravity & WLR_EDGE_TOP) { box->y -= offsets->bottom; - } else if (gravity & WLR_EDGE_BOTTOM) { + } else { box->y += offsets->top; } } else { From 68f2f8cf927d0ea9082438c130ffbc7c5d69fd85 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 13 Mar 2022 11:21:56 +0100 Subject: [PATCH 037/298] Revert "scene: try to import buffers as textures before rendering" This reverts commit 3db1bcbe641b407b9f5c9e5d0a012b45aa2c6cb7. Since [1], importing buffers as textures before wlr_renderer_begin isn't necessary anymore. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3464 --- include/wlr/types/wlr_scene.h | 4 ---- types/scene/wlr_scene.c | 14 -------------- 2 files changed, 18 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 867753996..7c2238fb9 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -69,9 +69,6 @@ struct wlr_scene { // May be NULL struct wlr_presentation *presentation; struct wl_listener presentation_destroy; - - // List of buffers which need to be imported as textures - struct wl_list pending_buffers; // wlr_scene_buffer.pending_link }; /** A sub-tree in the scene-graph. */ @@ -118,7 +115,6 @@ struct wlr_scene_buffer { struct wlr_fbox src_box; int dst_width, dst_height; enum wl_output_transform transform; - struct wl_list pending_link; // wlr_scene.pending_buffers }; /** A viewport for an output in the scene-graph */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 5d5ff9657..9353fef5c 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -130,7 +130,6 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); - wl_list_remove(&scene_buffer->pending_link); wlr_texture_destroy(scene_buffer->texture); wlr_buffer_unlock(scene_buffer->buffer); free(scene_buffer); @@ -146,7 +145,6 @@ struct wlr_scene *wlr_scene_create(void) { scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); - wl_list_init(&scene->pending_buffers); return scene; } @@ -362,9 +360,6 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, scene_node_damage_whole(&scene_buffer->node); - struct wlr_scene *scene = scene_node_get_root(parent); - wl_list_insert(&scene->pending_buffers, &scene_buffer->pending_link); - return scene_buffer; } @@ -1118,15 +1113,6 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { return true; } - // Try to import new buffers as textures - struct wlr_scene_buffer *scene_buffer, *scene_buffer_tmp; - wl_list_for_each_safe(scene_buffer, scene_buffer_tmp, - &scene_output->scene->pending_buffers, pending_link) { - scene_buffer_get_texture(scene_buffer, renderer); - wl_list_remove(&scene_buffer->pending_link); - wl_list_init(&scene_buffer->pending_link); - } - wlr_renderer_begin(renderer, output->width, output->height); int nrects; From 74381f3bc33d029aab3eb2fd764709211854ef1c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 5 Jan 2022 20:03:52 -0500 Subject: [PATCH 038/298] types/wlr_output: Handle subpixel hints through output commits --- include/wlr/interfaces/wlr_output.h | 3 ++- include/wlr/types/wlr_output.h | 2 ++ types/output/output.c | 21 +++++++++++++-------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 79cc8ee0a..c02a588f5 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -22,7 +22,8 @@ WLR_OUTPUT_STATE_SCALE | \ WLR_OUTPUT_STATE_TRANSFORM | \ WLR_OUTPUT_STATE_RENDER_FORMAT | \ - WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) + WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED | \ + WLR_OUTPUT_STATE_SUBPIXEL) /** * A backend implementation of wlr_output. diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 791023d2e..f3a02deef 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -62,6 +62,7 @@ enum wlr_output_state_field { WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED = 1 << 6, WLR_OUTPUT_STATE_GAMMA_LUT = 1 << 7, WLR_OUTPUT_STATE_RENDER_FORMAT = 1 << 8, + WLR_OUTPUT_STATE_SUBPIXEL = 1 << 9, }; enum wlr_output_state_mode_type { @@ -80,6 +81,7 @@ struct wlr_output_state { enum wl_output_transform transform; bool adaptive_sync_enabled; uint32_t render_format; + enum wl_output_subpixel subpixel; // only valid if WLR_OUTPUT_STATE_BUFFER struct wlr_buffer *buffer; diff --git a/types/output/output.c b/types/output/output.c index 1c0241fe5..e4d45043a 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -328,16 +328,12 @@ void wlr_output_set_render_format(struct wlr_output *output, uint32_t format) { void wlr_output_set_subpixel(struct wlr_output *output, enum wl_output_subpixel subpixel) { if (output->subpixel == subpixel) { + output->pending.committed &= ~WLR_OUTPUT_STATE_SUBPIXEL; return; } - output->subpixel = subpixel; - - struct wl_resource *resource; - wl_resource_for_each(resource, &output->resources) { - send_geometry(resource); - } - wlr_output_schedule_done(output); + output->pending.committed |= WLR_OUTPUT_STATE_SUBPIXEL; + output->pending.subpixel = subpixel; } void wlr_output_set_name(struct wlr_output *output, const char *name) { @@ -634,6 +630,10 @@ static bool output_basic_test(struct wlr_output *output) { wlr_log(WLR_DEBUG, "Tried to set the gamma lut on a disabled output"); return false; } + if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) { + wlr_log(WLR_DEBUG, "Tried to set the subpixel layout on a disabled output"); + return false; + } return true; } @@ -716,6 +716,10 @@ bool wlr_output_commit(struct wlr_output *output) { output->render_format = output->pending.render_format; } + if (output->pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) { + output->subpixel = output->pending.subpixel; + } + output->commit_seq++; bool scale_updated = output->pending.committed & WLR_OUTPUT_STATE_SCALE; @@ -729,7 +733,8 @@ bool wlr_output_commit(struct wlr_output *output) { } bool geometry_updated = output->pending.committed & - (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM); + (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | + WLR_OUTPUT_STATE_SUBPIXEL); if (geometry_updated || scale_updated) { struct wl_resource *resource; wl_resource_for_each(resource, &output->resources) { From 64fe6ab300ae36a8219281dc40471bbdf466358b Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Fri, 4 Mar 2022 21:59:23 -0500 Subject: [PATCH 039/298] tinywl: init cursor_mode valgrind complains on a use-before-init for the cursor mode. --- tinywl/tinywl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 2abcfb11f..e21d47347 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -842,6 +842,7 @@ int main(int argc, char *argv[]) { * * And more comments are sprinkled throughout the notify functions above. */ + server.cursor_mode = TINYWL_CURSOR_PASSTHROUGH; server.cursor_motion.notify = server_cursor_motion; wl_signal_add(&server.cursor->events.motion, &server.cursor_motion); server.cursor_motion_absolute.notify = server_cursor_motion_absolute; From f9b6aa307974a51a0b80d4bfec99caa066e6e2db Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 3 Mar 2022 13:23:08 -0500 Subject: [PATCH 040/298] backend/wayland: give wlr_keyboard ownership to wlr_wl_seat --- backend/wayland/backend.c | 4 +- backend/wayland/seat.c | 115 ++++++++++++++++---------------------- include/backend/wayland.h | 18 ++++-- 3 files changed, 62 insertions(+), 75 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index c0e99a228..44468a268 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -413,8 +413,8 @@ static bool backend_start(struct wlr_backend *backend) { struct wlr_wl_seat *seat; wl_list_for_each(seat, &wl->seats, link) { - if (seat->keyboard) { - create_wl_keyboard(seat); + if (seat->wl_keyboard) { + init_seat_keyboard(seat); } if (wl->tablet_manager) { diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index c1eddcd78..0ca297f36 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -26,9 +26,6 @@ #include "util/time.h" static const struct wlr_pointer_impl pointer_impl; -static const struct wlr_keyboard_impl keyboard_impl = { - .name = "wl-keyboard", -}; static const struct wlr_touch_impl touch_impl; static struct wlr_wl_pointer *output_get_pointer( @@ -223,31 +220,27 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { - struct wlr_input_device *dev = data; - - uint32_t time = get_current_time_msec(); + struct wlr_keyboard *keyboard = data; uint32_t *keycode_ptr; wl_array_for_each(keycode_ptr, keys) { struct wlr_event_keyboard_key event = { .keycode = *keycode_ptr, .state = WL_KEYBOARD_KEY_STATE_PRESSED, - .time_msec = time, + .time_msec = get_current_time_msec(), .update_state = false, }; - wlr_keyboard_notify_key(dev->keyboard, &event); + wlr_keyboard_notify_key(keyboard, &event); } } static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface) { - struct wlr_input_device *dev = data; + struct wlr_keyboard *keyboard = data; - uint32_t time = get_current_time_msec(); - - size_t num_keycodes = dev->keyboard->num_keycodes; + size_t num_keycodes = keyboard->num_keycodes; uint32_t pressed[num_keycodes + 1]; - memcpy(pressed, dev->keyboard->keycodes, + memcpy(pressed, keyboard->keycodes, num_keycodes * sizeof(uint32_t)); for (size_t i = 0; i < num_keycodes; ++i) { @@ -256,17 +249,16 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, struct wlr_event_keyboard_key event = { .keycode = keycode, .state = WL_KEYBOARD_KEY_STATE_RELEASED, - .time_msec = time, + .time_msec = get_current_time_msec(), .update_state = false, }; - wlr_keyboard_notify_key(dev->keyboard, &event); + wlr_keyboard_notify_key(keyboard, &event); } } static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - struct wlr_input_device *dev = data; - assert(dev && dev->keyboard); + struct wlr_keyboard *keyboard = data; struct wlr_event_keyboard_key wlr_event = { .keycode = key, @@ -274,15 +266,14 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, .time_msec = time, .update_state = false, }; - wlr_keyboard_notify_key(dev->keyboard, &wlr_event); + wlr_keyboard_notify_key(keyboard, &wlr_event); } static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { - struct wlr_input_device *dev = data; - assert(dev && dev->keyboard); - wlr_keyboard_notify_modifiers(dev->keyboard, mods_depressed, mods_latched, + struct wlr_keyboard *keyboard = data; + wlr_keyboard_notify_modifiers(keyboard, mods_depressed, mods_latched, mods_locked, group); } @@ -300,6 +291,24 @@ static const struct wl_keyboard_listener keyboard_listener = { .repeat_info = keyboard_handle_repeat_info }; +static const struct wlr_keyboard_impl keyboard_impl = { + .name = "wl-keyboard", +}; + +void init_seat_keyboard(struct wlr_wl_seat *seat) { + assert(seat->wl_keyboard); + + char name[128] = {0}; + snprintf(name, sizeof(name), "wayland-keyboard-%s", seat->name); + + wlr_keyboard_init(&seat->wlr_keyboard, &keyboard_impl, name); + wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, + &seat->wlr_keyboard); + + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_keyboard.base); +} + static void touch_coordinates_to_absolute(struct wlr_wl_input_device *device, wl_fixed_t x, wl_fixed_t y, double *sx, double *sy) { // TODO: each output needs its own touch @@ -420,10 +429,11 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { if (seat->pointer) { wl_pointer_destroy(seat->pointer); } - if (seat->keyboard && !wl->started) { - // early termination will not be handled by input_device_destroy - wl_keyboard_destroy(seat->keyboard); + if (seat->wl_keyboard) { + wl_keyboard_release(seat->wl_keyboard); + wlr_keyboard_finish(&seat->wlr_keyboard); } + free(seat->name); assert(seat->wl_seat); wl_seat_destroy(seat->wl_seat); @@ -474,8 +484,9 @@ struct wlr_wl_input_device *create_wl_input_device( switch (type) { case WLR_INPUT_DEVICE_KEYBOARD: - type_name = "keyboard"; - break; + wlr_log(WLR_ERROR, "can't create keyboard wlr_wl_input_device"); + free(dev); + return NULL; case WLR_INPUT_DEVICE_POINTER: type_name = "pointer"; break; @@ -550,8 +561,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { struct wlr_input_device *wlr_dev = &dev->wlr_input_device; switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - wlr_keyboard_finish(wlr_dev->keyboard); - free(wlr_dev->keyboard); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no keyboard"); break; case WLR_INPUT_DEVICE_POINTER: /* Owned by wlr_wl_pointer */ @@ -814,29 +824,6 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); } -void create_wl_keyboard(struct wlr_wl_seat *seat) { - assert(seat->keyboard); - struct wl_keyboard *wl_keyboard = seat->keyboard; - struct wlr_wl_input_device *dev = - create_wl_input_device(seat, WLR_INPUT_DEVICE_KEYBOARD); - if (!dev) { - return; - } - - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->keyboard = calloc(1, sizeof(*wlr_dev->keyboard)); - if (!wlr_dev->keyboard) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - destroy_wl_input_device(dev); - return; - } - - wlr_keyboard_init(wlr_dev->keyboard, &keyboard_impl, wlr_dev->name); - - wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev); - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev); -} - void create_wl_touch(struct wlr_wl_seat *seat) { assert(seat->touch); struct wl_touch *wl_touch = seat->touch; @@ -903,31 +890,23 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, seat->pointer = NULL; } - if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard == NULL) { - wlr_log(WLR_DEBUG, "seat %p offered keyboard", (void *)wl_seat); + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard == NULL) { + wlr_log(WLR_DEBUG, "seat '%s' offering keyboard", seat->name); struct wl_keyboard *wl_keyboard = wl_seat_get_keyboard(wl_seat); - seat->keyboard = wl_keyboard; + seat->wl_keyboard = wl_keyboard; if (backend->started) { - create_wl_keyboard(seat); + init_seat_keyboard(seat); } } - if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->keyboard != NULL) { - wlr_log(WLR_DEBUG, "seat %p dropped keyboard", (void *)wl_seat); + if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard != NULL) { + wlr_log(WLR_DEBUG, "seat '%s' dropping keyboard", seat->name); - struct wlr_wl_input_device *device, *tmp; - wl_list_for_each_safe(device, tmp, &backend->devices, link) { - if (device->wlr_input_device.type != WLR_INPUT_DEVICE_KEYBOARD) { - continue; - } + wl_keyboard_release(seat->wl_keyboard); + wlr_keyboard_finish(&seat->wlr_keyboard); - if (device->seat != seat) { - continue; - } - destroy_wl_input_device(device); - } - assert(seat->keyboard == NULL); // free'ed by input_device_destroy + seat->wl_keyboard = NULL; } if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch == NULL) { diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 668b69aed..20484cef3 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -112,23 +113,29 @@ struct wlr_wl_pointer { }; struct wlr_wl_seat { + char *name; struct wl_seat *wl_seat; - struct wl_list link; // wlr_wl_backend.seats - char *name; + struct wlr_wl_backend *backend; + + struct wl_keyboard *wl_keyboard; + struct wlr_keyboard wlr_keyboard; + struct wl_touch *touch; struct wl_pointer *pointer; - struct wl_keyboard *keyboard; - struct wlr_wl_backend *backend; struct wlr_wl_pointer *active_pointer; + + struct wl_list link; // wlr_wl_backend.seats }; struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend); void update_wl_output_cursor(struct wlr_wl_output *output); struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer); + +void init_seat_keyboard(struct wlr_wl_seat *seat); + void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); -void create_wl_keyboard(struct wlr_wl_seat *seat); void create_wl_touch(struct wlr_wl_seat *seat); struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_seat *seat, enum wlr_input_device_type type); @@ -138,6 +145,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev); void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; + extern const struct wlr_tablet_pad_impl tablet_pad_impl; extern const struct wlr_tablet_impl tablet_impl; From be8527bd360b748bba109049fbecae886b2c5380 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Fri, 4 Mar 2022 21:59:59 -0500 Subject: [PATCH 041/298] backend/wayland: give wlr_pointer ownership to wlr_wl_seat All the code logic related to the pointer has been moved to its own file. The seat is responsible for the lifetime of its wlr_wl_pointer(s), and assigning them to the relevant wlr_wl_output. The wlr_wl_pointer becomes a simple helper to manager the wlr_pointer associated to the seat's wl_pointer and its lifetime. --- backend/wayland/meson.build | 1 + backend/wayland/output.c | 8 +- backend/wayland/pointer.c | 528 ++++++++++++++++++++++++++++++++++++ backend/wayland/seat.c | 517 +---------------------------------- include/backend/wayland.h | 35 ++- 5 files changed, 569 insertions(+), 520 deletions(-) create mode 100644 backend/wayland/pointer.c diff --git a/backend/wayland/meson.build b/backend/wayland/meson.build index 1831bbb30..a8e310f3f 100644 --- a/backend/wayland/meson.build +++ b/backend/wayland/meson.build @@ -8,6 +8,7 @@ wlr_files += files( 'backend.c', 'output.c', 'seat.c', + 'pointer.c', 'tablet_v2.c', ) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index de5d42edd..65084b7a2 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -436,7 +436,9 @@ void update_wl_output_cursor(struct wlr_wl_output *output) { if (pointer) { assert(pointer->output == output); assert(output->enter_serial); - wl_pointer_set_cursor(pointer->wl_pointer, output->enter_serial, + + struct wlr_wl_seat *seat = pointer->seat; + wl_pointer_set_cursor(seat->wl_pointer, output->enter_serial, output->cursor.surface, output->cursor.hotspot_x, output->cursor.hotspot_y); } @@ -582,8 +584,8 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { struct wlr_wl_seat *seat; wl_list_for_each(seat, &backend->seats, link) { - if (seat->pointer) { - create_wl_pointer(seat, output); + if (seat->wl_pointer) { + create_pointer(seat, output); } } diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c new file mode 100644 index 000000000..9d3131b99 --- /dev/null +++ b/backend/wayland/pointer.c @@ -0,0 +1,528 @@ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include + +#include "backend/wayland.h" +#include "util/signal.h" + +#include "pointer-gestures-unstable-v1-client-protocol.h" +#include "relative-pointer-unstable-v1-client-protocol.h" + +static struct wlr_wl_pointer *output_get_pointer(struct wlr_wl_output *output, + const struct wl_pointer *wl_pointer) { + struct wlr_wl_seat *seat; + wl_list_for_each(seat, &output->backend->seats, link) { + if (seat->wl_pointer != wl_pointer) { + continue; + } + + struct wlr_wl_pointer *pointer; + wl_list_for_each(pointer, &seat->pointers, link) { + if (pointer->output == output) { + return pointer; + } + } + } + + return NULL; +} + +static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, + wl_fixed_t sy) { + struct wlr_wl_seat *seat = data; + if (surface == NULL) { + return; + } + + struct wlr_wl_output *output = wl_surface_get_user_data(surface); + assert(output); + + struct wlr_wl_pointer *pointer = output_get_pointer(output, wl_pointer); + seat->active_pointer = pointer; + + // Manage cursor icon/rendering on output + struct wlr_wl_pointer *current = output->cursor.pointer; + if (current && current != pointer) { + wlr_log(WLR_INFO, "Ignoring seat '%s' pointer in favor of seat '%s'", + seat->name, current->seat->name); + return; + } + + output->enter_serial = serial; + output->cursor.pointer = pointer; + update_wl_output_cursor(output); +} + +static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + struct wlr_wl_seat *seat = data; + if (surface == NULL) { + return; + } + + struct wlr_wl_output *output = wl_surface_get_user_data(surface); + assert(output); + + if (seat->active_pointer != NULL && + seat->active_pointer->output == output) { + seat->active_pointer = NULL; + } + + if (output->cursor.pointer == seat->active_pointer) { + output->enter_serial = 0; + output->cursor.pointer = NULL; + } +} + +static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t sx, wl_fixed_t sy) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_output *wlr_output = &pointer->output->wlr_output; + struct wlr_event_pointer_motion_absolute event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .x = wl_fixed_to_double(sx) / wlr_output->width, + .y = wl_fixed_to_double(sy) / wlr_output->height, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.motion_absolute, &event); +} + +static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_button event = { + .device = &pointer->wlr_pointer.base, + .button = button, + .state = state, + .time_msec = time, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.button, &event); +} + +static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_axis event = { + .device = &pointer->wlr_pointer.base, + .delta = wl_fixed_to_double(value), + .delta_discrete = pointer->axis_discrete, + .orientation = axis, + .time_msec = time, + .source = pointer->axis_source, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); + + pointer->axis_discrete = 0; +} + +static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + wlr_signal_emit_safe(&pointer->wlr_pointer.events.frame, + &pointer->wlr_pointer); +} + +static void pointer_handle_axis_source(void *data, + struct wl_pointer *wl_pointer, uint32_t axis_source) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->axis_source = axis_source; +} + +static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_axis event = { + .device = &pointer->wlr_pointer.base, + .delta = 0, + .delta_discrete = 0, + .orientation = axis, + .time_msec = time, + .source = pointer->axis_source, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); +} + +static void pointer_handle_axis_discrete(void *data, + struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->axis_discrete = discrete; +} + +static const struct wl_pointer_listener pointer_listener = { + .enter = pointer_handle_enter, + .leave = pointer_handle_leave, + .motion = pointer_handle_motion, + .button = pointer_handle_button, + .axis = pointer_handle_axis, + .frame = pointer_handle_frame, + .axis_source = pointer_handle_axis_source, + .axis_stop = pointer_handle_axis_stop, + .axis_discrete = pointer_handle_axis_discrete, +}; + +static void gesture_swipe_begin(void *data, + struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, + uint32_t serial, uint32_t time, struct wl_surface *surface, + uint32_t fingers) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->fingers = fingers; + + struct wlr_event_pointer_swipe_begin wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .fingers = fingers, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_begin, &wlr_event); +} + +static void gesture_swipe_update(void *data, + struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, + uint32_t time, wl_fixed_t dx, wl_fixed_t dy) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_swipe_update wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .fingers = pointer->fingers, + .dx = wl_fixed_to_double(dx), + .dy = wl_fixed_to_double(dy), + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_update, &wlr_event); +} + +static void gesture_swipe_end(void *data, + struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, + uint32_t serial, uint32_t time, int32_t cancelled) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_swipe_end wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .cancelled = cancelled, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_end, &wlr_event); +} + +static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_impl = { + .begin = gesture_swipe_begin, + .update = gesture_swipe_update, + .end = gesture_swipe_end, +}; + +static void gesture_pinch_begin(void *data, + struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, + uint32_t serial, uint32_t time, struct wl_surface *surface, + uint32_t fingers) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->fingers = fingers; + + struct wlr_event_pointer_pinch_begin wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .fingers = pointer->fingers, + }; + + wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_begin, &wlr_event); +} + +static void gesture_pinch_update(void *data, + struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, + uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, + wl_fixed_t rotation) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_pinch_update wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .fingers = pointer->fingers, + .dx = wl_fixed_to_double(dx), + .dy = wl_fixed_to_double(dy), + .scale = wl_fixed_to_double(scale), + .rotation = wl_fixed_to_double(rotation), + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_update, &wlr_event); +} + +static void gesture_pinch_end(void *data, + struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, + uint32_t serial, uint32_t time, int32_t cancelled) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_pinch_end wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .cancelled = cancelled, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_end, &wlr_event); +} + +static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_impl = { + .begin = gesture_pinch_begin, + .update = gesture_pinch_update, + .end = gesture_pinch_end, +}; + +static void gesture_hold_begin(void *data, + struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1, + uint32_t serial, uint32_t time, struct wl_surface *surface, + uint32_t fingers) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->fingers = fingers; + + struct wlr_event_pointer_hold_begin wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .fingers = fingers, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.hold_begin, &wlr_event); +} + +static void gesture_hold_end(void *data, + struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1, + uint32_t serial, uint32_t time, int32_t cancelled) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_hold_end wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = time, + .cancelled = cancelled, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.hold_end, &wlr_event); +} + +static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_impl = { + .begin = gesture_hold_begin, + .end = gesture_hold_end, +}; + +static void relative_pointer_handle_relative_motion(void *data, + struct zwp_relative_pointer_v1 *relative_pointer, uint32_t utime_hi, + uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, + wl_fixed_t dy_unaccel) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + uint64_t time_usec = (uint64_t)utime_hi << 32 | utime_lo; + + struct wlr_event_pointer_motion wlr_event = { + .device = &pointer->wlr_pointer.base, + .time_msec = (uint32_t)(time_usec / 1000), + .delta_x = wl_fixed_to_double(dx), + .delta_y = wl_fixed_to_double(dy), + .unaccel_dx = wl_fixed_to_double(dx_unaccel), + .unaccel_dy = wl_fixed_to_double(dy_unaccel), + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.motion, &wlr_event); +} + +static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { + .relative_motion = relative_pointer_handle_relative_motion, +}; + +const struct wlr_pointer_impl wl_pointer_impl = { + .name = "wl-pointer", +}; + +static void destroy_pointer(struct wlr_wl_pointer *pointer) { + if (pointer->output->cursor.pointer == pointer) { + pointer->output->cursor.pointer = NULL; + } + + wlr_pointer_finish(&pointer->wlr_pointer); + wl_list_remove(&pointer->output_destroy.link); + wl_list_remove(&pointer->link); + free(pointer); +} + +static void pointer_output_destroy(struct wl_listener *listener, void *data) { + struct wlr_wl_pointer *pointer = + wl_container_of(listener, pointer, output_destroy); + destroy_pointer(pointer); +} + +void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { + assert(seat->wl_pointer); + + if (output_get_pointer(output, seat->wl_pointer)) { + wlr_log(WLR_DEBUG, + "pointer for output '%s' from seat '%s' already exists", + output->wlr_output.name, seat->name); + return; + } + + wlr_log(WLR_DEBUG, "creating pointer for output '%s' from seat '%s'", + output->wlr_output.name, seat->name); + + struct wlr_wl_pointer *pointer = calloc(1, sizeof(struct wlr_wl_pointer)); + if (pointer == NULL) { + wlr_log(WLR_ERROR, "failed to allocate wlr_wl_pointer"); + return; + } + + char name[64] = {0}; + snprintf(name, sizeof(name), "wayland-pointer-%s", seat->name); + wlr_pointer_init(&pointer->wlr_pointer, &wl_pointer_impl, name); + + /* TODO: move output_name to pointer/touch */ + pointer->wlr_pointer.base.output_name = strdup(output->wlr_output.name); + + pointer->seat = seat; + pointer->output = output; + + wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy); + pointer->output_destroy.notify = pointer_output_destroy; + + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &pointer->wlr_pointer.base); + + wl_list_insert(&seat->pointers, &pointer->link); +} + +void init_seat_pointer(struct wlr_wl_seat *seat) { + assert(seat->wl_pointer); + + struct wlr_wl_backend *backend = seat->backend; + + wl_list_init(&seat->pointers); + + struct wlr_wl_output *output; + wl_list_for_each(output, &backend->outputs, link) { + create_pointer(seat, output); + } + + if (backend->zwp_pointer_gestures_v1) { + uint32_t version = zwp_pointer_gestures_v1_get_version( + backend->zwp_pointer_gestures_v1); + + seat->gesture_swipe = zwp_pointer_gestures_v1_get_swipe_gesture( + backend->zwp_pointer_gestures_v1, seat->wl_pointer); + zwp_pointer_gesture_swipe_v1_add_listener(seat->gesture_swipe, + &gesture_swipe_impl, seat); + + seat->gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture( + backend->zwp_pointer_gestures_v1, seat->wl_pointer); + zwp_pointer_gesture_pinch_v1_add_listener(seat->gesture_pinch, + &gesture_pinch_impl, seat); + + if (version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE) { + seat->gesture_hold = zwp_pointer_gestures_v1_get_hold_gesture( + backend->zwp_pointer_gestures_v1, seat->wl_pointer); + zwp_pointer_gesture_hold_v1_add_listener(seat->gesture_hold, + &gesture_hold_impl, seat); + } + } + + if (backend->zwp_relative_pointer_manager_v1) { + seat->relative_pointer = + zwp_relative_pointer_manager_v1_get_relative_pointer( + backend->zwp_relative_pointer_manager_v1, seat->wl_pointer); + zwp_relative_pointer_v1_add_listener(seat->relative_pointer, + &relative_pointer_listener, seat); + } + + wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); +} + +void finish_seat_pointer(struct wlr_wl_seat *seat) { + assert(seat->wl_pointer); + + wl_pointer_release(seat->wl_pointer); + + struct wlr_wl_pointer *pointer, *tmp; + wl_list_for_each_safe(pointer, tmp, &seat->pointers, link) { + destroy_pointer(pointer); + } + + if (seat->gesture_swipe != NULL) { + zwp_pointer_gesture_swipe_v1_destroy(seat->gesture_swipe); + } + if (seat->gesture_pinch != NULL) { + zwp_pointer_gesture_pinch_v1_destroy(seat->gesture_pinch); + } + if (seat->gesture_hold != NULL) { + zwp_pointer_gesture_hold_v1_destroy(seat->gesture_hold); + } + if (seat->relative_pointer != NULL) { + zwp_relative_pointer_v1_destroy(seat->relative_pointer); + } + + seat->wl_pointer = NULL; + seat->active_pointer = NULL; +} diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 0ca297f36..c8ad91ee0 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -11,208 +11,19 @@ #include #include -#include #include #include #include #include #include -#include "pointer-gestures-unstable-v1-client-protocol.h" -#include "relative-pointer-unstable-v1-client-protocol.h" #include "interfaces/wlr_input_device.h" #include "backend/wayland.h" #include "util/signal.h" #include "util/time.h" -static const struct wlr_pointer_impl pointer_impl; static const struct wlr_touch_impl touch_impl; -static struct wlr_wl_pointer *output_get_pointer( - struct wlr_wl_output *output, - const struct wl_pointer *wl_pointer) { - struct wlr_wl_input_device *dev; - wl_list_for_each(dev, &output->backend->devices, link) { - if (dev->wlr_input_device.type != WLR_INPUT_DEVICE_POINTER) { - continue; - } - struct wlr_wl_pointer *pointer = - pointer_get_wl(dev->wlr_input_device.pointer); - if (pointer->output == output && pointer->wl_pointer == wl_pointer) { - return pointer; - } - } - - return NULL; -} - -static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, - wl_fixed_t sy) { - struct wlr_wl_seat *seat = data; - if (surface == NULL) { - return; - } - - struct wlr_wl_output *output = wl_surface_get_user_data(surface); - assert(output); - struct wlr_wl_pointer *pointer = output_get_pointer(output, wl_pointer); - seat->active_pointer = pointer; - - // Manage cursor icon/rendering on output - struct wlr_wl_pointer *current_pointer = output->cursor.pointer; - if (current_pointer && current_pointer != pointer) { - wlr_log(WLR_INFO, "Ignoring seat %s pointer cursor in favor of seat %s", - seat->name, current_pointer->input_device->seat->name); - return; - } - - output->enter_serial = serial; - output->cursor.pointer = pointer; - update_wl_output_cursor(output); -} - -static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, struct wl_surface *surface) { - struct wlr_wl_seat *seat = data; - if (surface == NULL) { - return; - } - - struct wlr_wl_output *output = wl_surface_get_user_data(surface); - assert(output); - - if (seat->active_pointer != NULL && - seat->active_pointer->output == output) { - seat->active_pointer = NULL; - } - - if (output->cursor.pointer == seat->active_pointer) { - output->enter_serial = 0; - output->cursor.pointer = NULL; - } -} - -static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, - uint32_t time, wl_fixed_t sx, wl_fixed_t sy) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - struct wlr_output *wlr_output = &pointer->output->wlr_output; - struct wlr_event_pointer_motion_absolute event = { - .device = &pointer->input_device->wlr_input_device, - .time_msec = time, - .x = wl_fixed_to_double(sx) / wlr_output->width, - .y = wl_fixed_to_double(sy) / wlr_output->height, - }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.motion_absolute, &event); -} - -static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, - uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - struct wlr_event_pointer_button event = { - .device = &pointer->input_device->wlr_input_device, - .button = button, - .state = state, - .time_msec = time, - }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.button, &event); -} - -static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - struct wlr_event_pointer_axis event = { - .device = &pointer->input_device->wlr_input_device, - .delta = wl_fixed_to_double(value), - .delta_discrete = pointer->axis_discrete, - .orientation = axis, - .time_msec = time, - .source = pointer->axis_source, - }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); - - pointer->axis_discrete = 0; -} - -static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - wlr_signal_emit_safe(&pointer->wlr_pointer.events.frame, - &pointer->wlr_pointer); -} - -static void pointer_handle_axis_source(void *data, - struct wl_pointer *wl_pointer, uint32_t axis_source) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - pointer->axis_source = axis_source; -} - -static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - struct wlr_event_pointer_axis event = { - .device = &pointer->input_device->wlr_input_device, - .delta = 0, - .delta_discrete = 0, - .orientation = axis, - .time_msec = time, - .source = pointer->axis_source, - }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); -} - -static void pointer_handle_axis_discrete(void *data, - struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) { - struct wlr_wl_seat *seat = data; - struct wlr_wl_pointer *pointer = seat->active_pointer; - if (pointer == NULL) { - return; - } - - pointer->axis_discrete = discrete; -} - -static const struct wl_pointer_listener pointer_listener = { - .enter = pointer_handle_enter, - .leave = pointer_handle_leave, - .motion = pointer_handle_motion, - .button = pointer_handle_button, - .axis = pointer_handle_axis, - .frame = pointer_handle_frame, - .axis_source = pointer_handle_axis_source, - .axis_stop = pointer_handle_axis_stop, - .axis_discrete = pointer_handle_axis_discrete, -}; - static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { close(fd); @@ -426,8 +237,8 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { if (seat->touch) { wl_touch_destroy(seat->touch); } - if (seat->pointer) { - wl_pointer_destroy(seat->pointer); + if (seat->wl_pointer) { + finish_seat_pointer(seat); } if (seat->wl_keyboard) { wl_keyboard_release(seat->wl_keyboard); @@ -455,7 +266,7 @@ bool wlr_input_device_is_wl(struct wlr_input_device *dev) { case WLR_INPUT_DEVICE_KEYBOARD: return dev->keyboard->impl == &keyboard_impl; case WLR_INPUT_DEVICE_POINTER: - return dev->pointer->impl == &pointer_impl; + return dev->pointer->impl == &wl_pointer_impl; case WLR_INPUT_DEVICE_TOUCH: return dev->touch->impl == &touch_impl; case WLR_INPUT_DEVICE_TABLET_TOOL: @@ -488,8 +299,9 @@ struct wlr_wl_input_device *create_wl_input_device( free(dev); return NULL; case WLR_INPUT_DEVICE_POINTER: - type_name = "pointer"; - break; + wlr_log(WLR_ERROR, "can't create pointer wlr_wl_input_device"); + free(dev); + return NULL; case WLR_INPUT_DEVICE_TOUCH: type_name = "touch"; break; @@ -513,43 +325,6 @@ struct wlr_wl_input_device *create_wl_input_device( return dev; } -struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer) { - assert(wlr_pointer->impl == &pointer_impl); - return (struct wlr_wl_pointer *)wlr_pointer; -} - -static void pointer_destroy(struct wlr_pointer *wlr_pointer) { - struct wlr_wl_pointer *pointer = pointer_get_wl(wlr_pointer); - - if (pointer->output->cursor.pointer == pointer) { - pointer->output->cursor.pointer = NULL; - } - - struct wlr_wl_seat *seat = pointer->input_device->seat; - if (seat->active_pointer == pointer) { - seat->active_pointer = NULL; - } - - // pointer->wl_pointer belongs to the wlr_wl_seat - - if (pointer->gesture_swipe != NULL) { - zwp_pointer_gesture_swipe_v1_destroy(pointer->gesture_swipe); - } - if (pointer->gesture_pinch != NULL) { - zwp_pointer_gesture_pinch_v1_destroy(pointer->gesture_pinch); - } - if (pointer->gesture_hold != NULL) { - zwp_pointer_gesture_hold_v1_destroy(pointer->gesture_hold); - } - if (pointer->relative_pointer != NULL) { - zwp_relative_pointer_v1_destroy(pointer->relative_pointer); - } - - wlr_pointer_finish(&pointer->wlr_pointer); - wl_list_remove(&pointer->output_destroy.link); - free(pointer); -} - void destroy_wl_input_device(struct wlr_wl_input_device *dev) { /** * TODO remove the redundant wlr_input_device from wlr_wl_input_device @@ -564,8 +339,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_log(WLR_ERROR, "wlr_wl_input_device has no keyboard"); break; case WLR_INPUT_DEVICE_POINTER: - /* Owned by wlr_wl_pointer */ - pointer_destroy(wlr_dev->pointer); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer"); break; case WLR_INPUT_DEVICE_SWITCH: wlr_switch_finish(wlr_dev->switch_device); @@ -588,242 +362,6 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { free(dev); } -static void gesture_swipe_begin(void *data, - struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, - uint32_t serial, uint32_t time, - struct wl_surface *surface, uint32_t fingers) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_swipe_begin wlr_event = { - .device = wlr_dev, - .time_msec = time, - .fingers = fingers, - }; - input_device->fingers = fingers; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_begin, &wlr_event); -} - -static void gesture_swipe_update(void *data, - struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, - uint32_t time, wl_fixed_t dx, wl_fixed_t dy) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_swipe_update wlr_event = { - .device = wlr_dev, - .time_msec = time, - .fingers = input_device->fingers, - .dx = wl_fixed_to_double(dx), - .dy = wl_fixed_to_double(dy), - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_update, &wlr_event); -} - -static void gesture_swipe_end(void *data, - struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1, - uint32_t serial, uint32_t time, int32_t cancelled) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_swipe_end wlr_event = { - .device = wlr_dev, - .time_msec = time, - .cancelled = cancelled, - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_end, &wlr_event); -} - -static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_impl = { - .begin = gesture_swipe_begin, - .update = gesture_swipe_update, - .end = gesture_swipe_end, -}; - -static void gesture_pinch_begin(void *data, - struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, - uint32_t serial, uint32_t time, - struct wl_surface *surface, uint32_t fingers) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_pinch_begin wlr_event = { - .device = wlr_dev, - .time_msec = time, - .fingers = fingers, - }; - input_device->fingers = fingers; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_begin, &wlr_event); -} - -static void gesture_pinch_update(void *data, - struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, - uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale, wl_fixed_t rotation) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_pinch_update wlr_event = { - .device = wlr_dev, - .time_msec = time, - .fingers = input_device->fingers, - .dx = wl_fixed_to_double(dx), - .dy = wl_fixed_to_double(dy), - .scale = wl_fixed_to_double(scale), - .rotation = wl_fixed_to_double(rotation), - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_update, &wlr_event); -} - -static void gesture_pinch_end(void *data, - struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1, - uint32_t serial, uint32_t time, int32_t cancelled) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_pinch_end wlr_event = { - .device = wlr_dev, - .time_msec = time, - .cancelled = cancelled, - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_end, &wlr_event); -} - -static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_impl = { - .begin = gesture_pinch_begin, - .update = gesture_pinch_update, - .end = gesture_pinch_end, -}; - -static void gesture_hold_begin(void *data, - struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1, - uint32_t serial, uint32_t time, - struct wl_surface *surface, uint32_t fingers) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_hold_begin wlr_event = { - .device = wlr_dev, - .time_msec = time, - .fingers = fingers, - }; - input_device->fingers = fingers; - wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_begin, &wlr_event); -} - -static void gesture_hold_end(void *data, - struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1, - uint32_t serial, uint32_t time, int32_t cancelled) { - struct wlr_wl_input_device *input_device = (struct wlr_wl_input_device *)data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - struct wlr_event_pointer_hold_end wlr_event = { - .device = wlr_dev, - .time_msec = time, - .cancelled = cancelled, - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_end, &wlr_event); -} - -static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_impl = { - .begin = gesture_hold_begin, - .end = gesture_hold_end, -}; - -static void relative_pointer_handle_relative_motion(void *data, - struct zwp_relative_pointer_v1 *relative_pointer, uint32_t utime_hi, - uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, - wl_fixed_t dy_unaccel) { - struct wlr_wl_input_device *input_device = data; - struct wlr_input_device *wlr_dev = &input_device->wlr_input_device; - if (pointer_get_wl(wlr_dev->pointer) != input_device->seat->active_pointer) { - return; - } - - uint64_t time_usec = (uint64_t)utime_hi << 32 | utime_lo; - - struct wlr_event_pointer_motion wlr_event = { - .device = wlr_dev, - .time_msec = (uint32_t)(time_usec / 1000), - .delta_x = wl_fixed_to_double(dx), - .delta_y = wl_fixed_to_double(dy), - .unaccel_dx = wl_fixed_to_double(dx_unaccel), - .unaccel_dy = wl_fixed_to_double(dy_unaccel), - }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.motion, &wlr_event); -} - -static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { - .relative_motion = relative_pointer_handle_relative_motion, -}; - - -static void pointer_handle_output_destroy(struct wl_listener *listener, - void *data) { - struct wlr_wl_pointer *pointer = - wl_container_of(listener, pointer, output_destroy); - destroy_wl_input_device(pointer->input_device); -} - -void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { - assert(seat->pointer); - struct wl_pointer *wl_pointer = seat->pointer; - struct wlr_wl_backend *backend = output->backend; - - if (output_get_pointer(output, wl_pointer)) { - wlr_log(WLR_DEBUG, - "Pointer for seat %s and output %s already exists (ignoring)", - seat->name, output->wlr_output.name); - return; - } - - struct wlr_wl_pointer *pointer = calloc(1, sizeof(struct wlr_wl_pointer)); - if (pointer == NULL) { - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - pointer->wl_pointer = wl_pointer; - pointer->output = output; // we need output to map absolute coordinates onto - - struct wlr_wl_input_device *dev = - create_wl_input_device(seat, WLR_INPUT_DEVICE_POINTER); - if (dev == NULL) { - free(pointer); - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - pointer->input_device = dev; - - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->pointer = &pointer->wlr_pointer; - wlr_dev->output_name = strdup(output->wlr_output.name); - - wlr_pointer_init(&pointer->wlr_pointer, &pointer_impl, wlr_dev->name); - - wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy); - pointer->output_destroy.notify = pointer_handle_output_destroy; - - if (backend->zwp_pointer_gestures_v1) { - uint32_t version = zwp_pointer_gestures_v1_get_version( - backend->zwp_pointer_gestures_v1); - - pointer->gesture_swipe = zwp_pointer_gestures_v1_get_swipe_gesture( - backend->zwp_pointer_gestures_v1, wl_pointer); - zwp_pointer_gesture_swipe_v1_add_listener(pointer->gesture_swipe, &gesture_swipe_impl, dev); - pointer->gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture( - backend->zwp_pointer_gestures_v1, wl_pointer); - zwp_pointer_gesture_pinch_v1_add_listener(pointer->gesture_pinch, &gesture_pinch_impl, dev); - - if (version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE) { - pointer->gesture_hold = zwp_pointer_gestures_v1_get_hold_gesture( - backend->zwp_pointer_gestures_v1, wl_pointer); - zwp_pointer_gesture_hold_v1_add_listener(pointer->gesture_hold, &gesture_hold_impl, dev); - } - } - - if (backend->zwp_relative_pointer_manager_v1) { - pointer->relative_pointer = - zwp_relative_pointer_manager_v1_get_relative_pointer( - backend->zwp_relative_pointer_manager_v1, wl_pointer); - zwp_relative_pointer_v1_add_listener(pointer->relative_pointer, - &relative_pointer_listener, dev); - } - - wl_pointer_add_listener(wl_pointer, &pointer_listener, seat); - wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev); -} - void create_wl_touch(struct wlr_wl_seat *seat) { assert(seat->touch); struct wl_touch *wl_touch = seat->touch; @@ -852,42 +390,15 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, struct wlr_wl_seat *seat = data; struct wlr_wl_backend *backend = seat->backend; - if ((caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer == NULL) { - wlr_log(WLR_DEBUG, "seat %p offered pointer", (void *)wl_seat); + if ((caps & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer == NULL) { + wlr_log(WLR_DEBUG, "seat '%s' offering pointer", seat->name); - struct wl_pointer *wl_pointer = wl_seat_get_pointer(wl_seat); - seat->pointer = wl_pointer; - - struct wlr_wl_output *output; - wl_list_for_each(output, &backend->outputs, link) { - create_wl_pointer(seat, output); - } + seat->wl_pointer = wl_seat_get_pointer(wl_seat); + init_seat_pointer(seat); } - if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer != NULL) { - wlr_log(WLR_DEBUG, "seat %p dropped pointer", (void *)wl_seat); - - struct wl_pointer *wl_pointer = seat->pointer; - - struct wlr_wl_input_device *device, *tmp; - wl_list_for_each_safe(device, tmp, &backend->devices, link) { - if (device->wlr_input_device.type != WLR_INPUT_DEVICE_POINTER) { - continue; - } - struct wlr_wl_pointer *pointer = - pointer_get_wl(device->wlr_input_device.pointer); - if (pointer->wl_pointer != wl_pointer) { - continue; - } - wlr_log(WLR_DEBUG, "dropping pointer %s", - pointer->input_device->wlr_input_device.name); - struct wlr_wl_output *output = pointer->output; - destroy_wl_input_device(device); - assert(seat->active_pointer != pointer); - assert(output->cursor.pointer != pointer); - } - - wl_pointer_release(seat->pointer); - seat->pointer = NULL; + if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer != NULL) { + wlr_log(WLR_DEBUG, "seat '%s' dropping pointer", seat->name); + finish_seat_pointer(seat); } if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && seat->wl_keyboard == NULL) { diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 20484cef3..0ff856105 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -89,7 +89,6 @@ struct wlr_wl_output { struct wlr_wl_input_device { struct wlr_input_device wlr_input_device; struct wl_list link; - uint32_t fingers; struct wlr_wl_backend *backend; struct wlr_wl_seat *seat; @@ -99,17 +98,16 @@ struct wlr_wl_input_device { struct wlr_wl_pointer { struct wlr_pointer wlr_pointer; - struct wlr_wl_input_device *input_device; - struct wl_pointer *wl_pointer; - struct zwp_pointer_gesture_swipe_v1 *gesture_swipe; - struct zwp_pointer_gesture_pinch_v1 *gesture_pinch; - struct zwp_pointer_gesture_hold_v1 *gesture_hold; - struct zwp_relative_pointer_v1 *relative_pointer; - enum wlr_axis_source axis_source; - int32_t axis_discrete; + struct wlr_wl_seat *seat; struct wlr_wl_output *output; + enum wlr_axis_source axis_source; + int32_t axis_discrete; + uint32_t fingers; // trackpad gesture + struct wl_listener output_destroy; + + struct wl_list link; }; struct wlr_wl_seat { @@ -121,21 +119,29 @@ struct wlr_wl_seat { struct wl_keyboard *wl_keyboard; struct wlr_keyboard wlr_keyboard; - struct wl_touch *touch; - struct wl_pointer *pointer; - + struct wl_pointer *wl_pointer; struct wlr_wl_pointer *active_pointer; + struct wl_list pointers; // wlr_wl_pointer::link + + struct zwp_pointer_gesture_swipe_v1 *gesture_swipe; + struct zwp_pointer_gesture_pinch_v1 *gesture_pinch; + struct zwp_pointer_gesture_hold_v1 *gesture_hold; + struct zwp_relative_pointer_v1 *relative_pointer; + + struct wl_touch *touch; struct wl_list link; // wlr_wl_backend.seats }; struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *backend); void update_wl_output_cursor(struct wlr_wl_output *output); -struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer); void init_seat_keyboard(struct wlr_wl_seat *seat); -void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); +void init_seat_pointer(struct wlr_wl_seat *seat); +void finish_seat_pointer(struct wlr_wl_seat *seat); +void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); + void create_wl_touch(struct wlr_wl_seat *seat); struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_seat *seat, enum wlr_input_device_type type); @@ -146,6 +152,7 @@ void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; +extern const struct wlr_pointer_impl wl_pointer_impl; extern const struct wlr_tablet_pad_impl tablet_pad_impl; extern const struct wlr_tablet_impl tablet_impl; From e723dd928bb254c3521e1b8e866bad7971587094 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 7 Mar 2022 11:11:49 -0500 Subject: [PATCH 042/298] backend/wayland: drop wlr_switch support --- backend/wayland/seat.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index c8ad91ee0..f6665a58d 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -311,9 +310,10 @@ struct wlr_wl_input_device *create_wl_input_device( case WLR_INPUT_DEVICE_TABLET_PAD: type_name = "tablet-pad"; break; - case WLR_INPUT_DEVICE_SWITCH: - type_name = "switch"; - break; + default: + wlr_log(WLR_ERROR, "device not handled"); + free(dev); + return NULL; } size_t name_size = 8 + strlen(type_name) + strlen(seat->name) + 1; @@ -341,9 +341,6 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { case WLR_INPUT_DEVICE_POINTER: wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer"); break; - case WLR_INPUT_DEVICE_SWITCH: - wlr_switch_finish(wlr_dev->switch_device); - break; case WLR_INPUT_DEVICE_TABLET_PAD: wlr_tablet_pad_finish(wlr_dev->tablet_pad); free(wlr_dev->tablet_pad); @@ -356,6 +353,8 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_touch_finish(wlr_dev->touch); free(wlr_dev->touch); break; + default: + break; } } wl_list_remove(&dev->link); From d3fb44314cfbe307ac77230074baf5d0fb33c202 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Mon, 7 Mar 2022 13:33:20 -0500 Subject: [PATCH 043/298] backend/wayland: give wlr_touch ownership to wlr_wl_seat --- backend/wayland/seat.c | 131 ++++++++++++++++---------------------- include/backend/wayland.h | 5 +- 2 files changed, 59 insertions(+), 77 deletions(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index f6665a58d..e2d5278c3 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -21,8 +21,6 @@ #include "util/signal.h" #include "util/time.h" -static const struct wlr_touch_impl touch_impl; - static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) { close(fd); @@ -119,11 +117,17 @@ void init_seat_keyboard(struct wlr_wl_seat *seat) { &seat->wlr_keyboard.base); } -static void touch_coordinates_to_absolute(struct wlr_wl_input_device *device, +static void touch_coordinates_to_absolute(struct wlr_wl_seat *seat, wl_fixed_t x, wl_fixed_t y, double *sx, double *sy) { - // TODO: each output needs its own touch + /** + * TODO: multi-output touch support + * Although the wayland backend supports multi-output pointers, the support + * for multi-output touch has been left on the side for simplicity reasons. + * If this is a feature you want/need, please open an issue on the wlroots + * tracker here https://gitlab.freedesktop.org/wlroots/wlroots/-/issues + */ struct wlr_wl_output *output, *tmp; - wl_list_for_each_safe(output, tmp, &device->backend->outputs, link) { + wl_list_for_each_safe(output, tmp, &seat->backend->outputs, link) { *sx = wl_fixed_to_double(x) / output->wlr_output.width; *sy = wl_fixed_to_double(y) / output->wlr_output.height; return; // Choose the first output in the list @@ -135,56 +139,46 @@ static void touch_coordinates_to_absolute(struct wlr_wl_input_device *device, static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_input_device *device = data; - assert(device && device->wlr_input_device.touch); + struct wlr_wl_seat *seat = data; - double sx, sy; - touch_coordinates_to_absolute(device, x, y, &sx, &sy); struct wlr_event_touch_down event = { - .device = &device->wlr_input_device, + .device = &seat->wlr_touch.base, .time_msec = time, .touch_id = id, - .x = sx, - .y = sy }; - wlr_signal_emit_safe(&device->wlr_input_device.touch->events.down, &event); + touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); + wlr_signal_emit_safe(&seat->wlr_touch.events.down, &event); } static void touch_handle_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { - struct wlr_wl_input_device *device = data; - assert(device && device->wlr_input_device.touch); + struct wlr_wl_seat *seat = data; struct wlr_event_touch_up event = { - .device = &device->wlr_input_device, + .device = &seat->wlr_touch.base, .time_msec = time, .touch_id = id, }; - wlr_signal_emit_safe(&device->wlr_input_device.touch->events.up, &event); + wlr_signal_emit_safe(&seat->wlr_touch.events.up, &event); } static void touch_handle_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_input_device *device = data; - assert(device && device->wlr_input_device.touch); + struct wlr_wl_seat *seat = data; + struct wlr_input_device *device = &seat->wlr_touch.base; - double sx, sy; - touch_coordinates_to_absolute(device, x, y, &sx, &sy); struct wlr_event_touch_motion event = { - .device = &device->wlr_input_device, + .device = device, .time_msec = time, .touch_id = id, - .x = sx, - .y = sy }; - wlr_signal_emit_safe(&device->wlr_input_device.touch->events.motion, &event); + touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); + wlr_signal_emit_safe(&seat->wlr_touch.events.motion, &event); } static void touch_handle_frame(void *data, struct wl_touch *wl_touch) { - struct wlr_wl_input_device *device = data; - assert(device && device->wlr_input_device.touch); - - wlr_signal_emit_safe(&device->wlr_input_device.touch->events.frame, NULL); + struct wlr_wl_seat *seat = data; + wlr_signal_emit_safe(&seat->wlr_touch.events.frame, NULL); } static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) { @@ -211,6 +205,23 @@ static const struct wl_touch_listener touch_listener = { .orientation = touch_handle_orientation, }; +static const struct wlr_touch_impl touch_impl = { + .name = "wl-touch", +}; + +static void init_seat_touch(struct wlr_wl_seat *seat) { + assert(seat->wl_touch); + + char name[128] = {0}; + snprintf(name, sizeof(name), "wayland-touch-%s", seat->name); + + wlr_touch_init(&seat->wlr_touch, &touch_impl, name); + + wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_touch.base); +} + static struct wlr_wl_input_device *get_wl_input_device_from_input_device( struct wlr_input_device *wlr_dev) { assert(wlr_input_device_is_wl(wlr_dev)); @@ -233,8 +244,9 @@ bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl) { void destroy_wl_seats(struct wlr_wl_backend *wl) { struct wlr_wl_seat *seat, *tmp_seat; wl_list_for_each_safe(seat, tmp_seat, &wl->seats, link) { - if (seat->touch) { - wl_touch_destroy(seat->touch); + if (seat->wl_touch) { + wl_touch_release(seat->wl_touch); + wlr_touch_finish(&seat->wlr_touch); } if (seat->wl_pointer) { finish_seat_pointer(seat); @@ -302,8 +314,9 @@ struct wlr_wl_input_device *create_wl_input_device( free(dev); return NULL; case WLR_INPUT_DEVICE_TOUCH: - type_name = "touch"; - break; + wlr_log(WLR_ERROR, "can't create touch wlr_wl_input_device"); + free(dev); + return NULL; case WLR_INPUT_DEVICE_TABLET_TOOL: type_name = "tablet-tool"; break; @@ -350,8 +363,7 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { free(wlr_dev->tablet); break; case WLR_INPUT_DEVICE_TOUCH: - wlr_touch_finish(wlr_dev->touch); - free(wlr_dev->touch); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch"); break; default: break; @@ -361,29 +373,6 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { free(dev); } -void create_wl_touch(struct wlr_wl_seat *seat) { - assert(seat->touch); - struct wl_touch *wl_touch = seat->touch; - struct wlr_wl_input_device *dev = - create_wl_input_device(seat, WLR_INPUT_DEVICE_TOUCH); - if (!dev) { - return; - } - - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - - wlr_dev->touch = calloc(1, sizeof(*wlr_dev->touch)); - if (!wlr_dev->touch) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - destroy_wl_input_device(dev); - return; - } - wlr_touch_init(wlr_dev->touch, &touch_impl, wlr_dev->name); - - wl_touch_add_listener(wl_touch, &touch_listener, dev); - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev); -} - static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { struct wlr_wl_seat *seat = data; @@ -419,26 +408,18 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, seat->wl_keyboard = NULL; } - if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch == NULL) { - wlr_log(WLR_DEBUG, "seat %p offered touch", (void *)wl_seat); + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch == NULL) { + wlr_log(WLR_DEBUG, "seat '%s' offering touch", seat->name); - seat->touch = wl_seat_get_touch(wl_seat); - if (backend->started) { - create_wl_touch(seat); - } + seat->wl_touch = wl_seat_get_touch(wl_seat); + init_seat_touch(seat); } - if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->touch != NULL) { - wlr_log(WLR_DEBUG, "seat %p dropped touch", (void *)wl_seat); + if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch != NULL) { + wlr_log(WLR_DEBUG, "seat '%s' dropping touch", seat->name); - struct wlr_wl_input_device *device, *tmp; - wl_list_for_each_safe(device, tmp, &backend->devices, link) { - if (device->wlr_input_device.type == WLR_INPUT_DEVICE_TOUCH) { - destroy_wl_input_device(device); - } - } - - wl_touch_release(seat->touch); - seat->touch = NULL; + wl_touch_release(seat->wl_touch); + wlr_touch_finish(&seat->wlr_touch); + seat->wl_touch = NULL; } } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 0ff856105..e07daa4ff 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -10,6 +10,7 @@ #include #include #include +#include #include struct wlr_wl_backend { @@ -128,7 +129,8 @@ struct wlr_wl_seat { struct zwp_pointer_gesture_hold_v1 *gesture_hold; struct zwp_relative_pointer_v1 *relative_pointer; - struct wl_touch *touch; + struct wl_touch *wl_touch; + struct wlr_touch wlr_touch; struct wl_list link; // wlr_wl_backend.seats }; @@ -142,7 +144,6 @@ void init_seat_pointer(struct wlr_wl_seat *seat); void finish_seat_pointer(struct wlr_wl_seat *seat); void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); -void create_wl_touch(struct wlr_wl_seat *seat); struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_seat *seat, enum wlr_input_device_type type); bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); From 56f7c000b540b929bbdb0111b91108b1651924e6 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 09:33:58 -0500 Subject: [PATCH 044/298] backend/wayland/tablet_v2: give wlr_tablet_* ownership to wlr_wl_seat --- backend/wayland/backend.c | 2 +- backend/wayland/seat.c | 23 +- backend/wayland/tablet_v2.c | 471 ++++++++++++++++++------------------ include/backend/wayland.h | 21 +- 4 files changed, 262 insertions(+), 255 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 44468a268..3428488e9 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -418,7 +418,7 @@ static bool backend_start(struct wlr_backend *backend) { } if (wl->tablet_manager) { - wl_add_tablet_seat(wl->tablet_manager, seat); + init_seat_tablet(seat); } } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index e2d5278c3..854447ee1 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -255,6 +255,9 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { wl_keyboard_release(seat->wl_keyboard); wlr_keyboard_finish(&seat->wlr_keyboard); } + if (seat->zwp_tablet_seat_v2) { + finish_seat_tablet(seat); + } free(seat->name); assert(seat->wl_seat); @@ -281,9 +284,9 @@ bool wlr_input_device_is_wl(struct wlr_input_device *dev) { case WLR_INPUT_DEVICE_TOUCH: return dev->touch->impl == &touch_impl; case WLR_INPUT_DEVICE_TABLET_TOOL: - return dev->tablet->impl == &tablet_impl; + return dev->tablet->impl == &wl_tablet_impl; case WLR_INPUT_DEVICE_TABLET_PAD: - return dev->tablet_pad->impl == &tablet_pad_impl; + return dev->tablet_pad->impl == &wl_tablet_pad_impl; default: return false; } @@ -318,11 +321,13 @@ struct wlr_wl_input_device *create_wl_input_device( free(dev); return NULL; case WLR_INPUT_DEVICE_TABLET_TOOL: - type_name = "tablet-tool"; - break; + wlr_log(WLR_ERROR, "can't create tablet tool wlr_wl_input_device"); + free(dev); + return NULL; case WLR_INPUT_DEVICE_TABLET_PAD: - type_name = "tablet-pad"; - break; + wlr_log(WLR_ERROR, "can't create tablet pad wlr_wl_input_device"); + free(dev); + return NULL; default: wlr_log(WLR_ERROR, "device not handled"); free(dev); @@ -355,12 +360,10 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer"); break; case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_tablet_pad_finish(wlr_dev->tablet_pad); - free(wlr_dev->tablet_pad); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet pad"); break; case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_tablet_finish(wlr_dev->tablet); - free(wlr_dev->tablet); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet_tool"); break; case WLR_INPUT_DEVICE_TOUCH: wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch"); diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index dc7f50fd9..5666aa5f8 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -1,35 +1,25 @@ -#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif -#include #include #include #include #include #include #include -#include - -#include "util/signal.h" -#include "util/time.h" -#include "wlr/util/log.h" -#include "tablet-unstable-v2-client-protocol.h" +#include #include "backend/wayland.h" +#include "util/signal.h" +#include "util/time.h" -struct wlr_wl_tablet_seat { - struct zwp_tablet_seat_v2 *tablet_seat; -}; +#include "tablet-unstable-v2-client-protocol.h" -struct wlr_wl_tablet_tool { +struct tablet_tool { /* static */ - struct zwp_tablet_tool_v2 *tool; - struct wlr_tablet_tool wlr_tool; + struct wlr_wl_seat *seat; /* semi-static */ struct wlr_wl_output *output; - struct wlr_wl_input_device *tablet; double pre_x, pre_y; /* per frame */ @@ -49,11 +39,11 @@ struct wlr_wl_tablet_tool { bool is_down; }; -struct wlr_wl_tablet_pad_ring { - struct wl_list link; // wlr_wl_tablet_pad_group::rings +struct tablet_pad_ring { + struct wl_list link; // tablet_pad_group::rings /* static */ struct zwp_tablet_pad_ring_v2 *ring; - struct wlr_wl_tablet_pad_group *group; + struct tablet_pad_group *group; size_t index; /* per frame */ @@ -62,10 +52,10 @@ struct wlr_wl_tablet_pad_ring { bool stopped; }; -struct wlr_wl_tablet_pad_strip { - struct wl_list link; // wlr_wl_tablet_pad_group::strips +struct tablet_pad_strip { + struct wl_list link; // tablet_pad_group::strips struct zwp_tablet_pad_strip_v2 *strip; - struct wlr_wl_tablet_pad_group *group; + struct tablet_pad_group *group; size_t index; enum wlr_tablet_pad_strip_source source; @@ -73,41 +63,41 @@ struct wlr_wl_tablet_pad_strip { bool stopped; }; -struct wlr_wl_tablet_pad_group { +struct tablet_pad_group { struct zwp_tablet_pad_group_v2 *pad_group; struct wlr_tablet_pad *pad; unsigned int mode; struct wlr_tablet_pad_group group; - struct wl_list rings; // wlr_wl_tablet_pad_ring::link - struct wl_list strips; // wlr_wl_tablet_pad_strips::link + struct wl_list rings; // tablet_pad_ring::link + struct wl_list strips; // tablet_pad_strips::link }; static void handle_tablet_pad_ring_source(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, uint32_t source) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->source = source; } static void handle_tablet_pad_ring_angle(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, wl_fixed_t degrees) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->angle = wl_fixed_to_double(degrees); } static void handle_tablet_pad_ring_stop(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->stopped = true; } static void handle_tablet_pad_ring_frame(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, uint32_t time) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; struct wlr_event_tablet_pad_ring evt = { .time_msec = time, @@ -140,27 +130,27 @@ static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { static void handle_tablet_pad_strip_source(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t source) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->source = source; } static void handle_tablet_pad_strip_position(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t position) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->position = (double) position / 65536.0; } static void handle_tablet_pad_strip_stop(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->stopped = true; } static void handle_tablet_pad_strip_frame(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t time) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; struct wlr_event_tablet_pad_strip evt = { .time_msec = time, @@ -193,7 +183,7 @@ static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = static void handle_tablet_pad_group_buttons(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct wl_array *buttons) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; free(group->group.buttons); group->group.buttons = calloc(1, buttons->size); @@ -208,7 +198,7 @@ static void handle_tablet_pad_group_buttons(void *data, static void handle_tablet_pad_group_modes(void *data, struct zwp_tablet_pad_group_v2 *pad_group, uint32_t modes) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; group->group.mode_count = modes; } @@ -216,9 +206,9 @@ static void handle_tablet_pad_group_modes(void *data, static void handle_tablet_pad_group_ring(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_ring_v2 *ring) { - struct wlr_wl_tablet_pad_group *group = data; - struct wlr_wl_tablet_pad_ring *tablet_ring = - calloc(1, sizeof(struct wlr_wl_tablet_pad_ring)); + struct tablet_pad_group *group = data; + struct tablet_pad_ring *tablet_ring = + calloc(1, sizeof(struct tablet_pad_ring)); if (!tablet_ring) { zwp_tablet_pad_ring_v2_destroy(ring); return; @@ -237,9 +227,9 @@ static void handle_tablet_pad_group_ring(void *data, static void handle_tablet_pad_group_strip(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_strip_v2 *strip) { - struct wlr_wl_tablet_pad_group *group = data; - struct wlr_wl_tablet_pad_strip *tablet_strip = - calloc(1, sizeof(struct wlr_wl_tablet_pad_strip)); + struct tablet_pad_group *group = data; + struct tablet_pad_strip *tablet_strip = + calloc(1, sizeof(struct tablet_pad_strip)); if (!tablet_strip) { zwp_tablet_pad_strip_v2_destroy(strip); return; @@ -263,25 +253,20 @@ static void handle_tablet_pad_group_done(void *data, static void handle_tablet_pad_group_mode_switch(void *data, struct zwp_tablet_pad_group_v2 *pad_group, uint32_t time, uint32_t serial, uint32_t mode) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; group->mode = mode; } -/* This isn't in the listener, but keep the naming scheme around since the - * other removed functions work like this, and pad sub-resources are just a bit - * special */ -static void handle_tablet_pad_group_removed( - struct wlr_wl_tablet_pad_group *group) { - +static void destroy_tablet_pad_group(struct tablet_pad_group *group) { /* No need to remove the ::link on strips rings as long as we do *not* * wl_list_remove on the wl_groups ring/strip attributes here */ - struct wlr_wl_tablet_pad_ring *ring, *tmp_ring; + struct tablet_pad_ring *ring, *tmp_ring; wl_list_for_each_safe(ring, tmp_ring, &group->rings, link) { zwp_tablet_pad_ring_v2_destroy(ring->ring); free(ring); } - struct wlr_wl_tablet_pad_strip *strip, *tmp_strip; + struct tablet_pad_strip *strip, *tmp_strip; wl_list_for_each_safe(strip, tmp_strip, &group->strips, link) { zwp_tablet_pad_strip_v2_destroy(strip->strip); free(strip); @@ -309,12 +294,13 @@ static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = static void handle_tablet_pad_group(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad, struct zwp_tablet_pad_group_v2 *pad_group) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *pad = dev->wlr_input_device.tablet_pad; + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *pad = &seat->wlr_tablet_pad; - struct wlr_wl_tablet_pad_group *group = - calloc(1, sizeof(struct wlr_wl_tablet_pad_group)); + struct tablet_pad_group *group = + calloc(1, sizeof(struct tablet_pad_group)); if (!group) { + wlr_log_errno(WLR_ERROR, "failed to allocate tablet_pad_group"); zwp_tablet_pad_group_v2_destroy(pad_group); return; } @@ -331,20 +317,18 @@ static void handle_tablet_pad_group(void *data, } static void handle_tablet_pad_path(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - const char *path) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, const char *path) { + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *)); *dst = strdup(path); } static void handle_tablet_pad_buttons(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t buttons) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t buttons) { + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; tablet_pad->button_count = buttons; } @@ -352,9 +336,7 @@ static void handle_tablet_pad_buttons(void *data, static void handle_tablet_pad_button(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t time, uint32_t button, uint32_t state) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - + struct wlr_wl_seat *seat = data; struct wlr_event_tablet_pad_button evt = { .time_msec = time, .button = button, @@ -363,28 +345,25 @@ static void handle_tablet_pad_button(void *data, .group = 0, }; - wlr_signal_emit_safe(&tablet_pad->events.button, &evt); + wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.button, &evt); } static void handle_tablet_pad_done(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { - struct wlr_wl_input_device *dev = data; - - wlr_signal_emit_safe(&dev->backend->backend.events.new_input, - &dev->wlr_input_device); + struct wlr_wl_seat *seat = data; + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_tablet_pad.base); } static void handle_tablet_pad_enter(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t serial, struct zwp_tablet_v2 *tablet_p, struct wl_surface *surface) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - struct wlr_wl_input_device *tab_dev = zwp_tablet_v2_get_user_data(tablet_p); - struct wlr_input_device *tablet = &tab_dev->wlr_input_device; - wlr_log(WLR_DEBUG, "Tablet: %p\n", tablet); + struct wlr_wl_seat *seat = data; + assert(seat->zwp_tablet_v2 == tablet_p); - wlr_signal_emit_safe(&tablet_pad->events.attach_tablet, tablet); + wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.attach_tablet, + &seat->wlr_tablet_tool); } static void handle_tablet_pad_leave(void *data, @@ -396,16 +375,17 @@ static void handle_tablet_pad_leave(void *data, static void handle_tablet_pad_removed(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - struct wlr_wl_tablet_pad_group *group, *it; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; + struct tablet_pad_group *group, *it; wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { - handle_tablet_pad_group_removed(group); + destroy_tablet_pad_group(group); } - zwp_tablet_pad_v2_destroy(dev->resource); - destroy_wl_input_device(dev); + wlr_tablet_pad_finish(tablet_pad); + zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2); + seat->zwp_tablet_pad_v2 = NULL; } static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { @@ -419,39 +399,25 @@ static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { .removed = handle_tablet_pad_removed, }; -const struct wlr_tablet_pad_impl tablet_pad_impl = { +const struct wlr_tablet_pad_impl wl_tablet_pad_impl = { .name = "wl-tablet-pad", }; static void handle_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_pad_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet pad"); + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { struct wlr_wl_seat *seat = data; - struct wlr_wl_input_device *dev = create_wl_input_device( - seat, WLR_INPUT_DEVICE_TABLET_PAD); - if (!dev) { - /* This leaks a couple of server-sent resource ids. iirc this - * shouldn't ever be a problem, but it isn't exactly nice - * either. */ - zwp_tablet_pad_v2_destroy(id); + if (seat->zwp_tablet_pad_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_pad_v2 is already present"); return; } - dev->resource = id; - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->tablet_pad = calloc(1, sizeof(*wlr_dev->tablet_pad)); + seat->zwp_tablet_pad_v2 = zwp_tablet_pad_v2; + zwp_tablet_pad_v2_add_listener(zwp_tablet_pad_v2, &tablet_pad_listener, + seat); - if (!wlr_dev->tablet_pad) { - /* This leaks a couple of server-sent resource ids. iirc this - * shouldn't ever be a problem, but it isn't exactly nice - * either. */ - free(dev); - zwp_tablet_pad_v2_destroy(id); - return; - } - wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, "wlr_tablet_v2"); - zwp_tablet_pad_v2_add_listener(id, &tablet_pad_listener, dev); + wlr_tablet_pad_init(&seat->wlr_tablet_pad, &wl_tablet_pad_impl, + "wlr_tablet_v2"); } static void handle_tablet_tool_done(void *data, @@ -459,7 +425,8 @@ static void handle_tablet_tool_done(void *data, /* empty */ } -static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2_type type) { +static enum wlr_tablet_tool_type tablet_type_to_wlr_type( + enum zwp_tablet_tool_v2_type type) { switch (type) { case ZWP_TABLET_TOOL_V2_TYPE_PEN: return WLR_TABLET_TOOL_TYPE_PEN; @@ -484,94 +451,85 @@ static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2 } static void handle_tablet_tool_type(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t tool_type) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.type = tablet_type_to_wlr_type(tool_type); + struct zwp_tablet_tool_v2 *id, uint32_t tool_type) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->type = tablet_type_to_wlr_type(tool_type); } static void handle_tablet_tool_serial(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t high, uint32_t low) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.hardware_serial = - ((uint64_t) high) << 32 | (uint64_t) low; + struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->hardware_serial = ((uint64_t) high) << 32 | (uint64_t) low; } static void handle_tablet_tool_id_wacom(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t high, uint32_t low) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.hardware_wacom = - ((uint64_t) high) << 32 | (uint64_t) low; + struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->hardware_wacom = ((uint64_t) high) << 32 | (uint64_t) low; } static void handle_tablet_tool_capability(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t capability) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t capability) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; - enum zwp_tablet_tool_v2_capability cap = capability; - - switch (cap) { + /* One event is sent for each capability */ + switch (capability) { case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: - tool->wlr_tool.tilt = true; + wlr_tool->tilt = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: - tool->wlr_tool.pressure = true; + wlr_tool->pressure = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: - tool->wlr_tool.distance = true; + wlr_tool->distance = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: - tool->wlr_tool.rotation = true; + wlr_tool->rotation = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: - tool->wlr_tool.slider = true; + wlr_tool->slider = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: - tool->wlr_tool.wheel = true; + wlr_tool->wheel = true; break; } } static void handle_tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *id, uint32_t serial, - struct zwp_tablet_v2 *tablet_id, - struct wl_surface *surface) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_v2 *tablet_id, struct wl_surface *surface) { + struct tablet_tool *tool = data; + assert(tablet_id == tool->seat->zwp_tablet_v2); + tool->is_in = true; - tool->tablet = zwp_tablet_v2_get_user_data(tablet_id); tool->output = wl_surface_get_user_data(surface); } static void handle_tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->is_out = true; tool->output = NULL; } -static void handle_tablet_tool_down(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *id, unsigned int serial) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->is_down = true; } -static void handle_tablet_tool_up(void *data, - struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; +static void handle_tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *id) { + struct tablet_tool *tool = data; tool->is_up = true; } -static void handle_tablet_tool_motion(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; struct wlr_wl_output *output = tool->output; assert(output); @@ -580,58 +538,53 @@ static void handle_tablet_tool_motion(void *data, } static void handle_tablet_tool_pressure(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t pressure) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t pressure) { + struct tablet_tool *tool = data; tool->pressure = (double) pressure / 65535.0; } static void handle_tablet_tool_distance(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t distance) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t distance) { + struct tablet_tool *tool = data; tool->distance = (double) distance / 65535.0; } -static void handle_tablet_tool_tilt(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->tilt_x = wl_fixed_to_double(x); tool->tilt_y = wl_fixed_to_double(y); } static void handle_tablet_tool_rotation(void *data, - struct zwp_tablet_tool_v2 *id, - wl_fixed_t rotation) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, wl_fixed_t rotation) { + struct tablet_tool *tool = data; tool->rotation = wl_fixed_to_double(rotation); } -static void handle_tablet_tool_slider(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *id, int slider) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->slider = (double) slider / 65535.0;; } // TODO: This looks wrong :/ -static void handle_tablet_tool_wheel(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t degree, int clicks) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->wheel_delta = wl_fixed_to_double(degree); } static void handle_tablet_tool_button(void *data, struct zwp_tablet_tool_v2 *id, uint32_t serial, uint32_t button, uint32_t state) { - struct wlr_wl_tablet_tool *tool = data; - struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + struct wlr_tablet *tablet = &seat->wlr_tablet; struct wlr_event_tablet_tool_button evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = get_current_time_msec(), .button = button, .state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED ? @@ -641,7 +594,7 @@ static void handle_tablet_tool_button(void *data, wlr_signal_emit_safe(&tablet->events.button, &evt); } -static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) { +static void clear_tablet_tool_values(struct tablet_tool *tool) { tool->is_out = tool->is_in = false; tool->is_up = tool->is_down = false; tool->x = tool->y = NAN; @@ -656,18 +609,20 @@ static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) { static void handle_tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *id, uint32_t time) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + if (tool->is_out && tool->is_in) { /* we got a tablet tool coming in and out of proximity before * we could process it. Just ignore anything it did */ goto clear_values; } - struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; + struct wlr_tablet *tablet = &seat->wlr_tablet; if (tool->is_in) { struct wlr_event_tablet_tool_proximity evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -679,8 +634,8 @@ static void handle_tablet_tool_frame(void *data, { struct wlr_event_tablet_tool_axis evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .updated_axes = 0, }; @@ -742,8 +697,8 @@ static void handle_tablet_tool_frame(void *data, * need to generate the time */ if (tool->is_down) { struct wlr_event_tablet_tool_tip evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -755,8 +710,8 @@ static void handle_tablet_tool_frame(void *data, if (tool->is_up) { struct wlr_event_tablet_tool_tip evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -768,8 +723,8 @@ static void handle_tablet_tool_frame(void *data, if (tool->is_out) { struct wlr_event_tablet_tool_proximity evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -785,10 +740,12 @@ clear_values: static void handle_tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + + zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2); + seat->zwp_tablet_tool_v2 = NULL; - zwp_tablet_tool_v2_destroy(tool->tool); - wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); free(tool); } @@ -818,23 +775,34 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { static void handle_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_tool_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet tool"); - struct wlr_wl_tablet_tool *tool = calloc(1, sizeof(*tool)); - if (!tool) { - zwp_tablet_tool_v2_destroy(id); + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { + struct wlr_wl_seat *seat = data; + if (seat->zwp_tablet_tool_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_tool_v2 already present"); return; } - tool->tool = id; + + wl_signal_init(&seat->wlr_tablet_tool.events.destroy); + + struct tablet_tool *tool = calloc(1, sizeof(struct tablet_tool)); + if (tool == NULL) { + wlr_log_errno(WLR_ERROR, "failed to allocate tablet_tool"); + zwp_tablet_tool_v2_destroy(zwp_tablet_tool_v2); + return; + } + + tool->seat = seat; clear_tablet_tool_values(tool); - wl_signal_init(&tool->wlr_tool.events.destroy); - zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listener, tool); + + seat->zwp_tablet_tool_v2 = zwp_tablet_tool_v2; + zwp_tablet_tool_v2_add_listener(seat->zwp_tablet_tool_v2, &tablet_tool_listener, + tool); } static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, const char *name) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet *tablet = dev->wlr_input_device.tablet; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; free(tablet->base.name); tablet->base.name = strdup(name); @@ -842,33 +810,36 @@ static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, uint32_t vid, uint32_t pid) { - struct wlr_wl_input_device *dev = data; - dev->wlr_input_device.vendor = vid; - dev->wlr_input_device.product = pid; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; + + tablet->base.vendor = vid; + tablet->base.product = pid; } static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, const char *path) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet *tablet = dev->wlr_input_device.tablet; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; char **dst = wl_array_add(&tablet->paths, sizeof(char *)); *dst = strdup(path); } static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - wlr_signal_emit_safe(&dev->backend->backend.events.new_input, - &dev->wlr_input_device); + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_tablet.base); } static void handle_tablet_removed(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - zwp_tablet_v2_destroy(dev->resource); - destroy_wl_input_device(dev); + wlr_tablet_finish(&seat->wlr_tablet); + zwp_tablet_v2_destroy(seat->zwp_tablet_v2); + seat->zwp_tablet_v2 = NULL; } static const struct zwp_tablet_v2_listener tablet_listener = { @@ -879,34 +850,23 @@ static const struct zwp_tablet_v2_listener tablet_listener = { .removed = handle_tablet_removed, }; -const struct wlr_tablet_impl tablet_impl = { +const struct wlr_tablet_impl wl_tablet_impl = { .name = "wl-tablet-tool", }; static void handle_tab_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet"); + struct zwp_tablet_v2 *zwp_tablet_v2) { struct wlr_wl_seat *seat = data; - struct wlr_wl_input_device *dev = create_wl_input_device( - seat, WLR_INPUT_DEVICE_TABLET_TOOL); - - if (!dev) { - zwp_tablet_v2_destroy(id); + if (seat->zwp_tablet_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_v2 already present"); return; } - dev->resource = id; - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->tablet = calloc(1, sizeof(*wlr_dev->tablet)); + seat->zwp_tablet_v2 = zwp_tablet_v2; + zwp_tablet_v2_add_listener(zwp_tablet_v2, &tablet_listener, seat); - if (!wlr_dev->tablet) { - zwp_tablet_v2_destroy(id); - return; - } - zwp_tablet_v2_set_user_data(id, wlr_dev->tablet); - wlr_tablet_init(wlr_dev->tablet, &tablet_impl, "wlr_tablet_v2"); - zwp_tablet_v2_add_listener(id, &tablet_listener, dev); + wlr_tablet_init(&seat->wlr_tablet, &wl_tablet_impl, "wlr_tablet_v2"); } static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { @@ -915,20 +875,55 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { .pad_added = handle_pad_added, }; -struct wlr_wl_tablet_seat *wl_add_tablet_seat( - struct zwp_tablet_manager_v2 *manager, - struct wlr_wl_seat *seat) { - struct wlr_wl_tablet_seat *ret = - calloc(1, sizeof(struct wlr_wl_tablet_seat)); +void init_seat_tablet(struct wlr_wl_seat *seat) { + struct zwp_tablet_manager_v2 *manager = seat->backend->tablet_manager; + assert(manager); - if (!(ret->tablet_seat = - zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat))) { - free(ret); - return NULL; + /** + * TODO: multi tablet support + * The wlr_wl_seat should support multiple tablet_v2 devices, but for + * the sake of simplicity, it supports only one device of each. + * If this is a feature you want/need, please open an issue on the wlroots + * tracker here https://gitlab.freedesktop.org/wlroots/wlroots/-/issues + */ + + seat->zwp_tablet_seat_v2 = + zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat); + if (seat->zwp_tablet_seat_v2 == NULL) { + wlr_log(WLR_ERROR, "failed to get zwp_tablet_manager_v2 from seat '%s'", + seat->name); + return; } - zwp_tablet_seat_v2_add_listener(ret->tablet_seat, + zwp_tablet_seat_v2_add_listener(seat->zwp_tablet_seat_v2, &tablet_seat_listener, seat); - - return ret; +} + +void finish_seat_tablet(struct wlr_wl_seat *seat) { + if (seat->zwp_tablet_v2 != NULL) { + wlr_tablet_finish(&seat->wlr_tablet); + zwp_tablet_v2_destroy(seat->zwp_tablet_v2); + } + + if (seat->zwp_tablet_tool_v2 != NULL) { + struct tablet_tool *tool = + zwp_tablet_tool_v2_get_user_data(seat->zwp_tablet_tool_v2); + free(tool); + + zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2); + } + + if (seat->zwp_tablet_pad_v2 != NULL) { + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; + struct tablet_pad_group *group, *it; + wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { + destroy_tablet_pad_group(group); + } + + wlr_tablet_pad_finish(tablet_pad); + zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2); + } + + zwp_tablet_seat_v2_destroy(seat->zwp_tablet_seat_v2); + seat->zwp_tablet_seat_v2 = NULL; } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index e07daa4ff..d683dfca2 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -132,6 +134,14 @@ struct wlr_wl_seat { struct wl_touch *wl_touch; struct wlr_touch wlr_touch; + struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2; + struct zwp_tablet_v2 *zwp_tablet_v2; + struct wlr_tablet wlr_tablet; + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2; + struct wlr_tablet_tool wlr_tablet_tool; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2; + struct wlr_tablet_pad wlr_tablet_pad; + struct wl_list link; // wlr_wl_backend.seats }; @@ -144,6 +154,9 @@ void init_seat_pointer(struct wlr_wl_seat *seat); void finish_seat_pointer(struct wlr_wl_seat *seat); void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); +void init_seat_tablet(struct wlr_wl_seat *seat); +void finish_seat_tablet(struct wlr_wl_seat *seat); + struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_seat *seat, enum wlr_input_device_type type); bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); @@ -154,11 +167,7 @@ void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; extern const struct wlr_pointer_impl wl_pointer_impl; -extern const struct wlr_tablet_pad_impl tablet_pad_impl; -extern const struct wlr_tablet_impl tablet_impl; - -struct wlr_wl_tablet_seat *wl_add_tablet_seat( - struct zwp_tablet_manager_v2 *manager, - struct wlr_wl_seat *seat); +extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl; +extern const struct wlr_tablet_impl wl_tablet_impl; #endif From b7e9ad7989a1525a581cfb7065c3f8d576de03da Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 15:15:32 -0500 Subject: [PATCH 045/298] backend/wayland: remove wlr_wl_input_device --- backend/wayland/backend.c | 6 --- backend/wayland/seat.c | 103 +------------------------------------- include/backend/wayland.h | 13 ----- 3 files changed, 1 insertion(+), 121 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 3428488e9..998757f5f 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -441,11 +441,6 @@ static void backend_destroy(struct wlr_backend *backend) { wlr_output_destroy(&output->wlr_output); } - struct wlr_wl_input_device *input_device, *tmp_input_device; - wl_list_for_each_safe(input_device, tmp_input_device, &wl->devices, link) { - destroy_wl_input_device(input_device); - } - struct wlr_wl_buffer *buffer, *tmp_buffer; wl_list_for_each_safe(buffer, tmp_buffer, &wl->buffers, link) { destroy_wl_buffer(buffer); @@ -538,7 +533,6 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, wlr_backend_init(&wl->backend, &backend_impl); wl->local_display = display; - wl_list_init(&wl->devices); wl_list_init(&wl->outputs); wl_list_init(&wl->seats); wl_list_init(&wl->buffers); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 854447ee1..768c40837 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -14,9 +14,9 @@ #include #include #include +#include #include -#include "interfaces/wlr_input_device.h" #include "backend/wayland.h" #include "util/signal.h" #include "util/time.h" @@ -222,12 +222,6 @@ static void init_seat_touch(struct wlr_wl_seat *seat) { &seat->wlr_touch.base); } -static struct wlr_wl_input_device *get_wl_input_device_from_input_device( - struct wlr_input_device *wlr_dev) { - assert(wlr_input_device_is_wl(wlr_dev)); - return (struct wlr_wl_input_device *)wlr_dev; -} - bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl) { struct wlr_wl_seat *seat = calloc(1, sizeof(struct wlr_wl_seat)); if (!seat) { @@ -268,13 +262,6 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { } } -static struct wlr_wl_seat *input_device_get_seat(struct wlr_input_device *wlr_dev) { - struct wlr_wl_input_device *dev = - get_wl_input_device_from_input_device(wlr_dev); - assert(dev->seat); - return dev->seat; -} - bool wlr_input_device_is_wl(struct wlr_input_device *dev) { switch (dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: @@ -292,90 +279,6 @@ bool wlr_input_device_is_wl(struct wlr_input_device *dev) { } } -struct wlr_wl_input_device *create_wl_input_device( - struct wlr_wl_seat *seat, enum wlr_input_device_type type) { - struct wlr_wl_input_device *dev = - calloc(1, sizeof(struct wlr_wl_input_device)); - if (dev == NULL) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - return NULL; - } - dev->backend = seat->backend; - dev->seat = seat; - - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - - const char *type_name = "unknown"; - - switch (type) { - case WLR_INPUT_DEVICE_KEYBOARD: - wlr_log(WLR_ERROR, "can't create keyboard wlr_wl_input_device"); - free(dev); - return NULL; - case WLR_INPUT_DEVICE_POINTER: - wlr_log(WLR_ERROR, "can't create pointer wlr_wl_input_device"); - free(dev); - return NULL; - case WLR_INPUT_DEVICE_TOUCH: - wlr_log(WLR_ERROR, "can't create touch wlr_wl_input_device"); - free(dev); - return NULL; - case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_log(WLR_ERROR, "can't create tablet tool wlr_wl_input_device"); - free(dev); - return NULL; - case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_log(WLR_ERROR, "can't create tablet pad wlr_wl_input_device"); - free(dev); - return NULL; - default: - wlr_log(WLR_ERROR, "device not handled"); - free(dev); - return NULL; - } - - size_t name_size = 8 + strlen(type_name) + strlen(seat->name) + 1; - char name[name_size]; - (void) snprintf(name, name_size, "wayland-%s-%s", type_name, seat->name); - - wlr_input_device_init(wlr_dev, type, name); - wl_list_insert(&seat->backend->devices, &dev->link); - return dev; -} - -void destroy_wl_input_device(struct wlr_wl_input_device *dev) { - /** - * TODO remove the redundant wlr_input_device from wlr_wl_input_device - * wlr_wl_input_device::wlr_input_device is not owned by its input device - * type, which means we have 2 wlr_input_device to cleanup - */ - wlr_input_device_finish(&dev->wlr_input_device); - if (dev->wlr_input_device._device) { - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - switch (wlr_dev->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - wlr_log(WLR_ERROR, "wlr_wl_input_device has no keyboard"); - break; - case WLR_INPUT_DEVICE_POINTER: - wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer"); - break; - case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet pad"); - break; - case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet_tool"); - break; - case WLR_INPUT_DEVICE_TOUCH: - wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch"); - break; - default: - break; - } - } - wl_list_remove(&dev->link); - free(dev); -} - static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { struct wlr_wl_seat *seat = data; @@ -437,7 +340,3 @@ const struct wl_seat_listener seat_listener = { .capabilities = seat_handle_capabilities, .name = seat_handle_name, }; - -struct wl_seat *wlr_wl_input_device_get_seat(struct wlr_input_device *wlr_dev) { - return input_device_get_seat(wlr_dev)->wl_seat; -} diff --git a/include/backend/wayland.h b/include/backend/wayland.h index d683dfca2..a6d565385 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -21,7 +21,6 @@ struct wlr_wl_backend { /* local state */ bool started; struct wl_display *local_display; - struct wl_list devices; struct wl_list outputs; int drm_fd; struct wl_list buffers; // wlr_wl_buffer.link @@ -89,15 +88,6 @@ struct wlr_wl_output { } cursor; }; -struct wlr_wl_input_device { - struct wlr_input_device wlr_input_device; - struct wl_list link; - - struct wlr_wl_backend *backend; - struct wlr_wl_seat *seat; - void *resource; -}; - struct wlr_wl_pointer { struct wlr_pointer wlr_pointer; @@ -157,11 +147,8 @@ void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); void init_seat_tablet(struct wlr_wl_seat *seat); void finish_seat_tablet(struct wlr_wl_seat *seat); -struct wlr_wl_input_device *create_wl_input_device( - struct wlr_wl_seat *seat, enum wlr_input_device_type type); bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); void destroy_wl_seats(struct wlr_wl_backend *wl); -void destroy_wl_input_device(struct wlr_wl_input_device *dev); void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; From 2001441a370f673e8a46a1c172c5fc48df106750 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 15:20:56 -0500 Subject: [PATCH 046/298] backend/wayland: remove wl_seat_listener from public API --- backend/wayland/seat.c | 4 +++- include/backend/wayland.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 768c40837..7d16d7d4d 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -222,6 +222,8 @@ static void init_seat_touch(struct wlr_wl_seat *seat) { &seat->wlr_touch.base); } +static const struct wl_seat_listener seat_listener; + bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl) { struct wlr_wl_seat *seat = calloc(1, sizeof(struct wlr_wl_seat)); if (!seat) { @@ -336,7 +338,7 @@ static void seat_handle_name(void *data, struct wl_seat *wl_seat, seat->name = strdup(name); } -const struct wl_seat_listener seat_listener = { +static const struct wl_seat_listener seat_listener = { .capabilities = seat_handle_capabilities, .name = seat_handle_name, }; diff --git a/include/backend/wayland.h b/include/backend/wayland.h index a6d565385..5baaac9d8 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -151,8 +151,6 @@ bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); void destroy_wl_seats(struct wlr_wl_backend *wl); void destroy_wl_buffer(struct wlr_wl_buffer *buffer); -extern const struct wl_seat_listener seat_listener; - extern const struct wlr_pointer_impl wl_pointer_impl; extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl; extern const struct wlr_tablet_impl wl_tablet_impl; From a92e5f8d4634a5d24c2fbab4a7fe0256558a96e6 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 16:45:03 -0500 Subject: [PATCH 047/298] types/wlr_input_device: move output_name field to wlr_pointer and wlr_touch --- backend/wayland/pointer.c | 3 +-- backend/wayland/seat.c | 7 +++++++ backend/x11/output.c | 4 ++-- include/wlr/types/wlr_input_device.h | 1 - include/wlr/types/wlr_pointer.h | 2 ++ include/wlr/types/wlr_touch.h | 2 ++ types/wlr_input_device.c | 1 - types/wlr_pointer.c | 2 ++ types/wlr_touch.c | 2 ++ 9 files changed, 18 insertions(+), 6 deletions(-) diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index 9d3131b99..2dc5d752e 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -440,8 +440,7 @@ void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { snprintf(name, sizeof(name), "wayland-pointer-%s", seat->name); wlr_pointer_init(&pointer->wlr_pointer, &wl_pointer_impl, name); - /* TODO: move output_name to pointer/touch */ - pointer->wlr_pointer.base.output_name = strdup(output->wlr_output.name); + pointer->wlr_pointer.output_name = strdup(output->wlr_output.name); pointer->seat = seat; pointer->output = output; diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 7d16d7d4d..33a7383c5 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -217,6 +217,13 @@ static void init_seat_touch(struct wlr_wl_seat *seat) { wlr_touch_init(&seat->wlr_touch, &touch_impl, name); + struct wlr_wl_output *output; + wl_list_for_each(output, &seat->backend->outputs, link) { + /* Multi-output touch not supproted */ + seat->wlr_touch.output_name = strdup(output->wlr_output.name); + break; + } + wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); wlr_signal_emit_safe(&seat->backend->backend.events.new_input, &seat->wlr_touch.base); diff --git a/backend/x11/output.c b/backend/x11/output.c index 1b51b629a..86e1dfd8e 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -574,10 +574,10 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { wlr_output_update_enabled(wlr_output, true); wlr_pointer_init(&output->pointer, &x11_pointer_impl, "x11-pointer"); - output->pointer.base.output_name = strdup(wlr_output->name); + output->pointer.output_name = strdup(wlr_output->name); wlr_touch_init(&output->touch, &x11_touch_impl, "x11-touch"); - output->touch.base.output_name = strdup(wlr_output->name); + output->touch.output_name = strdup(wlr_output->name); wl_list_init(&output->touchpoints); wlr_signal_emit_safe(&x11->backend.events.new_output, wlr_output); diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 0ca64341b..730912f71 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -31,7 +31,6 @@ struct wlr_input_device { char *name; // Or 0 if not applicable to this device double width_mm, height_mm; - char *output_name; /* wlr_input_device.type determines which of these is valid */ union { diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index a58507189..dc7611b80 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -21,6 +21,8 @@ struct wlr_pointer { const struct wlr_pointer_impl *impl; + char *output_name; + struct { struct wl_signal motion; // struct wlr_event_pointer_motion struct wl_signal motion_absolute; // struct wlr_event_pointer_motion_absolute diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index b2c097e8f..ed2f0033c 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -20,6 +20,8 @@ struct wlr_touch { const struct wlr_touch_impl *impl; + char *output_name; + struct { struct wl_signal down; // struct wlr_event_touch_down struct wl_signal up; // struct wlr_event_touch_up diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index d376582ed..d87935d85 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -25,5 +25,4 @@ void wlr_input_device_finish(struct wlr_input_device *wlr_device) { wl_list_remove(&wlr_device->events.destroy.listener_list); free(wlr_device->name); - free(wlr_device->output_name); } diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index 737d36ec6..09782cda8 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -29,4 +29,6 @@ void wlr_pointer_init(struct wlr_pointer *pointer, void wlr_pointer_finish(struct wlr_pointer *pointer) { wlr_input_device_finish(&pointer->base); + + free(pointer->output_name); } diff --git a/types/wlr_touch.c b/types/wlr_touch.c index 612efcda8..96d196d34 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -21,4 +21,6 @@ void wlr_touch_init(struct wlr_touch *touch, void wlr_touch_finish(struct wlr_touch *touch) { wlr_input_device_finish(&touch->base); + + free(touch->output_name); } From 96ccc50c5753346e852625fe37418a54386c7804 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Tue, 8 Mar 2022 16:54:28 -0500 Subject: [PATCH 048/298] types/wlr_input_device: move width_mm and height_mm fields to wlr_tablet and wlr_touch --- backend/libinput/tablet_tool.c | 3 +++ backend/libinput/touch.c | 3 +++ examples/tablet.c | 12 ++++++------ include/wlr/types/wlr_input_device.h | 2 -- include/wlr/types/wlr_tablet_tool.h | 2 ++ include/wlr/types/wlr_touch.h | 1 + 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index c778ccc21..0aa960ab1 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -25,6 +25,9 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) { wlr_tablet->base.vendor = libinput_device_get_id_vendor(dev->handle); wlr_tablet->base.product = libinput_device_get_id_product(dev->handle); + libinput_device_get_size(dev->handle, &wlr_tablet->width_mm, + &wlr_tablet->height_mm); + struct udev_device *udev = libinput_device_get_udev_device(dev->handle); char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *)); *dst = strdup(udev_device_get_syspath(udev)); diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 481a57874..fba3d5684 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -14,6 +14,9 @@ void init_device_touch(struct wlr_libinput_input_device *dev) { wlr_touch_init(wlr_touch, &libinput_touch_impl, name); wlr_touch->base.vendor = libinput_device_get_id_vendor(dev->handle); wlr_touch->base.product = libinput_device_get_id_product(dev->handle); + + libinput_device_get_size(dev->handle, &wlr_touch->width_mm, + &wlr_touch->height_mm); } struct wlr_libinput_input_device *device_from_touch( diff --git a/examples/tablet.c b/examples/tablet.c index 234bfb991..dd48983dd 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -320,11 +320,12 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wl_signal_add(&device->tablet_pad->events.ring, &pstate->ring); wl_list_insert(&sample->tablet_pads, &pstate->link); break; - case WLR_INPUT_DEVICE_TABLET_TOOL: - sample->width_mm = device->width_mm == 0 ? - 20 : device->width_mm; - sample->height_mm = device->height_mm == 0 ? - 10 : device->height_mm; + case WLR_INPUT_DEVICE_TABLET_TOOL:; + struct wlr_tablet *tablet = device->tablet; + sample->width_mm = tablet->width_mm == 0 ? + 20 : tablet->width_mm; + sample->height_mm = tablet->height_mm == 0 ? + 10 : tablet->height_mm; struct tablet_tool_state *tstate = calloc(sizeof(struct tablet_tool_state), 1); tstate->device = device; @@ -344,7 +345,6 @@ static void new_input_notify(struct wl_listener *listener, void *data) { } } - int main(int argc, char *argv[]) { wlr_log_init(WLR_DEBUG, NULL); struct wl_display *display = wl_display_create(); diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 730912f71..8c360aab7 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -29,8 +29,6 @@ struct wlr_input_device { enum wlr_input_device_type type; unsigned int vendor, product; char *name; - // Or 0 if not applicable to this device - double width_mm, height_mm; /* wlr_input_device.type determines which of these is valid */ union { diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index c7d612a33..2819bcc4b 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -64,6 +64,8 @@ struct wlr_tablet { const struct wlr_tablet_impl *impl; + double width_mm, height_mm; + struct { struct wl_signal axis; struct wl_signal proximity; diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index ed2f0033c..ac256e08a 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -21,6 +21,7 @@ struct wlr_touch { const struct wlr_touch_impl *impl; char *output_name; + double width_mm, height_mm; struct { struct wl_signal down; // struct wlr_event_touch_down From bd6c000d142fe6a8e893f1cdd2d5eb0b9d2ac7b8 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 14:52:27 -0500 Subject: [PATCH 049/298] types/wlr_pointer: uniformize events name --- backend/libinput/pointer.c | 48 ++++++++++---------- backend/wayland/pointer.c | 52 +++++++++++----------- backend/x11/input_device.c | 12 ++--- examples/multi-pointer.c | 9 ++-- examples/pointer.c | 14 +++--- include/wlr/types/wlr_pointer.h | 48 ++++++++++---------- include/wlr/types/wlr_virtual_pointer_v1.h | 2 +- tinywl/tinywl.c | 13 +++--- types/wlr_cursor.c | 22 ++++----- types/wlr_virtual_pointer_v1.c | 31 +++++-------- 10 files changed, 123 insertions(+), 128 deletions(-) diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 8daf20057..124a4fda3 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -29,8 +29,8 @@ void handle_pointer_motion(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); - struct wlr_event_pointer_motion wlr_event = { 0 }; - wlr_event.device = &pointer->base; + struct wlr_pointer_motion_event wlr_event = { 0 }; + wlr_event.pointer = pointer; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.delta_x = libinput_event_pointer_get_dx(pevent); @@ -45,8 +45,8 @@ void handle_pointer_motion_abs(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); - struct wlr_event_pointer_motion_absolute wlr_event = { 0 }; - wlr_event.device = &pointer->base; + struct wlr_pointer_motion_absolute_event wlr_event = { 0 }; + wlr_event.pointer = pointer; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1); @@ -59,8 +59,8 @@ void handle_pointer_button(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); - struct wlr_event_pointer_button wlr_event = { 0 }; - wlr_event.device = &pointer->base; + struct wlr_pointer_button_event wlr_event = { 0 }; + wlr_event.pointer = pointer; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.button = libinput_event_pointer_get_button(pevent); @@ -80,8 +80,8 @@ void handle_pointer_axis(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_pointer *pevent = libinput_event_get_pointer_event(event); - struct wlr_event_pointer_axis wlr_event = { 0 }; - wlr_event.device = &pointer->base; + struct wlr_pointer_axis_event wlr_event = { 0 }; + wlr_event.pointer = pointer; wlr_event.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); switch (libinput_event_pointer_get_axis_source(pevent)) { @@ -126,8 +126,8 @@ void handle_pointer_swipe_begin(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_swipe_begin wlr_event = { - .device = &pointer->base, + struct wlr_pointer_swipe_begin_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -139,8 +139,8 @@ void handle_pointer_swipe_update(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_swipe_update wlr_event = { - .device = &pointer->base, + struct wlr_pointer_swipe_update_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -154,8 +154,8 @@ void handle_pointer_swipe_end(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_swipe_end wlr_event = { - .device = &pointer->base, + struct wlr_pointer_swipe_end_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), @@ -167,8 +167,8 @@ void handle_pointer_pinch_begin(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_pinch_begin wlr_event = { - .device = &pointer->base, + struct wlr_pointer_pinch_begin_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -180,8 +180,8 @@ void handle_pointer_pinch_update(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_pinch_update wlr_event = { - .device = &pointer->base, + struct wlr_pointer_pinch_update_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -197,8 +197,8 @@ void handle_pointer_pinch_end(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_pinch_end wlr_event = { - .device = &pointer->base, + struct wlr_pointer_pinch_end_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), @@ -210,8 +210,8 @@ void handle_pointer_hold_begin(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_hold_begin wlr_event = { - .device = &pointer->base, + struct wlr_pointer_hold_begin_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), @@ -223,8 +223,8 @@ void handle_pointer_hold_end(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = libinput_event_get_gesture_event(event); - struct wlr_event_pointer_hold_end wlr_event = { - .device = &pointer->base, + struct wlr_pointer_hold_end_event wlr_event = { + .pointer = pointer, .time_msec = usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index 2dc5d752e..b2ed2ae75 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -88,8 +88,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, } struct wlr_output *wlr_output = &pointer->output->wlr_output; - struct wlr_event_pointer_motion_absolute event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_motion_absolute_event event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .x = wl_fixed_to_double(sx) / wlr_output->width, .y = wl_fixed_to_double(sy) / wlr_output->height, @@ -105,8 +105,8 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, return; } - struct wlr_event_pointer_button event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_button_event event = { + .pointer = &pointer->wlr_pointer, .button = button, .state = state, .time_msec = time, @@ -122,8 +122,8 @@ static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, return; } - struct wlr_event_pointer_axis event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_axis_event event = { + .pointer = &pointer->wlr_pointer, .delta = wl_fixed_to_double(value), .delta_discrete = pointer->axis_discrete, .orientation = axis, @@ -165,8 +165,8 @@ static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, return; } - struct wlr_event_pointer_axis event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_axis_event event = { + .pointer = &pointer->wlr_pointer, .delta = 0, .delta_discrete = 0, .orientation = axis, @@ -211,8 +211,8 @@ static void gesture_swipe_begin(void *data, pointer->fingers = fingers; - struct wlr_event_pointer_swipe_begin wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_swipe_begin_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .fingers = fingers, }; @@ -228,8 +228,8 @@ static void gesture_swipe_update(void *data, return; } - struct wlr_event_pointer_swipe_update wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_swipe_update_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .fingers = pointer->fingers, .dx = wl_fixed_to_double(dx), @@ -247,8 +247,8 @@ static void gesture_swipe_end(void *data, return; } - struct wlr_event_pointer_swipe_end wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_swipe_end_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .cancelled = cancelled, }; @@ -273,8 +273,8 @@ static void gesture_pinch_begin(void *data, pointer->fingers = fingers; - struct wlr_event_pointer_pinch_begin wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_pinch_begin_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .fingers = pointer->fingers, }; @@ -292,8 +292,8 @@ static void gesture_pinch_update(void *data, return; } - struct wlr_event_pointer_pinch_update wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_pinch_update_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .fingers = pointer->fingers, .dx = wl_fixed_to_double(dx), @@ -313,8 +313,8 @@ static void gesture_pinch_end(void *data, return; } - struct wlr_event_pointer_pinch_end wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_pinch_end_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .cancelled = cancelled, }; @@ -339,8 +339,8 @@ static void gesture_hold_begin(void *data, pointer->fingers = fingers; - struct wlr_event_pointer_hold_begin wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_hold_begin_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .fingers = fingers, }; @@ -356,8 +356,8 @@ static void gesture_hold_end(void *data, return; } - struct wlr_event_pointer_hold_end wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_hold_end_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = time, .cancelled = cancelled, }; @@ -381,8 +381,8 @@ static void relative_pointer_handle_relative_motion(void *data, uint64_t time_usec = (uint64_t)utime_hi << 32 | utime_lo; - struct wlr_event_pointer_motion wlr_event = { - .device = &pointer->wlr_pointer.base, + struct wlr_pointer_motion_event wlr_event = { + .pointer = &pointer->wlr_pointer, .time_msec = (uint32_t)(time_usec / 1000), .delta_x = wl_fixed_to_double(dx), .delta_y = wl_fixed_to_double(dy), diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 77edf8ad3..f9675fe01 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -31,8 +31,8 @@ static void send_key_event(struct wlr_x11_backend *x11, uint32_t key, static void send_button_event(struct wlr_x11_output *output, uint32_t key, enum wlr_button_state st, xcb_timestamp_t time) { - struct wlr_event_pointer_button ev = { - .device = &output->pointer.base, + struct wlr_pointer_button_event ev = { + .pointer = &output->pointer, .time_msec = time, .button = key, .state = st, @@ -43,8 +43,8 @@ static void send_button_event(struct wlr_x11_output *output, uint32_t key, static void send_axis_event(struct wlr_x11_output *output, int32_t delta, xcb_timestamp_t time) { - struct wlr_event_pointer_axis ev = { - .device = &output->pointer.base, + struct wlr_pointer_axis_event ev = { + .pointer = &output->pointer, .time_msec = time, .source = WLR_AXIS_SOURCE_WHEEL, .orientation = WLR_AXIS_ORIENTATION_VERTICAL, @@ -58,8 +58,8 @@ static void send_axis_event(struct wlr_x11_output *output, int32_t delta, static void send_pointer_position_event(struct wlr_x11_output *output, int16_t x, int16_t y, xcb_timestamp_t time) { - struct wlr_event_pointer_motion_absolute ev = { - .device = &output->pointer.base, + struct wlr_pointer_motion_absolute_event ev = { + .pointer = &output->pointer, .time_msec = time, .x = (double)x / output->wlr_output.width, .y = (double)y / output->wlr_output.height, diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index 5095cb729..d44df2a1e 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -109,8 +109,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sample_cursor *cursor = wl_container_of(listener, cursor, cursor_motion); - struct wlr_event_pointer_motion *event = data; - wlr_cursor_move(cursor->cursor, event->device, event->delta_x, + struct wlr_pointer_motion_event *event = data; + wlr_cursor_move(cursor->cursor, &event->pointer->base, event->delta_x, event->delta_y); } @@ -118,8 +118,9 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, void *data) { struct sample_cursor *cursor = wl_container_of(listener, cursor, cursor_motion_absolute); - struct wlr_event_pointer_motion_absolute *event = data; - wlr_cursor_warp_absolute(cursor->cursor, event->device, event->x, event->y); + struct wlr_pointer_motion_absolute_event *event = data; + wlr_cursor_warp_absolute(cursor->cursor, &event->pointer->base, event->x, + event->y); } static void cursor_destroy(struct sample_cursor *cursor) { diff --git a/examples/pointer.c b/examples/pointer.c index bf3701a45..af14178cb 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -112,8 +112,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { static void handle_cursor_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_motion); - struct wlr_event_pointer_motion *event = data; - wlr_cursor_move(sample->cursor, event->device, event->delta_x, + struct wlr_pointer_motion_event *event = data; + wlr_cursor_move(sample->cursor, &event->pointer->base, event->delta_x, event->delta_y); } @@ -121,19 +121,19 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_motion_absolute); - struct wlr_event_pointer_motion_absolute *event = data; + struct wlr_pointer_motion_absolute_event *event = data; sample->cur_x = event->x; sample->cur_y = event->y; - wlr_cursor_warp_absolute(sample->cursor, event->device, sample->cur_x, - sample->cur_y); + wlr_cursor_warp_absolute(sample->cursor, &event->pointer->base, + sample->cur_x, sample->cur_y); } static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_button); - struct wlr_event_pointer_button *event = data; + struct wlr_pointer_button_event *event = data; float (*color)[4]; if (event->state == WLR_BUTTON_RELEASED) { @@ -150,7 +150,7 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { static void handle_cursor_axis(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, cursor_axis); - struct wlr_event_pointer_axis *event = data; + struct wlr_pointer_axis_event *event = data; for (size_t i = 0; i < 3; ++i) { sample->default_color[i] += event->delta > 0 ? -0.05f : 0.05f; diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index dc7611b80..17ab258a9 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -45,22 +45,22 @@ struct wlr_pointer { void *data; }; -struct wlr_event_pointer_motion { - struct wlr_input_device *device; +struct wlr_pointer_motion_event { + struct wlr_pointer *pointer; uint32_t time_msec; double delta_x, delta_y; double unaccel_dx, unaccel_dy; }; -struct wlr_event_pointer_motion_absolute { - struct wlr_input_device *device; +struct wlr_pointer_motion_absolute_event { + struct wlr_pointer *pointer; uint32_t time_msec; // From 0..1 double x, y; }; -struct wlr_event_pointer_button { - struct wlr_input_device *device; +struct wlr_pointer_button_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t button; enum wlr_button_state state; @@ -78,8 +78,8 @@ enum wlr_axis_orientation { WLR_AXIS_ORIENTATION_HORIZONTAL, }; -struct wlr_event_pointer_axis { - struct wlr_input_device *device; +struct wlr_pointer_axis_event { + struct wlr_pointer *pointer; uint32_t time_msec; enum wlr_axis_source source; enum wlr_axis_orientation orientation; @@ -87,14 +87,14 @@ struct wlr_event_pointer_axis { int32_t delta_discrete; }; -struct wlr_event_pointer_swipe_begin { - struct wlr_input_device *device; +struct wlr_pointer_swipe_begin_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t fingers; }; -struct wlr_event_pointer_swipe_update { - struct wlr_input_device *device; +struct wlr_pointer_swipe_update_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t fingers; // Relative coordinates of the logical center of the gesture @@ -102,20 +102,20 @@ struct wlr_event_pointer_swipe_update { double dx, dy; }; -struct wlr_event_pointer_swipe_end { - struct wlr_input_device *device; +struct wlr_pointer_swipe_end_event { + struct wlr_pointer *pointer; uint32_t time_msec; bool cancelled; }; -struct wlr_event_pointer_pinch_begin { - struct wlr_input_device *device; +struct wlr_pointer_pinch_begin_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t fingers; }; -struct wlr_event_pointer_pinch_update { - struct wlr_input_device *device; +struct wlr_pointer_pinch_update_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t fingers; // Relative coordinates of the logical center of the gesture @@ -127,20 +127,20 @@ struct wlr_event_pointer_pinch_update { double rotation; }; -struct wlr_event_pointer_pinch_end { - struct wlr_input_device *device; +struct wlr_pointer_pinch_end_event { + struct wlr_pointer *pointer; uint32_t time_msec; bool cancelled; }; -struct wlr_event_pointer_hold_begin { - struct wlr_input_device *device; +struct wlr_pointer_hold_begin_event { + struct wlr_pointer *pointer; uint32_t time_msec; uint32_t fingers; }; -struct wlr_event_pointer_hold_end { - struct wlr_input_device *device; +struct wlr_pointer_hold_end_event { + struct wlr_pointer *pointer; uint32_t time_msec; bool cancelled; }; diff --git a/include/wlr/types/wlr_virtual_pointer_v1.h b/include/wlr/types/wlr_virtual_pointer_v1.h index 656ca371f..954103e1a 100644 --- a/include/wlr/types/wlr_virtual_pointer_v1.h +++ b/include/wlr/types/wlr_virtual_pointer_v1.h @@ -30,7 +30,7 @@ struct wlr_virtual_pointer_v1 { struct wlr_pointer pointer; struct wl_resource *resource; /* Vertical and horizontal */ - struct wlr_event_pointer_axis axis_event[2]; + struct wlr_pointer_axis_event axis_event[2]; enum wl_pointer_axis axis; bool axis_valid[2]; diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index e21d47347..fae16ac01 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -458,13 +458,13 @@ static void server_cursor_motion(struct wl_listener *listener, void *data) { * pointer motion event (i.e. a delta) */ struct tinywl_server *server = wl_container_of(listener, server, cursor_motion); - struct wlr_event_pointer_motion *event = data; + struct wlr_pointer_motion_event *event = data; /* The cursor doesn't move unless we tell it to. The cursor automatically * handles constraining the motion to the output layout, as well as any * special configuration applied for the specific input device which * generated the event. You can pass NULL for the device if you want to move * the cursor around without any input. */ - wlr_cursor_move(server->cursor, event->device, + wlr_cursor_move(server->cursor, &event->pointer->base, event->delta_x, event->delta_y); process_cursor_motion(server, event->time_msec); } @@ -479,8 +479,9 @@ static void server_cursor_motion_absolute( * emits these events. */ struct tinywl_server *server = wl_container_of(listener, server, cursor_motion_absolute); - struct wlr_event_pointer_motion_absolute *event = data; - wlr_cursor_warp_absolute(server->cursor, event->device, event->x, event->y); + struct wlr_pointer_motion_absolute_event *event = data; + wlr_cursor_warp_absolute(server->cursor, &event->pointer->base, event->x, + event->y); process_cursor_motion(server, event->time_msec); } @@ -489,7 +490,7 @@ static void server_cursor_button(struct wl_listener *listener, void *data) { * event. */ struct tinywl_server *server = wl_container_of(listener, server, cursor_button); - struct wlr_event_pointer_button *event = data; + struct wlr_pointer_button_event *event = data; /* Notify the client with pointer focus that a button press has occurred */ wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state); @@ -511,7 +512,7 @@ static void server_cursor_axis(struct wl_listener *listener, void *data) { * for example when you move the scroll wheel. */ struct tinywl_server *server = wl_container_of(listener, server, cursor_axis); - struct wlr_event_pointer_axis *event = data; + struct wlr_pointer_axis_event *event = data; /* Notify the client with pointer focus of the axis event. */ wlr_seat_pointer_notify_axis(server->seat, event->time_msec, event->orientation, event->delta, diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 3160ca03b..aabc1f9eb 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -431,7 +431,7 @@ static struct wlr_output *get_mapped_output(struct wlr_cursor_device *cursor_dev static void handle_pointer_motion_absolute(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_motion_absolute *event = data; + struct wlr_pointer_motion_absolute_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, motion_absolute); @@ -444,14 +444,14 @@ static void handle_pointer_motion_absolute(struct wl_listener *listener, } static void handle_pointer_button(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_button *event = data; + struct wlr_pointer_button_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, button); wlr_signal_emit_safe(&device->cursor->events.button, event); } static void handle_pointer_axis(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_axis *event = data; + struct wlr_pointer_axis_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, axis); wlr_signal_emit_safe(&device->cursor->events.axis, event); } @@ -462,49 +462,49 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) { } static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_swipe_begin *event = data; + struct wlr_pointer_swipe_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_begin); wlr_signal_emit_safe(&device->cursor->events.swipe_begin, event); } static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_swipe_update *event = data; + struct wlr_pointer_swipe_update_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_update); wlr_signal_emit_safe(&device->cursor->events.swipe_update, event); } static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_swipe_end *event = data; + struct wlr_pointer_swipe_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_end); wlr_signal_emit_safe(&device->cursor->events.swipe_end, event); } static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_pinch_begin *event = data; + struct wlr_pointer_pinch_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_begin); wlr_signal_emit_safe(&device->cursor->events.pinch_begin, event); } static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_pinch_update *event = data; + struct wlr_pointer_pinch_update_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_update); wlr_signal_emit_safe(&device->cursor->events.pinch_update, event); } static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_pinch_end *event = data; + struct wlr_pointer_pinch_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_end); wlr_signal_emit_safe(&device->cursor->events.pinch_end, event); } static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_hold_begin *event = data; + struct wlr_pointer_hold_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, hold_begin); wlr_signal_emit_safe(&device->cursor->events.hold_begin, event); } static void handle_pointer_hold_end(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_hold_end *event = data; + struct wlr_pointer_hold_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, hold_end); wlr_signal_emit_safe(&device->cursor->events.hold_end, event); } diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index 22aa903ec..931545afe 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -29,9 +29,8 @@ static void virtual_pointer_motion(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; - struct wlr_event_pointer_motion event = { - .device = wlr_dev, + struct wlr_pointer_motion_event event = { + .pointer = &pointer->pointer, .time_msec = time, .delta_x = wl_fixed_to_double(dx), .delta_y = wl_fixed_to_double(dy), @@ -52,14 +51,13 @@ static void virtual_pointer_motion_absolute(struct wl_client *client, if (x_extent == 0 || y_extent == 0) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; - struct wlr_event_pointer_motion_absolute event = { - .device = wlr_dev, + struct wlr_pointer_motion_absolute_event event = { + .pointer = &pointer->pointer, .time_msec = time, .x = (double)x / x_extent, .y = (double)y / y_extent, }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.motion_absolute, &event); + wlr_signal_emit_safe(&pointer->pointer.events.motion_absolute, &event); } static void virtual_pointer_button(struct wl_client *client, @@ -70,14 +68,13 @@ static void virtual_pointer_button(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; - struct wlr_event_pointer_button event = { - .device = wlr_dev, + struct wlr_pointer_button_event event = { + .pointer = &pointer->pointer, .time_msec = time, .button = button, .state = state ? WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED }; - wlr_signal_emit_safe(&wlr_dev->pointer->events.button, &event); + wlr_signal_emit_safe(&pointer->pointer.events.button, &event); } static void virtual_pointer_axis(struct wl_client *client, @@ -94,10 +91,9 @@ static void virtual_pointer_axis(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; pointer->axis = axis; pointer->axis_valid[pointer->axis] = true; - pointer->axis_event[pointer->axis].device = wlr_dev; + pointer->axis_event[pointer->axis].pointer = &pointer->pointer; pointer->axis_event[pointer->axis].time_msec = time; pointer->axis_event[pointer->axis].orientation = axis; pointer->axis_event[pointer->axis].delta = wl_fixed_to_double(value); @@ -140,8 +136,7 @@ static void virtual_pointer_axis_source(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; - pointer->axis_event[pointer->axis].device = wlr_dev; + pointer->axis_event[pointer->axis].pointer = &pointer->pointer; pointer->axis_event[pointer->axis].source = source; } @@ -158,10 +153,9 @@ static void virtual_pointer_axis_stop(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; pointer->axis = axis; pointer->axis_valid[pointer->axis] = true; - pointer->axis_event[pointer->axis].device = wlr_dev; + pointer->axis_event[pointer->axis].pointer = &pointer->pointer; pointer->axis_event[pointer->axis].time_msec = time; pointer->axis_event[pointer->axis].orientation = axis; pointer->axis_event[pointer->axis].delta = 0; @@ -182,10 +176,9 @@ static void virtual_pointer_axis_discrete(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; pointer->axis = axis; pointer->axis_valid[pointer->axis] = true; - pointer->axis_event[pointer->axis].device = wlr_dev; + pointer->axis_event[pointer->axis].pointer = &pointer->pointer; pointer->axis_event[pointer->axis].time_msec = time; pointer->axis_event[pointer->axis].orientation = axis; pointer->axis_event[pointer->axis].delta = wl_fixed_to_double(value); From 9a17200446952f67b10b7801a272b6abdd1ae8b3 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 15:05:12 -0500 Subject: [PATCH 050/298] types/wlr_keyboard: uniformize events name --- backend/libinput/keyboard.c | 2 +- backend/wayland/seat.c | 6 +++--- backend/x11/input_device.c | 2 +- examples/multi-pointer.c | 2 +- examples/output-layout.c | 2 +- examples/pointer.c | 2 +- examples/quads.c | 2 +- examples/rotation.c | 2 +- examples/simple.c | 2 +- examples/tablet.c | 2 +- examples/touch.c | 2 +- include/types/wlr_keyboard.h | 2 +- include/wlr/interfaces/wlr_keyboard.h | 2 +- include/wlr/types/wlr_keyboard.h | 2 +- tinywl/tinywl.c | 2 +- types/wlr_keyboard.c | 6 +++--- types/wlr_keyboard_group.c | 4 ++-- types/wlr_virtual_keyboard_v1.c | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/backend/libinput/keyboard.c b/backend/libinput/keyboard.c index 210fd4501..789260d54 100644 --- a/backend/libinput/keyboard.c +++ b/backend/libinput/keyboard.c @@ -36,7 +36,7 @@ void handle_keyboard_key(struct libinput_event *event, struct wlr_keyboard *kb) { struct libinput_event_keyboard *kbevent = libinput_event_get_keyboard_event(event); - struct wlr_event_keyboard_key wlr_event = { 0 }; + struct wlr_keyboard_key_event wlr_event = { 0 }; wlr_event.time_msec = usec_to_msec(libinput_event_keyboard_get_time_usec(kbevent)); wlr_event.keycode = libinput_event_keyboard_get_key(kbevent); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 33a7383c5..9659efc37 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -32,7 +32,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t *keycode_ptr; wl_array_for_each(keycode_ptr, keys) { - struct wlr_event_keyboard_key event = { + struct wlr_keyboard_key_event event = { .keycode = *keycode_ptr, .state = WL_KEYBOARD_KEY_STATE_PRESSED, .time_msec = get_current_time_msec(), @@ -54,7 +54,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, for (size_t i = 0; i < num_keycodes; ++i) { uint32_t keycode = pressed[i]; - struct wlr_event_keyboard_key event = { + struct wlr_keyboard_key_event event = { .keycode = keycode, .state = WL_KEYBOARD_KEY_STATE_RELEASED, .time_msec = get_current_time_msec(), @@ -68,7 +68,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { struct wlr_keyboard *keyboard = data; - struct wlr_event_keyboard_key wlr_event = { + struct wlr_keyboard_key_event wlr_event = { .keycode = key, .state = state, .time_msec = time, diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index f9675fe01..dac867f9d 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -20,7 +20,7 @@ static void send_key_event(struct wlr_x11_backend *x11, uint32_t key, enum wl_keyboard_key_state st, xcb_timestamp_t time) { - struct wlr_event_keyboard_key ev = { + struct wlr_keyboard_key_event ev = { .time_msec = time, .keycode = key, .state = st, diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index d44df2a1e..d6189f29f 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -185,7 +185,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/output-layout.c b/examples/output-layout.c index bc5cb7e90..a057ca78b 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -183,7 +183,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/pointer.c b/examples/pointer.c index af14178cb..d22047dee 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -228,7 +228,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->state; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/quads.c b/examples/quads.c index d74ef25e6..88c59f7c4 100644 --- a/examples/quads.c +++ b/examples/quads.c @@ -129,7 +129,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/rotation.c b/examples/rotation.c index cc1cfbb5b..a2e868af2 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -134,7 +134,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/simple.c b/examples/simple.c index 94f3abe0e..e46093be5 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -109,7 +109,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/tablet.c b/examples/tablet.c index dd48983dd..05fbc773c 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -261,7 +261,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/examples/touch.c b/examples/touch.c index ae2dcf8fc..5984c500b 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -172,7 +172,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct sample_state *sample = keyboard->sample; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, diff --git a/include/types/wlr_keyboard.h b/include/types/wlr_keyboard.h index edcfec49b..7cd26e8a5 100644 --- a/include/types/wlr_keyboard.h +++ b/include/types/wlr_keyboard.h @@ -1,7 +1,7 @@ #include void keyboard_key_update(struct wlr_keyboard *keyboard, - struct wlr_event_keyboard_key *event); + struct wlr_keyboard_key_event *event); bool keyboard_modifier_update(struct wlr_keyboard *keyboard); diff --git a/include/wlr/interfaces/wlr_keyboard.h b/include/wlr/interfaces/wlr_keyboard.h index 3f4c42552..06b079891 100644 --- a/include/wlr/interfaces/wlr_keyboard.h +++ b/include/wlr/interfaces/wlr_keyboard.h @@ -26,7 +26,7 @@ void wlr_keyboard_init(struct wlr_keyboard *keyboard, void wlr_keyboard_finish(struct wlr_keyboard *keyboard); void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, - struct wlr_event_keyboard_key *event); + struct wlr_keyboard_key_event *event); void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group); diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index 063d6e3f6..d8415933f 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -94,7 +94,7 @@ struct wlr_keyboard { void *data; }; -struct wlr_event_keyboard_key { +struct wlr_keyboard_key_event { uint32_t time_msec; uint32_t keycode; bool update_state; // if backend doesn't update modifiers on its own diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index fae16ac01..da965c4c0 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -188,7 +188,7 @@ static void keyboard_handle_key( struct tinywl_keyboard *keyboard = wl_container_of(listener, keyboard, key); struct tinywl_server *server = keyboard->server; - struct wlr_event_keyboard_key *event = data; + struct wlr_keyboard_key_event *event = data; struct wlr_seat *seat = server->seat; /* Translate libinput keycode -> xkbcommon */ diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 52d9a06d7..df99e8ba9 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -61,7 +61,7 @@ bool keyboard_modifier_update(struct wlr_keyboard *keyboard) { } void keyboard_key_update(struct wlr_keyboard *keyboard, - struct wlr_event_keyboard_key *event) { + struct wlr_keyboard_key_event *event) { if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { set_add(keyboard->keycodes, &keyboard->num_keycodes, WLR_KEYBOARD_KEYS_CAP, event->keycode); @@ -92,7 +92,7 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, } void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, - struct wlr_event_keyboard_key *event) { + struct wlr_keyboard_key_event *event) { keyboard_key_update(keyboard, event); wlr_signal_emit_safe(&keyboard->events.key, event); @@ -137,7 +137,7 @@ void wlr_keyboard_finish(struct wlr_keyboard *kb) { size_t orig_num_keycodes = kb->num_keycodes; for (size_t i = 0; i < orig_num_keycodes; ++i) { assert(kb->num_keycodes == orig_num_keycodes - i); - struct wlr_event_keyboard_key event = { + struct wlr_keyboard_key_event event = { .time_msec = get_current_time_msec(), .keycode = kb->keycodes[orig_num_keycodes - i - 1], .update_state = false, diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c index 7f575810e..5261c1416 100644 --- a/types/wlr_keyboard_group.c +++ b/types/wlr_keyboard_group.c @@ -69,7 +69,7 @@ struct wlr_keyboard_group *wlr_keyboard_group_from_wlr_keyboard( } static bool process_key(struct keyboard_group_device *group_device, - struct wlr_event_keyboard_key *event) { + struct wlr_keyboard_key_event *event) { struct wlr_keyboard_group *group = group_device->keyboard->group; struct keyboard_group_key *key, *tmp; @@ -188,7 +188,7 @@ static void refresh_state(struct keyboard_group_device *device, for (size_t i = 0; i < device->keyboard->num_keycodes; i++) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - struct wlr_event_keyboard_key event = { + struct wlr_keyboard_key_event event = { .time_msec = (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000, .keycode = device->keyboard->keycodes[i], .update_state = true, diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 01f7d6dc2..791557dbc 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -78,7 +78,7 @@ static void virtual_keyboard_key(struct wl_client *client, "Cannot send a keypress before defining a keymap"); return; } - struct wlr_event_keyboard_key event = { + struct wlr_keyboard_key_event event = { .time_msec = time, .keycode = key, .update_state = false, From 13d7fa2f03452ef5b1f34cdf7847476052532178 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 15:08:20 -0500 Subject: [PATCH 051/298] types/wlr_switch: uniformize events name --- backend/libinput/switch.c | 3 +-- include/wlr/types/wlr_switch.h | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/backend/libinput/switch.c b/backend/libinput/switch.c index 586ec0c80..2e89ed59a 100644 --- a/backend/libinput/switch.c +++ b/backend/libinput/switch.c @@ -29,8 +29,7 @@ void handle_switch_toggle(struct libinput_event *event, struct wlr_switch *wlr_switch) { struct libinput_event_switch *sevent = libinput_event_get_switch_event (event); - struct wlr_event_switch_toggle wlr_event = { 0 }; - wlr_event.device = &wlr_switch->base; + struct wlr_switch_toggle_event wlr_event = { 0 }; switch (libinput_event_switch_get_switch(sevent)) { case LIBINPUT_SWITCH_LID: wlr_event.switch_type = WLR_SWITCH_TYPE_LID; diff --git a/include/wlr/types/wlr_switch.h b/include/wlr/types/wlr_switch.h index 8e7230327..e26c9a3f0 100644 --- a/include/wlr/types/wlr_switch.h +++ b/include/wlr/types/wlr_switch.h @@ -28,17 +28,16 @@ struct wlr_switch { }; enum wlr_switch_type { - WLR_SWITCH_TYPE_LID = 1, + WLR_SWITCH_TYPE_LID, WLR_SWITCH_TYPE_TABLET_MODE, }; enum wlr_switch_state { WLR_SWITCH_STATE_OFF = 0, - WLR_SWITCH_STATE_ON + WLR_SWITCH_STATE_ON, }; -struct wlr_event_switch_toggle { - struct wlr_input_device *device; +struct wlr_switch_toggle_event { uint32_t time_msec; enum wlr_switch_type switch_type; enum wlr_switch_state switch_state; From d1f543a9d87f354e5ad8f942933dba3edb54ffed Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 15:16:04 -0500 Subject: [PATCH 052/298] types/wlr_tablet_pad: uniformize events name --- backend/libinput/tablet_pad.c | 6 +++--- backend/wayland/tablet_v2.c | 6 +++--- examples/tablet.c | 4 ++-- include/wlr/types/wlr_tablet_pad.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 87abd454a..083711ef0 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -145,7 +145,7 @@ void handle_tablet_pad_button(struct libinput_event *event, struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); - struct wlr_event_tablet_pad_button wlr_event = { 0 }; + struct wlr_tablet_pad_button_event wlr_event = { 0 }; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent)); wlr_event.button = libinput_event_tablet_pad_get_button_number(pevent); @@ -167,7 +167,7 @@ void handle_tablet_pad_ring(struct libinput_event *event, struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); - struct wlr_event_tablet_pad_ring wlr_event = { 0 }; + struct wlr_tablet_pad_ring_event wlr_event = { 0 }; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent)); wlr_event.ring = libinput_event_tablet_pad_get_ring_number(pevent); @@ -188,7 +188,7 @@ void handle_tablet_pad_strip(struct libinput_event *event, struct wlr_tablet_pad *tablet_pad) { struct libinput_event_tablet_pad *pevent = libinput_event_get_tablet_pad_event(event); - struct wlr_event_tablet_pad_strip wlr_event = { 0 }; + struct wlr_tablet_pad_strip_event wlr_event = { 0 }; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent)); wlr_event.strip = libinput_event_tablet_pad_get_strip_number(pevent); diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index 5666aa5f8..04ce23777 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -99,7 +99,7 @@ static void handle_tablet_pad_ring_frame(void *data, uint32_t time) { struct tablet_pad_ring *ring = data; - struct wlr_event_tablet_pad_ring evt = { + struct wlr_tablet_pad_ring_event evt = { .time_msec = time, .source = ring->source, .ring = ring->index, @@ -152,7 +152,7 @@ static void handle_tablet_pad_strip_frame(void *data, uint32_t time) { struct tablet_pad_strip *strip = data; - struct wlr_event_tablet_pad_strip evt = { + struct wlr_tablet_pad_strip_event evt = { .time_msec = time, .source = strip->source, .strip = strip->index, @@ -337,7 +337,7 @@ static void handle_tablet_pad_button(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t time, uint32_t button, uint32_t state) { struct wlr_wl_seat *seat = data; - struct wlr_event_tablet_pad_button evt = { + struct wlr_tablet_pad_button_event evt = { .time_msec = time, .button = button, .state = state, diff --git a/examples/tablet.c b/examples/tablet.c index 05fbc773c..9903bbf18 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -185,7 +185,7 @@ static void tablet_tool_button_notify(struct wl_listener *listener, void *data) static void tablet_pad_button_notify(struct wl_listener *listener, void *data) { struct tablet_pad_state *pstate = wl_container_of(listener, pstate, button); - struct wlr_event_tablet_pad_button *event = data; + struct wlr_tablet_pad_button_event *event = data; struct sample_state *sample = pstate->sample; float default_color[4] = { 0.5, 0.5, 0.5, 1.0 }; if (event->state == WLR_BUTTON_RELEASED) { @@ -203,7 +203,7 @@ static void tablet_pad_button_notify(struct wl_listener *listener, void *data) { static void tablet_pad_ring_notify(struct wl_listener *listener, void *data) { struct tablet_pad_state *pstate = wl_container_of(listener, pstate, ring); - struct wlr_event_tablet_pad_ring *event = data; + struct wlr_tablet_pad_ring_event *event = data; struct sample_state *sample = pstate->sample; if (event->position != -1) { sample->ring = -(event->position * (M_PI / 180.0)); diff --git a/include/wlr/types/wlr_tablet_pad.h b/include/wlr/types/wlr_tablet_pad.h index 249233537..64420f465 100644 --- a/include/wlr/types/wlr_tablet_pad.h +++ b/include/wlr/types/wlr_tablet_pad.h @@ -58,7 +58,7 @@ struct wlr_tablet_pad_group { unsigned int mode_count; }; -struct wlr_event_tablet_pad_button { +struct wlr_tablet_pad_button_event { uint32_t time_msec; uint32_t button; enum wlr_button_state state; @@ -71,7 +71,7 @@ enum wlr_tablet_pad_ring_source { WLR_TABLET_PAD_RING_SOURCE_FINGER, }; -struct wlr_event_tablet_pad_ring { +struct wlr_tablet_pad_ring_event { uint32_t time_msec; enum wlr_tablet_pad_ring_source source; uint32_t ring; @@ -84,7 +84,7 @@ enum wlr_tablet_pad_strip_source { WLR_TABLET_PAD_STRIP_SOURCE_FINGER, }; -struct wlr_event_tablet_pad_strip { +struct wlr_tablet_pad_strip_event { uint32_t time_msec; enum wlr_tablet_pad_strip_source source; uint32_t strip; From e732c5c8954900d06e042dac1b04cda9b93c2051 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 15:43:28 -0500 Subject: [PATCH 053/298] types/wlr_tablet_tool: uniformize events name --- backend/libinput/tablet_tool.c | 17 ++++++++--------- backend/wayland/tablet_v2.c | 24 ++++++++++++------------ examples/pointer.c | 6 +++--- examples/tablet.c | 6 +++--- include/wlr/types/wlr_tablet_tool.h | 20 ++++++++++---------- types/wlr_cursor.c | 8 ++++---- 6 files changed, 40 insertions(+), 41 deletions(-) diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index 0aa960ab1..31cd18b8c 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -130,9 +130,8 @@ void handle_tablet_tool_axis(struct libinput_event *event, struct tablet_tool *tool = get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - struct wlr_event_tablet_tool_axis wlr_event = { 0 }; - - wlr_event.device = &wlr_tablet->base; + struct wlr_tablet_tool_axis_event wlr_event = { 0 }; + wlr_event.tablet = wlr_tablet; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); @@ -185,9 +184,9 @@ void handle_tablet_tool_proximity(struct libinput_event *event, struct tablet_tool *tool = get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - struct wlr_event_tablet_tool_proximity wlr_event = { 0 }; + struct wlr_tablet_tool_proximity_event wlr_event = { 0 }; + wlr_event.tablet = wlr_tablet; wlr_event.tool = &tool->wlr_tool; - wlr_event.device = &wlr_tablet->base; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); wlr_event.x = libinput_event_tablet_tool_get_x_transformed(tevent, 1); @@ -227,8 +226,8 @@ void handle_tablet_tool_tip(struct libinput_event *event, struct tablet_tool *tool = get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - struct wlr_event_tablet_tool_tip wlr_event = { 0 }; - wlr_event.device = &wlr_tablet->base; + struct wlr_tablet_tool_tip_event wlr_event = { 0 }; + wlr_event.tablet = wlr_tablet; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); @@ -255,8 +254,8 @@ void handle_tablet_tool_button(struct libinput_event *event, struct tablet_tool *tool = get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent)); - struct wlr_event_tablet_tool_button wlr_event = { 0 }; - wlr_event.device = &wlr_tablet->base; + struct wlr_tablet_tool_button_event wlr_event = { 0 }; + wlr_event.tablet = wlr_tablet; wlr_event.tool = &tool->wlr_tool; wlr_event.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)); diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index 04ce23777..bedaabf20 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -582,8 +582,8 @@ static void handle_tablet_tool_button(void *data, struct wlr_wl_seat *seat = tool->seat; struct wlr_tablet *tablet = &seat->wlr_tablet; - struct wlr_event_tablet_tool_button evt = { - .device = &tablet->base, + struct wlr_tablet_tool_button_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = get_current_time_msec(), .button = button, @@ -620,8 +620,8 @@ static void handle_tablet_tool_frame(void *data, struct wlr_tablet *tablet = &seat->wlr_tablet; if (tool->is_in) { - struct wlr_event_tablet_tool_proximity evt = { - .device = &tablet->base, + struct wlr_tablet_tool_proximity_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, @@ -633,8 +633,8 @@ static void handle_tablet_tool_frame(void *data, } { - struct wlr_event_tablet_tool_axis evt = { - .device = &tablet->base, + struct wlr_tablet_tool_axis_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = time, .updated_axes = 0, @@ -696,8 +696,8 @@ static void handle_tablet_tool_frame(void *data, * Downside: Here we have the frame time, if we sent right away, we * need to generate the time */ if (tool->is_down) { - struct wlr_event_tablet_tool_tip evt = { - .device = &tablet->base, + struct wlr_tablet_tool_tip_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, @@ -709,8 +709,8 @@ static void handle_tablet_tool_frame(void *data, } if (tool->is_up) { - struct wlr_event_tablet_tool_tip evt = { - .device = &tablet->base, + struct wlr_tablet_tool_tip_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, @@ -722,8 +722,8 @@ static void handle_tablet_tool_frame(void *data, } if (tool->is_out) { - struct wlr_event_tablet_tool_proximity evt = { - .device = &tablet->base, + struct wlr_tablet_tool_proximity_event evt = { + .tablet = tablet, .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, diff --git a/examples/pointer.c b/examples/pointer.c index d22047dee..d1dab770a 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -217,11 +217,11 @@ static void handle_touch_cancel(struct wl_listener *listener, void *data) { static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, tablet_tool_axis); - struct wlr_event_tablet_tool_axis *event = data; + struct wlr_tablet_tool_axis_event *event = data; if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) && (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { - wlr_cursor_warp_absolute(sample->cursor, - event->device, event->x, event->y); + wlr_cursor_warp_absolute(sample->cursor, &event->tablet->base, + event->x, event->y); } } diff --git a/examples/tablet.c b/examples/tablet.c index 9903bbf18..35def7007 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -136,7 +136,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { static void tablet_tool_axis_notify(struct wl_listener *listener, void *data) { struct tablet_tool_state *tstate = wl_container_of(listener, tstate, axis); - struct wlr_event_tablet_tool_axis *event = data; + struct wlr_tablet_tool_axis_event *event = data; struct sample_state *sample = tstate->sample; if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) { sample->x = event->x; @@ -160,14 +160,14 @@ static void tablet_tool_axis_notify(struct wl_listener *listener, void *data) { static void tablet_tool_proximity_notify(struct wl_listener *listener, void *data) { struct tablet_tool_state *tstate = wl_container_of(listener, tstate, proximity); - struct wlr_event_tablet_tool_proximity *event = data; + struct wlr_tablet_tool_proximity_event *event = data; struct sample_state *sample = tstate->sample; sample->proximity = event->state == WLR_TABLET_TOOL_PROXIMITY_IN; } static void tablet_tool_button_notify(struct wl_listener *listener, void *data) { struct tablet_tool_state *tstate = wl_container_of(listener, tstate, button); - struct wlr_event_tablet_tool_button *event = data; + struct wlr_tablet_tool_button_event *event = data; struct sample_state *sample = tstate->sample; if (event->state == WLR_BUTTON_RELEASED) { sample->button = false; diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index 2819bcc4b..ec0fc42a8 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -90,8 +90,8 @@ enum wlr_tablet_tool_axes { WLR_TABLET_TOOL_AXIS_WHEEL = 1 << 8, }; -struct wlr_event_tablet_tool_axis { - struct wlr_input_device *device; +struct wlr_tablet_tool_axis_event { + struct wlr_tablet *tablet; struct wlr_tablet_tool *tool; uint32_t time_msec; @@ -113,8 +113,8 @@ enum wlr_tablet_tool_proximity_state { WLR_TABLET_TOOL_PROXIMITY_IN, }; -struct wlr_event_tablet_tool_proximity { - struct wlr_input_device *device; +struct wlr_tablet_tool_proximity_event { + struct wlr_tablet *tablet; struct wlr_tablet_tool *tool; uint32_t time_msec; // From 0..1 @@ -123,12 +123,12 @@ struct wlr_event_tablet_tool_proximity { }; enum wlr_tablet_tool_tip_state { - WLR_TABLET_TOOL_TIP_UP, - WLR_TABLET_TOOL_TIP_DOWN, + WLR_TABLET_TOOL_TIP_UP = 1 << 0, + WLR_TABLET_TOOL_TIP_DOWN = 1 << 1, }; -struct wlr_event_tablet_tool_tip { - struct wlr_input_device *device; +struct wlr_tablet_tool_tip_event { + struct wlr_tablet *tablet; struct wlr_tablet_tool *tool; uint32_t time_msec; // From 0..1 @@ -136,8 +136,8 @@ struct wlr_event_tablet_tool_tip { enum wlr_tablet_tool_tip_state state; }; -struct wlr_event_tablet_tool_button { - struct wlr_input_device *device; +struct wlr_tablet_tool_button_event { + struct wlr_tablet *tablet; struct wlr_tablet_tool *tool; uint32_t time_msec; uint32_t button; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index aabc1f9eb..b95509595 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -556,7 +556,7 @@ static void handle_touch_frame(struct wl_listener *listener, void *data) { } static void handle_tablet_tool_tip(struct wl_listener *listener, void *data) { - struct wlr_event_tablet_tool_tip *event = data; + struct wlr_tablet_tool_tip_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_tip); @@ -569,7 +569,7 @@ static void handle_tablet_tool_tip(struct wl_listener *listener, void *data) { } static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { - struct wlr_event_tablet_tool_axis *event = data; + struct wlr_tablet_tool_axis_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_axis); @@ -605,7 +605,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { static void handle_tablet_tool_button(struct wl_listener *listener, void *data) { - struct wlr_event_tablet_tool_button *event = data; + struct wlr_tablet_tool_button *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_button); wlr_signal_emit_safe(&device->cursor->events.tablet_tool_button, event); @@ -613,7 +613,7 @@ static void handle_tablet_tool_button(struct wl_listener *listener, static void handle_tablet_tool_proximity(struct wl_listener *listener, void *data) { - struct wlr_event_tablet_tool_proximity *event = data; + struct wlr_tablet_tool_proximity_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_proximity); From aaf787ee5650e77f0bda4dea8e3ba8325e0e6b39 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Wed, 9 Mar 2022 16:01:14 -0500 Subject: [PATCH 054/298] types/wlr_touch: uniformize events name --- backend/libinput/touch.c | 16 ++++++++-------- backend/wayland/seat.c | 23 +++++++++++++---------- backend/x11/input_device.c | 12 ++++++------ examples/pointer.c | 12 ++++++------ examples/touch.c | 6 +++--- include/wlr/types/wlr_touch.h | 16 ++++++++-------- types/wlr_cursor.c | 8 ++++---- 7 files changed, 48 insertions(+), 45 deletions(-) diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index fba3d5684..1475a03e8 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -32,8 +32,8 @@ void handle_touch_down(struct libinput_event *event, struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); - struct wlr_event_touch_down wlr_event = { 0 }; - wlr_event.device = &touch->base; + struct wlr_touch_down_event wlr_event = { 0 }; + wlr_event.touch = touch; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); @@ -46,8 +46,8 @@ void handle_touch_up(struct libinput_event *event, struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); - struct wlr_event_touch_up wlr_event = { 0 }; - wlr_event.device = &touch->base; + struct wlr_touch_up_event wlr_event = { 0 }; + wlr_event.touch = touch; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); @@ -58,8 +58,8 @@ void handle_touch_motion(struct libinput_event *event, struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); - struct wlr_event_touch_motion wlr_event = { 0 }; - wlr_event.device = &touch->base; + struct wlr_touch_motion_event wlr_event = { 0 }; + wlr_event.touch = touch; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); @@ -72,8 +72,8 @@ void handle_touch_cancel(struct libinput_event *event, struct wlr_touch *touch) { struct libinput_event_touch *tevent = libinput_event_get_touch_event(event); - struct wlr_event_touch_cancel wlr_event = { 0 }; - wlr_event.device = &touch->base; + struct wlr_touch_cancel_event wlr_event = { 0 }; + wlr_event.touch = touch; wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 9659efc37..261da909e 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -140,40 +140,43 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct wlr_wl_seat *seat = data; + struct wlr_touch *touch = &seat->wlr_touch; - struct wlr_event_touch_down event = { - .device = &seat->wlr_touch.base, + struct wlr_touch_down_event event = { + .touch = touch, .time_msec = time, .touch_id = id, }; touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); - wlr_signal_emit_safe(&seat->wlr_touch.events.down, &event); + wlr_signal_emit_safe(&touch->events.down, &event); } static void touch_handle_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) { struct wlr_wl_seat *seat = data; + struct wlr_touch *touch = &seat->wlr_touch; - struct wlr_event_touch_up event = { - .device = &seat->wlr_touch.base, + struct wlr_touch_up_event event = { + .touch = touch, .time_msec = time, .touch_id = id, }; - wlr_signal_emit_safe(&seat->wlr_touch.events.up, &event); + wlr_signal_emit_safe(&touch->events.up, &event); } static void touch_handle_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) { struct wlr_wl_seat *seat = data; - struct wlr_input_device *device = &seat->wlr_touch.base; + struct wlr_touch *touch = &seat->wlr_touch; - struct wlr_event_touch_motion event = { - .device = device, + struct wlr_touch_motion_event event = { + .touch = touch, .time_msec = time, .touch_id = id, }; + touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); - wlr_signal_emit_safe(&seat->wlr_touch.events.motion, &event); + wlr_signal_emit_safe(&touch->events.motion, &event); } static void touch_handle_frame(void *data, struct wl_touch *wl_touch) { diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index dac867f9d..d1f5c2c1f 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -70,8 +70,8 @@ static void send_pointer_position_event(struct wlr_x11_output *output, static void send_touch_down_event(struct wlr_x11_output *output, int16_t x, int16_t y, int32_t touch_id, xcb_timestamp_t time) { - struct wlr_event_touch_down ev = { - .device = &output->touch.base, + struct wlr_touch_down_event ev = { + .touch = &output->touch, .time_msec = time, .x = (double)x / output->wlr_output.width, .y = (double)y / output->wlr_output.height, @@ -83,8 +83,8 @@ static void send_touch_down_event(struct wlr_x11_output *output, static void send_touch_motion_event(struct wlr_x11_output *output, int16_t x, int16_t y, int32_t touch_id, xcb_timestamp_t time) { - struct wlr_event_touch_motion ev = { - .device = &output->touch.base, + struct wlr_touch_motion_event ev = { + .touch = &output->touch, .time_msec = time, .x = (double)x / output->wlr_output.width, .y = (double)y / output->wlr_output.height, @@ -96,8 +96,8 @@ static void send_touch_motion_event(struct wlr_x11_output *output, static void send_touch_up_event(struct wlr_x11_output *output, int32_t touch_id, xcb_timestamp_t time) { - struct wlr_event_touch_up ev = { - .device = &output->touch.base, + struct wlr_touch_up_event ev = { + .touch = &output->touch, .time_msec = time, .touch_id = touch_id, }; diff --git a/examples/pointer.c b/examples/pointer.c index d1dab770a..1197386e7 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -168,7 +168,7 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { static void handle_touch_up(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, touch_up); - struct wlr_event_touch_up *event = data; + struct wlr_touch_up_event *event = data; struct touch_point *point, *tmp; wl_list_for_each_safe(point, tmp, &sample->touch_points, link) { @@ -178,25 +178,25 @@ static void handle_touch_up(struct wl_listener *listener, void *data) { } } - warp_to_touch(sample, event->device); + warp_to_touch(sample, &event->touch->base); } static void handle_touch_down(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, touch_down); - struct wlr_event_touch_down *event = data; + struct wlr_touch_down_event *event = data; struct touch_point *point = calloc(1, sizeof(struct touch_point)); point->touch_id = event->touch_id; point->x = event->x; point->y = event->y; wl_list_insert(&sample->touch_points, &point->link); - warp_to_touch(sample, event->device); + warp_to_touch(sample, &event->touch->base); } static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sample_state *sample = wl_container_of(listener, sample, touch_motion); - struct wlr_event_touch_motion *event = data; + struct wlr_touch_motion_event *event = data; struct touch_point *point; wl_list_for_each(point, &sample->touch_points, link) { @@ -207,7 +207,7 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { } } - warp_to_touch(sample, event->device); + warp_to_touch(sample, &event->touch->base); } static void handle_touch_cancel(struct wl_listener *listener, void *data) { diff --git a/examples/touch.c b/examples/touch.c index 5984c500b..765b41aa8 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -93,7 +93,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } static void touch_down_notify(struct wl_listener *listener, void *data) { - struct wlr_event_touch_motion *event = data; + struct wlr_touch_motion_event *event = data; struct touch_state *tstate = wl_container_of(listener, tstate, down); struct sample_state *sample = tstate->sample; struct touch_point *point = calloc(1, sizeof(struct touch_point)); @@ -104,7 +104,7 @@ static void touch_down_notify(struct wl_listener *listener, void *data) { } static void touch_up_notify(struct wl_listener *listener, void *data ) { - struct wlr_event_touch_up *event = data; + struct wlr_touch_up_event *event = data; struct touch_state *tstate = wl_container_of(listener, tstate, up); struct sample_state *sample = tstate->sample; struct touch_point *point, *tmp; @@ -117,7 +117,7 @@ static void touch_up_notify(struct wl_listener *listener, void *data ) { } static void touch_motion_notify(struct wl_listener *listener, void *data) { - struct wlr_event_touch_motion *event = data; + struct wlr_touch_motion_event *event = data; struct touch_state *tstate = wl_container_of(listener, tstate, motion); struct sample_state *sample = tstate->sample; struct touch_point *point; diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index ac256e08a..0d2a27b6b 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -34,30 +34,30 @@ struct wlr_touch { void *data; }; -struct wlr_event_touch_down { - struct wlr_input_device *device; +struct wlr_touch_down_event { + struct wlr_touch *touch; uint32_t time_msec; int32_t touch_id; // From 0..1 double x, y; }; -struct wlr_event_touch_up { - struct wlr_input_device *device; +struct wlr_touch_up_event { + struct wlr_touch *touch; uint32_t time_msec; int32_t touch_id; }; -struct wlr_event_touch_motion { - struct wlr_input_device *device; +struct wlr_touch_motion_event { + struct wlr_touch *touch; uint32_t time_msec; int32_t touch_id; // From 0..1 double x, y; }; -struct wlr_event_touch_cancel { - struct wlr_input_device *device; +struct wlr_touch_cancel_event { + struct wlr_touch *touch; uint32_t time_msec; int32_t touch_id; }; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index b95509595..cd50e61e7 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -510,14 +510,14 @@ static void handle_pointer_hold_end(struct wl_listener *listener, void *data) { } static void handle_touch_up(struct wl_listener *listener, void *data) { - struct wlr_event_touch_up *event = data; + struct wlr_touch_up_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_up); wlr_signal_emit_safe(&device->cursor->events.touch_up, event); } static void handle_touch_down(struct wl_listener *listener, void *data) { - struct wlr_event_touch_down *event = data; + struct wlr_touch_down_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_down); @@ -530,7 +530,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { } static void handle_touch_motion(struct wl_listener *listener, void *data) { - struct wlr_event_touch_motion *event = data; + struct wlr_touch_motion_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_motion); @@ -543,7 +543,7 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { } static void handle_touch_cancel(struct wl_listener *listener, void *data) { - struct wlr_event_touch_cancel *event = data; + struct wlr_touch_cancel_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_cancel); wlr_signal_emit_safe(&device->cursor->events.touch_cancel, event); From 4cc2a03620b55113622379772c0b8890010fe7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 8 Mar 2022 12:26:59 +0100 Subject: [PATCH 055/298] layer-shell: Make wlr_layer_surface_v1_from_resource public This allows compositors to leverage the `wl_instance_of` based type check. --- include/wlr/types/wlr_layer_shell_v1.h | 7 +++++++ types/wlr_layer_shell_v1.c | 24 ++++++++++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/wlr/types/wlr_layer_shell_v1.h b/include/wlr/types/wlr_layer_shell_v1.h index 370fad837..fcb72f242 100644 --- a/include/wlr/types/wlr_layer_shell_v1.h +++ b/include/wlr/types/wlr_layer_shell_v1.h @@ -178,4 +178,11 @@ struct wlr_surface *wlr_layer_surface_v1_popup_surface_at( struct wlr_layer_surface_v1 *surface, double sx, double sy, double *sub_x, double *sub_y); +/** Get the corresponding wlr_layer_surface_v1 from a resource. + * + * Aborts if the resource doesn't have the correct type. + */ +struct wlr_layer_surface_v1 *wlr_layer_surface_v1_from_resource( + struct wl_resource *resource); + #endif diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index c8d3a1cb5..107dac631 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -28,7 +28,7 @@ static struct wlr_layer_shell_v1 *layer_shell_from_resource( return wl_resource_get_user_data(resource); } -static struct wlr_layer_surface_v1 *layer_surface_from_resource( +struct wlr_layer_surface_v1 *wlr_layer_surface_v1_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwlr_layer_surface_v1_interface, &layer_surface_implementation)); @@ -58,7 +58,8 @@ static void layer_surface_configure_destroy( static void layer_surface_handle_ack_configure(struct wl_client *client, struct wl_resource *resource, uint32_t serial) { - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = + wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -98,7 +99,8 @@ static void layer_surface_handle_ack_configure(struct wl_client *client, static void layer_surface_handle_set_size(struct wl_client *client, struct wl_resource *resource, uint32_t width, uint32_t height) { - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = + wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -127,7 +129,8 @@ static void layer_surface_handle_set_anchor(struct wl_client *client, ZWLR_LAYER_SURFACE_V1_ERROR_INVALID_ANCHOR, "invalid anchor %" PRIu32, anchor); } - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = + wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -144,7 +147,7 @@ static void layer_surface_handle_set_anchor(struct wl_client *client, static void layer_surface_handle_set_exclusive_zone(struct wl_client *client, struct wl_resource *resource, int32_t zone) { - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -162,7 +165,8 @@ static void layer_surface_handle_set_exclusive_zone(struct wl_client *client, static void layer_surface_handle_set_margin( struct wl_client *client, struct wl_resource *resource, int32_t top, int32_t right, int32_t bottom, int32_t left) { - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = + wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -186,7 +190,7 @@ static void layer_surface_handle_set_margin( static void layer_surface_handle_set_keyboard_interactivity( struct wl_client *client, struct wl_resource *resource, uint32_t interactive) { - struct wlr_layer_surface_v1 *surface = layer_surface_from_resource(resource); + struct wlr_layer_surface_v1 *surface = wlr_layer_surface_v1_from_resource(resource); if (!surface) { return; @@ -210,7 +214,7 @@ static void layer_surface_handle_get_popup(struct wl_client *client, struct wl_resource *layer_resource, struct wl_resource *popup_resource) { struct wlr_layer_surface_v1 *parent = - layer_surface_from_resource(layer_resource); + wlr_layer_surface_v1_from_resource(layer_resource); struct wlr_xdg_popup *popup = wlr_xdg_popup_from_resource(popup_resource); @@ -225,7 +229,7 @@ static void layer_surface_handle_get_popup(struct wl_client *client, static void layer_surface_set_layer(struct wl_client *client, struct wl_resource *surface_resource, uint32_t layer) { struct wlr_layer_surface_v1 *surface = - layer_surface_from_resource(surface_resource); + wlr_layer_surface_v1_from_resource(surface_resource); if (!surface) { return; } @@ -288,7 +292,7 @@ static void layer_surface_destroy(struct wlr_layer_surface_v1 *surface) { static void layer_surface_resource_destroy(struct wl_resource *resource) { struct wlr_layer_surface_v1 *surface = - layer_surface_from_resource(resource); + wlr_layer_surface_v1_from_resource(resource); if (surface != NULL) { layer_surface_destroy(surface); } From 4519117a6885736b26f2d8ff1af97886d184c155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 21 Mar 2022 17:37:17 -0600 Subject: [PATCH 056/298] seat: take wlr_keyboard in wlr_seat_set_keyboard() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Hernández Hernández --- include/wlr/types/wlr_seat.h | 2 +- tinywl/tinywl.c | 16 ++++++++-------- types/seat/wlr_seat_keyboard.c | 10 ++++------ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 41f3918b0..ebbcfd479 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -474,7 +474,7 @@ bool wlr_seat_pointer_has_grab(struct wlr_seat *seat); /** * Set this keyboard as the active keyboard for the seat. */ -void wlr_seat_set_keyboard(struct wlr_seat *seat, struct wlr_input_device *dev); +void wlr_seat_set_keyboard(struct wlr_seat *seat, struct wlr_keyboard *keyboard); /** * Get the active keyboard for the seat. diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index da965c4c0..290dd0942 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -91,7 +91,7 @@ struct tinywl_view { struct tinywl_keyboard { struct wl_list link; struct tinywl_server *server; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener modifiers; struct wl_listener key; @@ -149,10 +149,10 @@ static void keyboard_handle_modifiers( * same seat. You can swap out the underlying wlr_keyboard like this and * wlr_seat handles this transparently. */ - wlr_seat_set_keyboard(keyboard->server->seat, keyboard->device); + wlr_seat_set_keyboard(keyboard->server->seat, keyboard->wlr_keyboard); /* Send modifiers to the client. */ wlr_seat_keyboard_notify_modifiers(keyboard->server->seat, - &keyboard->device->keyboard->modifiers); + &keyboard->wlr_keyboard->modifiers); } static bool handle_keybinding(struct tinywl_server *server, xkb_keysym_t sym) { @@ -196,10 +196,10 @@ static void keyboard_handle_key( /* Get a list of keysyms based on the keymap for this keyboard */ const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms( - keyboard->device->keyboard->xkb_state, keycode, &syms); + keyboard->wlr_keyboard->xkb_state, keycode, &syms); bool handled = false; - uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard); + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr_keyboard); if ((modifiers & WLR_MODIFIER_ALT) && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { /* If alt is held down and this button was _pressed_, we attempt to @@ -211,7 +211,7 @@ static void keyboard_handle_key( if (!handled) { /* Otherwise, we pass it along to the client. */ - wlr_seat_set_keyboard(seat, keyboard->device); + wlr_seat_set_keyboard(seat, keyboard->wlr_keyboard); wlr_seat_keyboard_notify_key(seat, event->time_msec, event->keycode, event->state); } @@ -236,7 +236,7 @@ static void server_new_keyboard(struct tinywl_server *server, struct tinywl_keyboard *keyboard = calloc(1, sizeof(struct tinywl_keyboard)); keyboard->server = server; - keyboard->device = device; + keyboard->wlr_keyboard = device->keyboard; /* We need to prepare an XKB keymap and assign it to the keyboard. This * assumes the defaults (e.g. layout = "us"). */ @@ -257,7 +257,7 @@ static void server_new_keyboard(struct tinywl_server *server, keyboard->destroy.notify = keyboard_handle_destroy; wl_signal_add(&device->events.destroy, &keyboard->destroy); - wlr_seat_set_keyboard(server->seat, device); + wlr_seat_set_keyboard(server->seat, keyboard->wlr_keyboard); /* And add the keyboard to our list of keyboards */ wl_list_insert(&server->keyboards, &keyboard->link); diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c index 1bad8ff62..e1f137831 100644 --- a/types/seat/wlr_seat_keyboard.c +++ b/types/seat/wlr_seat_keyboard.c @@ -118,11 +118,10 @@ static void handle_keyboard_destroy(struct wl_listener *listener, void *data) { } void wlr_seat_set_keyboard(struct wlr_seat *seat, - struct wlr_input_device *device) { + struct wlr_keyboard *keyboard) { // TODO call this on device key event before the event reaches the // compositor and set a pending keyboard and then send the new keyboard // state on the next keyboard notify event. - struct wlr_keyboard *keyboard = (device ? device->keyboard : NULL); if (seat->keyboard_state.keyboard == keyboard) { return; } @@ -135,16 +134,15 @@ void wlr_seat_set_keyboard(struct wlr_seat *seat, } if (keyboard) { - assert(device->type == WLR_INPUT_DEVICE_KEYBOARD); seat->keyboard_state.keyboard = keyboard; - wl_signal_add(&device->events.destroy, + wl_signal_add(&keyboard->base.events.destroy, &seat->keyboard_state.keyboard_destroy); seat->keyboard_state.keyboard_destroy.notify = handle_keyboard_destroy; - wl_signal_add(&device->keyboard->events.keymap, + wl_signal_add(&keyboard->events.keymap, &seat->keyboard_state.keyboard_keymap); seat->keyboard_state.keyboard_keymap.notify = handle_keyboard_keymap; - wl_signal_add(&device->keyboard->events.repeat_info, + wl_signal_add(&keyboard->events.repeat_info, &seat->keyboard_state.keyboard_repeat_info); seat->keyboard_state.keyboard_repeat_info.notify = handle_keyboard_repeat_info; From dd03d839ab56c3e5d7c607a8d76e58e0b75edb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Fri, 25 Mar 2022 18:48:58 +0100 Subject: [PATCH 057/298] xdg-activation: Deduplicate token creation code There were three places initializing a token: - wlr_xdg_activation_v1_add_token - wlr_xdg_activation_token_v1_create - activation_handle_get_activation_token The initialization of the token.destroy was missing in the first one. To prevent these functions from getting out of sync move the token creation into a common function. Fixes 4c59f7d4 ("xdg-activation: Allow to submit tokens") --- types/wlr_xdg_activation_v1.c | 42 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/types/wlr_xdg_activation_v1.c b/types/wlr_xdg_activation_v1.c index 02ba9e07f..c54364ccc 100644 --- a/types/wlr_xdg_activation_v1.c +++ b/types/wlr_xdg_activation_v1.c @@ -248,15 +248,11 @@ static void activation_handle_destroy(struct wl_client *client, wl_resource_destroy(activation_resource); } -static void activation_handle_get_activation_token(struct wl_client *client, - struct wl_resource *activation_resource, uint32_t id) { - struct wlr_xdg_activation_v1 *activation = - activation_from_resource(activation_resource); - +static struct wlr_xdg_activation_token_v1 *activation_token_create( + struct wlr_xdg_activation_v1 *activation) { struct wlr_xdg_activation_token_v1 *token = calloc(1, sizeof(*token)); if (token == NULL) { - wl_client_post_no_memory(client); - return; + return NULL; } wl_list_init(&token->link); wl_list_init(&token->seat_destroy.link); @@ -265,6 +261,20 @@ static void activation_handle_get_activation_token(struct wl_client *client, token->activation = activation; + return token; +} + +static void activation_handle_get_activation_token(struct wl_client *client, + struct wl_resource *activation_resource, uint32_t id) { + struct wlr_xdg_activation_v1 *activation = + activation_from_resource(activation_resource); + + struct wlr_xdg_activation_token_v1 *token = activation_token_create(activation); + if (token == NULL) { + wl_client_post_no_memory(client); + return; + } + uint32_t version = wl_resource_get_version(activation_resource); token->resource = wl_resource_create(client, &xdg_activation_token_v1_interface, version, id); @@ -371,19 +381,12 @@ struct wlr_xdg_activation_v1 *wlr_xdg_activation_v1_create( struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_token_v1_create( struct wlr_xdg_activation_v1 *activation) { - struct wlr_xdg_activation_token_v1 *token = calloc(1, sizeof(*token)); + struct wlr_xdg_activation_token_v1 *token = activation_token_create(activation); + if (token == NULL) { return NULL; } - wl_list_init(&token->link); - // Currently no way to set seat/surface - wl_list_init(&token->seat_destroy.link); - wl_list_init(&token->surface_destroy.link); - wl_signal_init(&token->events.destroy); - - token->activation = activation; - if (!token_init(token)) { wlr_xdg_activation_token_v1_destroy(token); return NULL; @@ -412,15 +415,10 @@ struct wlr_xdg_activation_token_v1 *wlr_xdg_activation_v1_add_token( struct wlr_xdg_activation_v1 *activation, const char *token_str) { assert(token_str); - struct wlr_xdg_activation_token_v1 *token = calloc(1, sizeof(*token)); + struct wlr_xdg_activation_token_v1 *token = activation_token_create(activation); if (token == NULL) { return NULL; } - wl_list_init(&token->link); - wl_list_init(&token->seat_destroy.link); - wl_list_init(&token->surface_destroy.link); - - token->activation = activation; token->token = strdup(token_str); wl_list_insert(&activation->tokens, &token->link); From bb32349c9776b31861a6b68ddb5c0187f7223d2c Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 28 Mar 2022 18:08:40 +0200 Subject: [PATCH 058/298] meson: soversion arg should be string muon, a meson implementation in C, is more strict with its types and revealed this discrepancy between meson behavior and documentation. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f7fb659c4..554fbc42a 100644 --- a/meson.build +++ b/meson.build @@ -169,7 +169,7 @@ symbols_file = 'wlroots.syms' symbols_flag = '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(), symbols_file) lib_wlr = library( meson.project_name(), wlr_files, - soversion: soversion, + soversion: soversion.to_string(), dependencies: wlr_deps, include_directories: [wlr_inc, proto_inc], install: true, From 62fbf3f4ba1b2993e29dfb46f077e5806f7aac1c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 1 Apr 2022 11:38:25 +0300 Subject: [PATCH 059/298] tinywl: don't generate xdg-shell-protocol.c It's unused, and wlroots-based compositors don't need to do this anyway. --- tinywl/Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tinywl/Makefile b/tinywl/Makefile index 505666f03..68bac2522 100644 --- a/tinywl/Makefile +++ b/tinywl/Makefile @@ -12,11 +12,7 @@ xdg-shell-protocol.h: $(WAYLAND_SCANNER) server-header \ $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ -xdg-shell-protocol.c: xdg-shell-protocol.h - $(WAYLAND_SCANNER) private-code \ - $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ - -tinywl: tinywl.c xdg-shell-protocol.h xdg-shell-protocol.c +tinywl: tinywl.c xdg-shell-protocol.h $(CC) $(CFLAGS) \ -g -Werror -I. \ -DWLR_USE_UNSTABLE \ From 578e5614d46660fbeabd4ea1009f5604aa9c8117 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 30 Mar 2022 16:10:41 +0300 Subject: [PATCH 060/298] tinywl: remove outdated non-feature from README.md Now that tinywl uses wlr_scene under the hood, damage tracking comes for free. --- tinywl/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/tinywl/README.md b/tinywl/README.md index e0385d243..7fc83b96d 100644 --- a/tinywl/README.md +++ b/tinywl/README.md @@ -43,5 +43,3 @@ Notable omissions from TinyWL: - Optional protocols, e.g. screen capture, primary selection, virtual keyboard, etc. Most of these are plug-and-play with wlroots, but they're omitted for brevity. -- Damage tracking, which tracks which parts of the screen are changing and - minimizes redraws accordingly. From 2e14bed9f790c29146b0eee70eab7d8c704876e9 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 3 Apr 2022 11:46:25 +0000 Subject: [PATCH 061/298] meson: use target_machine instead of host_machine --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 554fbc42a..2350f7da7 100644 --- a/meson.build +++ b/meson.build @@ -17,8 +17,8 @@ project( # between minor releases. soversion = 11 -little_endian = host_machine.endian() == 'little' -big_endian = host_machine.endian() == 'big' +little_endian = target_machine.endian() == 'little' +big_endian = target_machine.endian() == 'big' add_project_arguments([ '-DWLR_USE_UNSTABLE', From bf3f60ff731472e875790633a1660b5e91abdce5 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 4 Mar 2022 00:59:22 +0300 Subject: [PATCH 062/298] xdg-toplevel: treat unmapped parents as NULL --- types/xdg_shell/wlr_xdg_toplevel.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index ed304cfcd..a78a4e895 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -151,11 +151,13 @@ void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel, wl_list_remove(&toplevel->parent_unmap.link); } - toplevel->parent = parent; - if (parent) { + if (parent && parent->base->mapped) { + toplevel->parent = parent; toplevel->parent_unmap.notify = handle_parent_unmap; wl_signal_add(&toplevel->parent->base->events.unmap, - &toplevel->parent_unmap); + &toplevel->parent_unmap); + } else { + toplevel->parent = NULL; } wlr_signal_emit_safe(&toplevel->events.set_parent, NULL); From dac040f87fee1cfdd7660aa1786b0734d95e03a4 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 4 Mar 2022 01:09:34 +0300 Subject: [PATCH 063/298] xdg-foreign-v1: treat unmapped parents as NULL --- include/wlr/types/wlr_xdg_foreign_v1.h | 2 +- types/wlr_xdg_foreign_v1.c | 31 ++++++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/wlr/types/wlr_xdg_foreign_v1.h b/include/wlr/types/wlr_xdg_foreign_v1.h index d98c72312..bebbb8ae6 100644 --- a/include/wlr/types/wlr_xdg_foreign_v1.h +++ b/include/wlr/types/wlr_xdg_foreign_v1.h @@ -34,7 +34,7 @@ struct wlr_xdg_exported_v1 { struct wlr_xdg_foreign_exported base; struct wl_resource *resource; - struct wl_listener xdg_surface_destroy; + struct wl_listener xdg_surface_unmap; struct wl_list link; // wlr_xdg_foreign_v1::exporter::objects }; diff --git a/types/wlr_xdg_foreign_v1.c b/types/wlr_xdg_foreign_v1.c index c07959aaf..b6e1c0a26 100644 --- a/types/wlr_xdg_foreign_v1.c +++ b/types/wlr_xdg_foreign_v1.c @@ -82,6 +82,17 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client, if (!verify_is_toplevel(resource, wlr_surface_child)) { return; } + + struct wlr_xdg_surface *surface = + wlr_xdg_surface_from_wlr_surface(wlr_surface); + struct wlr_xdg_surface *surface_child = + wlr_xdg_surface_from_wlr_surface(wlr_surface_child); + + if (!surface->mapped) { + wlr_xdg_toplevel_set_parent(surface_child->toplevel, NULL); + return; + } + struct wlr_xdg_imported_child_v1 *child; wl_list_for_each(child, &imported->children, link) { if (child->surface == wlr_surface_child) { @@ -98,11 +109,6 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client, child->xdg_surface_unmap.notify = handle_child_xdg_surface_unmap; child->xdg_toplevel_set_parent.notify = handle_xdg_toplevel_set_parent; - struct wlr_xdg_surface *surface = - wlr_xdg_surface_from_wlr_surface(wlr_surface); - struct wlr_xdg_surface *surface_child = - wlr_xdg_surface_from_wlr_surface(wlr_surface_child); - wlr_xdg_toplevel_set_parent(surface_child->toplevel, surface->toplevel); wl_signal_add(&surface_child->events.unmap, &child->xdg_surface_unmap); @@ -151,10 +157,7 @@ static void destroy_imported(struct wlr_xdg_imported_v1 *imported) { wl_list_for_each_safe(child, child_tmp, &imported->children, link) { struct wlr_xdg_surface *xdg_child = wlr_xdg_surface_from_wlr_surface(child->surface); - - if (xdg_child != NULL) { - wlr_xdg_toplevel_set_parent(xdg_child->toplevel, NULL); - } + wlr_xdg_toplevel_set_parent(xdg_child->toplevel, NULL); } wl_list_remove(&imported->exported_destroyed.link); @@ -169,7 +172,7 @@ static void destroy_imported(struct wlr_xdg_imported_v1 *imported) { static void destroy_exported(struct wlr_xdg_exported_v1 *exported) { wlr_xdg_foreign_exported_finish(&exported->base); - wl_list_remove(&exported->xdg_surface_destroy.link); + wl_list_remove(&exported->xdg_surface_unmap.link); wl_list_remove(&exported->link); wl_resource_set_user_data(exported->resource, NULL); free(exported); @@ -185,10 +188,10 @@ static void xdg_exported_handle_resource_destroy( } } -static void handle_xdg_surface_destroy( +static void handle_xdg_surface_unmap( struct wl_listener *listener, void *data) { struct wlr_xdg_exported_v1 *exported = - wl_container_of(listener, exported, xdg_surface_destroy); + wl_container_of(listener, exported, xdg_surface_unmap); destroy_exported(exported); } @@ -235,10 +238,10 @@ static void xdg_exporter_handle_export(struct wl_client *wl_client, zxdg_exported_v1_send_handle(exported->resource, exported->base.handle); - exported->xdg_surface_destroy.notify = handle_xdg_surface_destroy; + exported->xdg_surface_unmap.notify = handle_xdg_surface_unmap; struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(surface); - wl_signal_add(&xdg_surface->events.unmap, &exported->xdg_surface_destroy); + wl_signal_add(&xdg_surface->events.unmap, &exported->xdg_surface_unmap); } static const struct zxdg_exporter_v1_interface xdg_exporter_impl = { From 04aa44b4dfa3ee7a299240794f77c2ef2d55e6f3 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 4 Mar 2022 01:11:51 +0300 Subject: [PATCH 064/298] xdg-foreign-v2: treat unmapped parents as NULL --- include/wlr/types/wlr_xdg_foreign_v2.h | 2 +- types/wlr_xdg_foreign_v2.c | 31 ++++++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/wlr/types/wlr_xdg_foreign_v2.h b/include/wlr/types/wlr_xdg_foreign_v2.h index d0fb506a3..23c8247b7 100644 --- a/include/wlr/types/wlr_xdg_foreign_v2.h +++ b/include/wlr/types/wlr_xdg_foreign_v2.h @@ -34,7 +34,7 @@ struct wlr_xdg_exported_v2 { struct wlr_xdg_foreign_exported base; struct wl_resource *resource; - struct wl_listener xdg_surface_destroy; + struct wl_listener xdg_surface_unmap; struct wl_list link; // wlr_xdg_foreign_v2::exporter::objects }; diff --git a/types/wlr_xdg_foreign_v2.c b/types/wlr_xdg_foreign_v2.c index abd997352..28efff146 100644 --- a/types/wlr_xdg_foreign_v2.c +++ b/types/wlr_xdg_foreign_v2.c @@ -88,6 +88,17 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client, if (!verify_is_toplevel(resource, wlr_surface_child)) { return; } + + struct wlr_xdg_surface *surface = + wlr_xdg_surface_from_wlr_surface(wlr_surface); + struct wlr_xdg_surface *surface_child = + wlr_xdg_surface_from_wlr_surface(wlr_surface_child); + + if (!surface->mapped) { + wlr_xdg_toplevel_set_parent(surface_child->toplevel, NULL); + return; + } + struct wlr_xdg_imported_child_v2 *child; wl_list_for_each(child, &imported->children, link) { if (child->surface == wlr_surface_child) { @@ -104,11 +115,6 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client, child->xdg_surface_unmap.notify = handle_child_xdg_surface_unmap; child->xdg_toplevel_set_parent.notify = handle_xdg_toplevel_set_parent; - struct wlr_xdg_surface *surface = - wlr_xdg_surface_from_wlr_surface(wlr_surface); - struct wlr_xdg_surface *surface_child = - wlr_xdg_surface_from_wlr_surface(wlr_surface_child); - wlr_xdg_toplevel_set_parent(surface_child->toplevel, surface->toplevel); wl_signal_add(&surface_child->events.unmap, &child->xdg_surface_unmap); @@ -157,10 +163,7 @@ static void destroy_imported(struct wlr_xdg_imported_v2 *imported) { wl_list_for_each_safe(child, child_tmp, &imported->children, link) { struct wlr_xdg_surface *xdg_child = wlr_xdg_surface_from_wlr_surface(child->surface); - - if (xdg_child != NULL) { - wlr_xdg_toplevel_set_parent(xdg_child->toplevel, NULL); - } + wlr_xdg_toplevel_set_parent(xdg_child->toplevel, NULL); } wl_list_remove(&imported->exported_destroyed.link); @@ -175,7 +178,7 @@ static void destroy_imported(struct wlr_xdg_imported_v2 *imported) { static void destroy_exported(struct wlr_xdg_exported_v2 *exported) { wlr_xdg_foreign_exported_finish(&exported->base); - wl_list_remove(&exported->xdg_surface_destroy.link); + wl_list_remove(&exported->xdg_surface_unmap.link); wl_list_remove(&exported->link); wl_resource_set_user_data(exported->resource, NULL); free(exported); @@ -191,10 +194,10 @@ static void xdg_exported_handle_resource_destroy( } } -static void handle_xdg_surface_destroy( +static void handle_xdg_surface_unmap( struct wl_listener *listener, void *data) { struct wlr_xdg_exported_v2 *exported = - wl_container_of(listener, exported, xdg_surface_destroy); + wl_container_of(listener, exported, xdg_surface_unmap); destroy_exported(exported); } @@ -241,10 +244,10 @@ static void xdg_exporter_handle_export(struct wl_client *wl_client, zxdg_exported_v2_send_handle(exported->resource, exported->base.handle); - exported->xdg_surface_destroy.notify = handle_xdg_surface_destroy; + exported->xdg_surface_unmap.notify = handle_xdg_surface_unmap; struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(surface); - wl_signal_add(&xdg_surface->events.unmap, &exported->xdg_surface_destroy); + wl_signal_add(&xdg_surface->events.unmap, &exported->xdg_surface_unmap); } static const struct zxdg_exporter_v2_interface xdg_exporter_impl = { From dec2565f2b6b0a723d08f025967ac8ff1b7ee756 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 11 Apr 2022 21:33:15 +0300 Subject: [PATCH 065/298] xdg-toplevel: don't schedule configures on state requests --- include/wlr/types/wlr_xdg_shell.h | 8 ++++++++ tinywl/tinywl.c | 30 ++++++++++++++++++++++++++++++ types/xdg_shell/wlr_xdg_toplevel.c | 4 ---- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 48bfbb975..95c6ee6c1 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -147,8 +147,16 @@ struct wlr_xdg_toplevel { char *app_id; struct { + // Note: as per xdg-shell protocol, the compositor has to + // handle state requests by sending a configure event, + // even if it didn't actually change the state. Therefore, + // every compositor implementing xdg-shell support *must* + // listen to these signals and schedule a configure event + // immediately or at some time in the future; not doing so + // is a protocol violation. struct wl_signal request_maximize; struct wl_signal request_fullscreen; + struct wl_signal request_minimize; struct wl_signal request_move; struct wl_signal request_resize; diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 290dd0942..2ab0bcc01 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -85,6 +85,8 @@ struct tinywl_view { struct wl_listener destroy; struct wl_listener request_move; struct wl_listener request_resize; + struct wl_listener request_maximize; + struct wl_listener request_fullscreen; int x, y; }; @@ -619,6 +621,8 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&view->destroy.link); wl_list_remove(&view->request_move.link); wl_list_remove(&view->request_resize.link); + wl_list_remove(&view->request_maximize.link); + wl_list_remove(&view->request_fullscreen.link); free(view); } @@ -684,6 +688,26 @@ static void xdg_toplevel_request_resize( begin_interactive(view, TINYWL_CURSOR_RESIZE, event->edges); } +static void xdg_toplevel_request_maximize( + struct wl_listener *listener, void *data) { + /* This event is raised when a client would like to maximize itself, + * typically because the user clicked on the maximize button on + * client-side decorations. tinywl doesn't support maximization, but + * to conform to xdg-shell protocol we still must send a configure. + * wlr_xdg_surface_schedule_configure() is used to send an empty reply. */ + struct tinywl_view *view = + wl_container_of(listener, view, request_maximize); + wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); +} + +static void xdg_toplevel_request_fullscreen( + struct wl_listener *listener, void *data) { + /* Just as with request_maximize, we must send a configure here. */ + struct tinywl_view *view = + wl_container_of(listener, view, request_fullscreen); + wlr_xdg_surface_schedule_configure(view->xdg_toplevel->base); +} + static void server_new_xdg_surface(struct wl_listener *listener, void *data) { /* This event is raised when wlr_xdg_shell receives a new xdg surface from a * client, either a toplevel (application window) or popup. */ @@ -730,6 +754,12 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { wl_signal_add(&toplevel->events.request_move, &view->request_move); view->request_resize.notify = xdg_toplevel_request_resize; wl_signal_add(&toplevel->events.request_resize, &view->request_resize); + view->request_maximize.notify = xdg_toplevel_request_maximize; + wl_signal_add(&toplevel->events.request_maximize, + &view->request_maximize); + view->request_fullscreen.notify = xdg_toplevel_request_fullscreen; + wl_signal_add(&toplevel->events.request_fullscreen, + &view->request_fullscreen); } int main(int argc, char *argv[]) { diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index a78a4e895..786cfdad9 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -320,7 +320,6 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client, wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = true; wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, @@ -329,7 +328,6 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = false; wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void handle_fullscreen_output_destroy(struct wl_listener *listener, @@ -369,7 +367,6 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, true, output); wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, @@ -380,7 +377,6 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, false, NULL); wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); - wlr_xdg_surface_schedule_configure(toplevel->base); } static void xdg_toplevel_handle_set_minimized(struct wl_client *client, From 4ba84582550ed582afeea16369be9401da8122d7 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Thu, 14 Apr 2022 09:26:54 +0300 Subject: [PATCH 066/298] scene/output-layout: fix scene destroy handler --- types/scene/output_layout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c index 33dac1303..b80759ff1 100644 --- a/types/scene/output_layout.c +++ b/types/scene/output_layout.c @@ -99,7 +99,7 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, wl_signal_add(&output_layout->events.add, &sol->layout_add); sol->scene_destroy.notify = scene_output_layout_handle_scene_destroy; - wl_signal_add(&output_layout->events.destroy, &sol->scene_destroy); + wl_signal_add(&scene->node.events.destroy, &sol->scene_destroy); return true; } From eedb9df531ae73061c0f72ef2944df6f0068f6cd Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Sun, 27 Mar 2022 23:21:32 +0200 Subject: [PATCH 067/298] types/wlr_pointer_gestures_v1: null-check both focused_surface and focused_client (fixes #3385) --- types/wlr_pointer_gestures_v1.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/types/wlr_pointer_gestures_v1.c b/types/wlr_pointer_gestures_v1.c index b8229dfc4..1601b7924 100644 --- a/types/wlr_pointer_gestures_v1.c +++ b/types/wlr_pointer_gestures_v1.c @@ -52,7 +52,9 @@ void wlr_pointer_gestures_v1_send_swipe_begin( uint32_t time_msec, uint32_t fingers) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -79,7 +81,9 @@ void wlr_pointer_gestures_v1_send_swipe_update( double dx, double dy) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -103,7 +107,9 @@ void wlr_pointer_gestures_v1_send_swipe_end( uint32_t time_msec, bool cancelled) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -164,7 +170,9 @@ void wlr_pointer_gestures_v1_send_pinch_begin( uint32_t time_msec, uint32_t fingers) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -193,7 +201,9 @@ void wlr_pointer_gestures_v1_send_pinch_update( double scale, double rotation) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -219,7 +229,9 @@ void wlr_pointer_gestures_v1_send_pinch_end( uint32_t time_msec, bool cancelled) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -285,7 +297,9 @@ void wlr_pointer_gestures_v1_send_hold_begin( uint32_t time_msec, uint32_t fingers) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } @@ -311,7 +325,9 @@ void wlr_pointer_gestures_v1_send_hold_end( uint32_t time_msec, bool cancelled) { struct wlr_surface *focus = seat->pointer_state.focused_surface; - if (focus == NULL) { + struct wlr_seat_client *focus_seat_client = + seat->pointer_state.focused_client; + if (focus == NULL || focus_seat_client == NULL) { return; } From 2d4e8135308d225ece8ca4badcef89929b5b228e Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Sat, 16 Apr 2022 20:53:52 +0200 Subject: [PATCH 068/298] types/wlr_pointer_gestures_v1.c: get client from seat client instead of resource --- types/wlr_pointer_gestures_v1.c | 34 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/types/wlr_pointer_gestures_v1.c b/types/wlr_pointer_gestures_v1.c index 1601b7924..b3f874c95 100644 --- a/types/wlr_pointer_gestures_v1.c +++ b/types/wlr_pointer_gestures_v1.c @@ -58,9 +58,8 @@ void wlr_pointer_gestures_v1_send_swipe_begin( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->swipes) { @@ -87,7 +86,7 @@ void wlr_pointer_gestures_v1_send_swipe_update( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); + struct wl_client *focus_client = focus_seat_client->client; struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->swipes) { @@ -113,9 +112,8 @@ void wlr_pointer_gestures_v1_send_swipe_end( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->swipes) { @@ -176,9 +174,8 @@ void wlr_pointer_gestures_v1_send_pinch_begin( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->pinches) { @@ -207,7 +204,7 @@ void wlr_pointer_gestures_v1_send_pinch_update( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); + struct wl_client *focus_client = focus_seat_client->client; struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->pinches) { @@ -235,9 +232,8 @@ void wlr_pointer_gestures_v1_send_pinch_end( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->pinches) { @@ -303,9 +299,8 @@ void wlr_pointer_gestures_v1_send_hold_begin( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->holds) { @@ -331,9 +326,8 @@ void wlr_pointer_gestures_v1_send_hold_end( return; } - struct wl_client *focus_client = wl_resource_get_client(focus->resource); - uint32_t serial = wlr_seat_client_next_serial( - seat->pointer_state.focused_client); + struct wl_client *focus_client = focus_seat_client->client; + uint32_t serial = wlr_seat_client_next_serial(focus_seat_client); struct wl_resource *gesture; wl_resource_for_each(gesture, &gestures->holds) { From d3a2ea33e5308f46d4c148cc1de7c428de782536 Mon Sep 17 00:00:00 2001 From: Ferdinand Bachmann Date: Sat, 16 Apr 2022 18:59:22 +0200 Subject: [PATCH 069/298] types/seat/wlr_seat.c: fix focused_client being null after seat_client recreation --- types/seat/wlr_seat.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index f2fd04c12..5280bc465 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "types/wlr_seat.h" #include "util/global.h" @@ -142,6 +143,20 @@ static void seat_handle_bind(struct wl_client *client, void *_wlr_seat, wl_signal_init(&seat_client->events.destroy); wl_list_insert(&wlr_seat->clients, &seat_client->link); + + struct wlr_surface *pointer_focus = + wlr_seat->pointer_state.focused_surface; + if (pointer_focus != NULL && + wl_resource_get_client(pointer_focus->resource) == client) { + wlr_seat->pointer_state.focused_client = seat_client; + } + + struct wlr_surface *keyboard_focus = + wlr_seat->keyboard_state.focused_surface; + if (keyboard_focus != NULL && + wl_resource_get_client(keyboard_focus->resource) == client) { + wlr_seat->keyboard_state.focused_client = seat_client; + } } wl_resource_set_implementation(wl_resource, &seat_impl, From 640f3b9f2156a007c5d1a36afdee570e123c95e4 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Sat, 16 Apr 2022 13:24:11 -0400 Subject: [PATCH 070/298] Revert "Copy xcb_icccm structs into wlroots" The original commit introduced a bug by transposing the order of some of the fields in xcb_size_hints_t. Since XCB ICCCM support is required now, we can just eliminate the duplicate structs. With minor changes: - Remove #ifdef HAS_XCB_ICCCM guards - Fix #includes - Fix references to local size_hints struct This reverts commit 12b9b1a4bdf00742cc510c2329c7a66c649b3ab0. --- include/wlr/xwayland.h | 30 +++--------------------------- xwayland/xwm.c | 26 ++++++++------------------ 2 files changed, 11 insertions(+), 45 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index aa9569fea..d4a483931 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -15,6 +15,7 @@ #include #include #include +#include struct wlr_xwm; struct wlr_xwayland_cursor; @@ -96,30 +97,6 @@ enum wlr_xwayland_surface_decorations { WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE = 2, }; -struct wlr_xwayland_surface_hints { - uint32_t flags; - uint32_t input; - int32_t initial_state; - xcb_pixmap_t icon_pixmap; - xcb_window_t icon_window; - int32_t icon_x, icon_y; - xcb_pixmap_t icon_mask; - xcb_window_t window_group; -}; - -struct wlr_xwayland_surface_size_hints { - uint32_t flags; - int32_t x, y; - int32_t width, height; - int32_t min_width, min_height; - int32_t max_width, max_height; - int32_t width_inc, height_inc; - int32_t base_width, base_height; - int32_t min_aspect_num, min_aspect_den; - int32_t max_aspect_num, max_aspect_den; - uint32_t win_gravity; -}; - /** * This represents the input focus described as follows: * @@ -176,9 +153,8 @@ struct wlr_xwayland_surface { size_t protocols_len; uint32_t decorations; - struct wlr_xwayland_surface_hints *hints; - uint32_t hints_urgency; - struct wlr_xwayland_surface_size_hints *size_hints; + xcb_icccm_wm_hints_t *hints; + xcb_size_hints_t *size_hints; bool pinging; struct wl_event_source *ping_timer; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 0c1992690..a80e47643 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "util/signal.h" #include "xwayland/xwm.h" @@ -662,17 +661,12 @@ static void read_surface_hints(struct wlr_xwm *xwm, return; } - xcb_icccm_wm_hints_t hints; - xcb_icccm_get_wm_hints_from_reply(&hints, reply); - free(xsurface->hints); - xsurface->hints = calloc(1, sizeof(struct wlr_xwayland_surface_hints)); + xsurface->hints = calloc(1, sizeof(xcb_icccm_wm_hints_t)); if (xsurface->hints == NULL) { return; } - - memcpy(xsurface->hints, &hints, sizeof(struct wlr_xwayland_surface_hints)); - xsurface->hints_urgency = xcb_icccm_wm_hints_get_urgency(&hints); + xcb_icccm_get_wm_hints_from_reply(xsurface->hints, reply); if (!(xsurface->hints->flags & XCB_ICCCM_WM_HINT_INPUT)) { // The client didn't specify whether it wants input. @@ -690,20 +684,16 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, return; } - xcb_size_hints_t size_hints; - xcb_icccm_get_wm_size_hints_from_reply(&size_hints, reply); - free(xsurface->size_hints); - xsurface->size_hints = - calloc(1, sizeof(struct wlr_xwayland_surface_size_hints)); + xsurface->size_hints = calloc(1, sizeof(xcb_size_hints_t)); if (xsurface->size_hints == NULL) { return; } - memcpy(xsurface->size_hints, &size_hints, - sizeof(struct wlr_xwayland_surface_size_hints)); + xcb_icccm_get_wm_size_hints_from_reply(xsurface->size_hints, reply); - bool has_min_size_hints = (size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) != 0; - bool has_base_size_hints = (size_hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) != 0; + int32_t flags = xsurface->size_hints->flags; + bool has_min_size_hints = (flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) != 0; + bool has_base_size_hints = (flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) != 0; /* ICCCM says that if absent, min size is equal to base size and vice versa */ if (!has_min_size_hints && !has_base_size_hints) { xsurface->size_hints->min_width = -1; @@ -718,7 +708,7 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, xsurface->size_hints->min_height = xsurface->size_hints->base_height; } - if ((size_hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) == 0) { + if ((flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) == 0) { xsurface->size_hints->max_width = -1; xsurface->size_hints->max_height = -1; } From 2ce0305483b7ca28d2ef27c7c3fd9f3282875ede Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 16 Apr 2022 09:24:10 -0400 Subject: [PATCH 071/298] seat: Don't finish wlr_keyboard if server was never started --- backend/wayland/seat.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 261da909e..c05591aa3 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -259,7 +259,10 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { } if (seat->wl_keyboard) { wl_keyboard_release(seat->wl_keyboard); - wlr_keyboard_finish(&seat->wlr_keyboard); + + if (seat->backend->started) { + wlr_keyboard_finish(&seat->wlr_keyboard); + } } if (seat->zwp_tablet_seat_v2) { finish_seat_tablet(seat); From a43d105a507810a5562f8286d2a642e672dd1dca Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 20 Apr 2022 14:49:25 +0300 Subject: [PATCH 072/298] backend/wayland/pointer: fix indentation --- backend/wayland/pointer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index b2ed2ae75..0dc5efa94 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -401,14 +401,14 @@ const struct wlr_pointer_impl wl_pointer_impl = { }; static void destroy_pointer(struct wlr_wl_pointer *pointer) { - if (pointer->output->cursor.pointer == pointer) { - pointer->output->cursor.pointer = NULL; - } + if (pointer->output->cursor.pointer == pointer) { + pointer->output->cursor.pointer = NULL; + } - wlr_pointer_finish(&pointer->wlr_pointer); - wl_list_remove(&pointer->output_destroy.link); - wl_list_remove(&pointer->link); - free(pointer); + wlr_pointer_finish(&pointer->wlr_pointer); + wl_list_remove(&pointer->output_destroy.link); + wl_list_remove(&pointer->link); + free(pointer); } static void pointer_output_destroy(struct wl_listener *listener, void *data) { From 03c88b07ba64185de7183f52f5f3e4875c5c1d5d Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 20 Apr 2022 14:49:45 +0300 Subject: [PATCH 073/298] backend/wayland: zero out finished input devices --- backend/wayland/seat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index c05591aa3..3f89ec501 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -325,7 +325,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_keyboard_release(seat->wl_keyboard); wlr_keyboard_finish(&seat->wlr_keyboard); - + memset(&seat->wlr_keyboard, 0, sizeof(seat->wlr_keyboard)); seat->wl_keyboard = NULL; } @@ -340,6 +340,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_touch_release(seat->wl_touch); wlr_touch_finish(&seat->wlr_touch); + memset(&seat->wlr_touch, 0, sizeof(seat->wlr_touch)); seat->wl_touch = NULL; } } From 91da4c557b5f46167ce78576b2e8d5dead81bec1 Mon Sep 17 00:00:00 2001 From: zsugabubus <48559-zsugabubus@users.noreply.gitlab.freedesktop.org> Date: Wed, 20 Apr 2022 17:50:55 +0200 Subject: [PATCH 074/298] xwayland: do not double free server on destroy --- xwayland/xwayland.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 86e8c6ebe..e09b05cfc 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -29,6 +29,8 @@ struct wlr_xwayland_cursor { static void handle_server_destroy(struct wl_listener *listener, void *data) { struct wlr_xwayland *xwayland = wl_container_of(listener, xwayland, server_destroy); + // Server is being destroyed so avoid destroying it once again. + xwayland->server = NULL; wlr_xwayland_destroy(xwayland); } From c091a075894253808daa4cb251383d7c20072293 Mon Sep 17 00:00:00 2001 From: tiosgz Date: Fri, 22 Apr 2022 12:14:45 +0000 Subject: [PATCH 075/298] CONTRIBUTING.md: make forks public to let the CI run This little note helps first-time contributors who are in doubt regarding the repo visibility. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63e279b53..0ef9f7c1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ If you already have your own merge request habits, feel free to use them. If you don't, however, allow me to make a suggestion: feature branches pulled from upstream. Try this: -1. Fork wlroots +1. Fork wlroots (make the fork public to allow the CI to run) 2. `git clone git@gitlab.freedesktop.org:/wlroots.git && cd wlroots` 3. `git remote add upstream https://gitlab.freedesktop.org/wlroots/wlroots.git` From 54653b5d95935e379e26db5518456a66384b5405 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 26 Apr 2022 09:43:10 +0200 Subject: [PATCH 076/298] util/addon: fix public include Everything in wlr/ is public and should be included via angle-bracket include directives. --- util/addon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/util/addon.c b/util/addon.c index d9e13978d..395a8df67 100644 --- a/util/addon.c +++ b/util/addon.c @@ -1,8 +1,7 @@ #include #include #include - -#include "wlr/util/addon.h" +#include void wlr_addon_set_init(struct wlr_addon_set *set) { wl_list_init(&set->addons); From 6c350799b22ddc5cb89467c95692437bbf0116b9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 26 Apr 2022 09:43:54 +0200 Subject: [PATCH 077/298] Zero-initialize structs in init functions Ensures there is no field left to its previous undefined value after calling an init function. --- backend/backend.c | 2 +- backend/drm/drm.c | 1 + render/allocator/allocator.c | 1 + render/wlr_renderer.c | 2 ++ render/wlr_texture.c | 2 ++ types/data_device/wlr_data_source.c | 1 + types/output/output.c | 2 ++ types/scene/wlr_scene.c | 2 ++ types/wlr_buffer.c | 2 ++ types/wlr_compositor.c | 2 ++ types/wlr_input_device.c | 1 + types/wlr_keyboard.c | 1 + types/wlr_pointer.c | 1 + types/wlr_primary_selection.c | 1 + types/wlr_switch.c | 1 + types/wlr_tablet_pad.c | 1 + types/wlr_tablet_tool.c | 1 + types/wlr_touch.c | 1 + util/addon.c | 3 +++ xwayland/selection/selection.c | 2 ++ 20 files changed, 29 insertions(+), 1 deletion(-) diff --git a/backend/backend.c b/backend/backend.c index bfb43ba07..ac6e21653 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -36,7 +36,7 @@ void wlr_backend_init(struct wlr_backend *backend, const struct wlr_backend_impl *impl) { - assert(backend); + memset(backend, 0, sizeof(*backend)); backend->impl = impl; wl_signal_init(&backend->events.destroy); wl_signal_init(&backend->events.new_input); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 2b573295c..5a828426a 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -380,6 +380,7 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn, static void drm_connector_state_init(struct wlr_drm_connector_state *state, struct wlr_drm_connector *conn, const struct wlr_output_state *base) { + memset(state, 0, sizeof(*state)); state->base = base; state->modeset = base->committed & (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE); diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 2c75421f1..83e836aee 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -18,6 +18,7 @@ void wlr_allocator_init(struct wlr_allocator *alloc, const struct wlr_allocator_interface *impl, uint32_t buffer_caps) { assert(impl && impl->destroy && impl->create_buffer); + memset(alloc, 0, sizeof(*alloc)); alloc->impl = impl; alloc->buffer_caps = buffer_caps; wl_signal_init(&alloc->events.destroy); diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 2b5cf9945..478db7453 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -39,6 +39,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer, assert(impl->render_quad_with_matrix); assert(impl->get_shm_texture_formats); assert(impl->get_render_buffer_caps); + + memset(renderer, 0, sizeof(*renderer)); renderer->impl = impl; wl_signal_init(&renderer->events.destroy); diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 2cdf08c59..36cbf136d 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -1,12 +1,14 @@ #include #include #include +#include #include #include #include "types/wlr_buffer.h" void wlr_texture_init(struct wlr_texture *texture, const struct wlr_texture_impl *impl, uint32_t width, uint32_t height) { + memset(texture, 0, sizeof(*texture)); texture->impl = impl; texture->width = width; texture->height = height; diff --git a/types/data_device/wlr_data_source.c b/types/data_device/wlr_data_source.c index 1baaac60a..b07c44873 100644 --- a/types/data_device/wlr_data_source.c +++ b/types/data_device/wlr_data_source.c @@ -15,6 +15,7 @@ void wlr_data_source_init(struct wlr_data_source *source, const struct wlr_data_source_impl *impl) { assert(impl->send); + memset(source, 0, sizeof(*source)); source->impl = impl; wl_array_init(&source->mime_types); wl_signal_init(&source->events.destroy); diff --git a/types/output/output.c b/types/output/output.c index e4d45043a..68a74b6b3 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -377,6 +377,8 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, if (impl->set_cursor || impl->move_cursor) { assert(impl->set_cursor && impl->move_cursor); } + + memset(output, 0, sizeof(*output)); output->backend = backend; output->impl = impl; output->display = display; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 9353fef5c..d88dd55f2 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -48,6 +48,7 @@ static struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { } static void scene_node_state_init(struct wlr_scene_node_state *state) { + memset(state, 0, sizeof(*state)); wl_list_init(&state->children); wl_list_init(&state->link); state->enabled = true; @@ -61,6 +62,7 @@ static void scene_node_init(struct wlr_scene_node *node, enum wlr_scene_node_type type, struct wlr_scene_node *parent) { assert(type == WLR_SCENE_NODE_ROOT || parent != NULL); + memset(node, 0, sizeof(*node)); node->type = type; node->parent = parent; scene_node_state_init(&node->state); diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 0e091f569..e50fad405 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -17,6 +17,8 @@ void wlr_buffer_init(struct wlr_buffer *buffer, if (impl->begin_data_ptr_access || impl->end_data_ptr_access) { assert(impl->begin_data_ptr_access && impl->end_data_ptr_access); } + + memset(buffer, 0, sizeof(*buffer)); buffer->impl = impl; buffer->width = width; buffer->height = height; diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index bb4275ef3..1e86e9e78 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -583,6 +583,8 @@ struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource) { } static void surface_state_init(struct wlr_surface_state *state) { + memset(state, 0, sizeof(*state)); + state->scale = 1; state->transform = WL_OUTPUT_TRANSFORM_NORMAL; diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index d87935d85..87cc64b8e 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -7,6 +7,7 @@ void wlr_input_device_init(struct wlr_input_device *dev, enum wlr_input_device_type type, const char *name) { + memset(dev, 0, sizeof(*dev)); dev->type = type; dev->name = strdup(name); dev->vendor = 0; diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index df99e8ba9..2a82cfa8e 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -116,6 +116,7 @@ void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, void wlr_keyboard_init(struct wlr_keyboard *kb, const struct wlr_keyboard_impl *impl, const char *name) { + memset(kb, 0, sizeof(*kb)); wlr_input_device_init(&kb->base, WLR_INPUT_DEVICE_KEYBOARD, name); kb->base.keyboard = kb; diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index 09782cda8..e4d39f6af 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -8,6 +8,7 @@ void wlr_pointer_init(struct wlr_pointer *pointer, const struct wlr_pointer_impl *impl, const char *name) { + memset(pointer, 0, sizeof(*pointer)); wlr_input_device_init(&pointer->base, WLR_INPUT_DEVICE_POINTER, name); pointer->base.pointer = pointer; diff --git a/types/wlr_primary_selection.c b/types/wlr_primary_selection.c index 0875462c8..21784aae7 100644 --- a/types/wlr_primary_selection.c +++ b/types/wlr_primary_selection.c @@ -8,6 +8,7 @@ void wlr_primary_selection_source_init( struct wlr_primary_selection_source *source, const struct wlr_primary_selection_source_impl *impl) { assert(impl->send); + memset(source, 0, sizeof(*source)); wl_array_init(&source->mime_types); wl_signal_init(&source->events.destroy); source->impl = impl; diff --git a/types/wlr_switch.c b/types/wlr_switch.c index 8e84841d5..3b05ec6c0 100644 --- a/types/wlr_switch.c +++ b/types/wlr_switch.c @@ -8,6 +8,7 @@ void wlr_switch_init(struct wlr_switch *switch_device, const struct wlr_switch_impl *impl, const char *name) { + memset(switch_device, 0, sizeof(*switch_device)); wlr_input_device_init(&switch_device->base, WLR_INPUT_DEVICE_SWITCH, name); switch_device->base.switch_device = switch_device; diff --git a/types/wlr_tablet_pad.c b/types/wlr_tablet_pad.c index df389c465..353b4d431 100644 --- a/types/wlr_tablet_pad.c +++ b/types/wlr_tablet_pad.c @@ -9,6 +9,7 @@ void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name) { + memset(pad, 0, sizeof(*pad)); wlr_input_device_init(&pad->base, WLR_INPUT_DEVICE_TABLET_PAD, name); pad->base.tablet_pad = pad; diff --git a/types/wlr_tablet_tool.c b/types/wlr_tablet_tool.c index a5c9d44fa..7d8eb4187 100644 --- a/types/wlr_tablet_tool.c +++ b/types/wlr_tablet_tool.c @@ -8,6 +8,7 @@ void wlr_tablet_init(struct wlr_tablet *tablet, const struct wlr_tablet_impl *impl, const char *name) { + memset(tablet, 0, sizeof(*tablet)); wlr_input_device_init(&tablet->base, WLR_INPUT_DEVICE_TABLET_TOOL, name); tablet->base.tablet = tablet; diff --git a/types/wlr_touch.c b/types/wlr_touch.c index 96d196d34..28fec1982 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -8,6 +8,7 @@ void wlr_touch_init(struct wlr_touch *touch, const struct wlr_touch_impl *impl, const char *name) { + memset(touch, 0, sizeof(*touch)); wlr_input_device_init(&touch->base, WLR_INPUT_DEVICE_TOUCH, name); touch->base.touch = touch; diff --git a/util/addon.c b/util/addon.c index 395a8df67..c9b373a76 100644 --- a/util/addon.c +++ b/util/addon.c @@ -1,9 +1,11 @@ #include #include +#include #include #include void wlr_addon_set_init(struct wlr_addon_set *set) { + memset(set, 0, sizeof(*set)); wl_list_init(&set->addons); } @@ -18,6 +20,7 @@ void wlr_addon_set_finish(struct wlr_addon_set *set) { void wlr_addon_init(struct wlr_addon *addon, struct wlr_addon_set *set, const void *owner, const struct wlr_addon_interface *impl) { assert(owner && impl); + memset(addon, 0, sizeof(*addon)); struct wlr_addon *iter; wl_list_for_each(iter, &set->addons, link) { if (iter->owner == addon->owner && iter->impl == addon->impl) { diff --git a/xwayland/selection/selection.c b/xwayland/selection/selection.c index 26817fbbe..4cc8b6272 100644 --- a/xwayland/selection/selection.c +++ b/xwayland/selection/selection.c @@ -34,6 +34,7 @@ void xwm_selection_transfer_destroy_property_reply( void xwm_selection_transfer_init(struct wlr_xwm_selection_transfer *transfer, struct wlr_xwm_selection *selection) { + memset(transfer, 0, sizeof(*transfer)); transfer->selection = selection; transfer->wl_client_fd = -1; } @@ -174,6 +175,7 @@ int xwm_handle_selection_event(struct wlr_xwm *xwm, void xwm_selection_init(struct wlr_xwm_selection *selection, struct wlr_xwm *xwm, xcb_atom_t atom) { + memset(selection, 0, sizeof(*selection)); wl_list_init(&selection->incoming); wl_list_init(&selection->outgoing); From a1e1e9aba8d1ccbd9582be659c5d3d2e587214ff Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 26 Apr 2022 09:45:00 +0200 Subject: [PATCH 078/298] Revert "backend/wayland: zero out finished input devices" This reverts commit 03c88b07ba64185de7183f52f5f3e4875c5c1d5d. init functions now zero out the structs. --- backend/wayland/seat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 3f89ec501..c05591aa3 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -325,7 +325,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_keyboard_release(seat->wl_keyboard); wlr_keyboard_finish(&seat->wlr_keyboard); - memset(&seat->wlr_keyboard, 0, sizeof(seat->wlr_keyboard)); + seat->wl_keyboard = NULL; } @@ -340,7 +340,6 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_touch_release(seat->wl_touch); wlr_touch_finish(&seat->wlr_touch); - memset(&seat->wlr_touch, 0, sizeof(seat->wlr_touch)); seat->wl_touch = NULL; } } From ec2af17674ade115e76c06cf5cde1d1e829460b3 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 27 Apr 2022 18:34:01 +0300 Subject: [PATCH 079/298] CONTRIBUTING.md: update init/finish description --- CONTRIBUTING.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ef9f7c1a..65446c184 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -167,7 +167,6 @@ if (condition1 && condition2 && ... Try to break the line in the place which you think is the most appropriate. - ### Line Length Try to keep your lines under 80 columns, but you can go up to 100 if it @@ -190,16 +189,18 @@ Functions that are responsible for constructing objects should take one of the two following forms: * `init`: for functions which accept a pointer to a pre-allocated object (e.g. -a member of a struct) and initialize it. +a member of a struct) and initialize it. Such functions must call `memset()` +to zero out the memory before initializing it to avoid leaving unset fields. * `create`: for functions which allocate the memory for an object, initialize -it, and return a pointer. +it, and return a pointer. Such functions should allocate the memory with +`calloc()` to avoid leaving unset fields. Likewise, functions that are responsible for destructing objects should take one of the two following forms: * `finish`: for functions which accept a pointer to an object and deinitialize -it. Such functions should always be able to accept an already deinitialized -object. +it. If a finished object isn't destroyed but kept for future use, it must be +reinitialized to be used again. * `destroy`: for functions which accept a pointer to an object, deinitialize it, and free the memory. Such functions should always be able to accept a NULL pointer. From bc4350c976f238bc945ad02cfddb0b186de207ed Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 29 Apr 2022 21:55:04 +0300 Subject: [PATCH 080/298] backend/wayland: reset active pointer on destroy --- backend/wayland/pointer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index 0dc5efa94..db31f1abb 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -404,6 +404,9 @@ static void destroy_pointer(struct wlr_wl_pointer *pointer) { if (pointer->output->cursor.pointer == pointer) { pointer->output->cursor.pointer = NULL; } + if (pointer->seat->active_pointer == pointer) { + pointer->seat->active_pointer = NULL; + } wlr_pointer_finish(&pointer->wlr_pointer); wl_list_remove(&pointer->output_destroy.link); From 48c811ffb6ef49a311eb25669da96519bfd5dc97 Mon Sep 17 00:00:00 2001 From: zccrs Date: Sun, 1 May 2022 14:27:40 +0800 Subject: [PATCH 081/298] render/vulkan: fix undefined reference to wlr_texture_is_vk Added the implement of wlr_texture_is_vk. Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3419 --- render/vulkan/texture.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index b705603cf..26af98676 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -7,14 +7,19 @@ #include #include #include +#include #include #include "render/pixel_format.h" #include "render/vulkan.h" static const struct wlr_texture_impl texture_impl; +bool wlr_texture_is_vk(struct wlr_texture *wlr_texture) { + return wlr_texture->impl == &texture_impl; +} + struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture) { - assert(wlr_texture->impl == &texture_impl); + assert(wlr_texture_is_vk(wlr_texture)); return (struct wlr_vk_texture *)wlr_texture; } From 95d3529edf16add98d0f2f7c749b59d2d861bfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Sun, 13 Mar 2022 20:50:03 +0100 Subject: [PATCH 082/298] xcursor: check that XDG base directory path is absolute The spec reads: > All paths set in these environment variables must be absolute. If an > implementation encounters a relative path in any of these variables it should > consider the path invalid and ignore it. and > If $XDG_DATA_HOME is either not set or empty, a default equal to > $HOME/.local/share should be used. Testing that the path is absolute also entails that is is non-empty. --- xcursor/xcursor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcursor/xcursor.c b/xcursor/xcursor.c index b0c424f4c..d9a942f89 100644 --- a/xcursor/xcursor.c +++ b/xcursor/xcursor.c @@ -647,7 +647,7 @@ XcursorLibraryPath (void) } else { env_var = getenv("XDG_DATA_HOME"); - if (env_var) { + if (env_var && env_var[0] == '/') { pathlen = strlen(env_var) + strlen(CURSORDIR ":" XCURSORPATH) + 1; path = malloc(pathlen); From 410c08cdc676de1f24d71d8817587e1f7e6b4093 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 29 Mar 2022 16:14:38 +0200 Subject: [PATCH 083/298] drm-lease-v1: skip device on wlr_drm_backend_get_non_master_fd failure On some setups, wlr_drm_backend_get_non_master_fd may fail because of permission issues. Instead of exposing a bogus global, bail out. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3391 --- types/wlr_drm_lease_v1.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/types/wlr_drm_lease_v1.c b/types/wlr_drm_lease_v1.c index 7cb9974d7..0ef9e0365 100644 --- a/types/wlr_drm_lease_v1.c +++ b/types/wlr_drm_lease_v1.c @@ -621,10 +621,18 @@ static void handle_backend_destroy(struct wl_listener *listener, void *data) { static void drm_lease_device_v1_create(struct wlr_drm_lease_v1_manager *manager, struct wlr_backend *backend) { - assert(backend); + struct wlr_drm_backend *drm_backend = get_drm_backend_from_backend(backend); + + // Make sure we can get a non-master FD for the DRM backend. On some setups + // we don't have the permission for this. + int fd = wlr_drm_backend_get_non_master_fd(backend); + if (fd < 0) { + wlr_log(WLR_INFO, "Skipping %s: failed to get read-only DRM FD", + drm_backend->name); + return; + } + close(fd); - struct wlr_drm_backend *drm_backend = - get_drm_backend_from_backend(backend); wlr_log(WLR_DEBUG, "Creating wlr_drm_lease_device_v1 for %s", drm_backend->name); From cb012c5cb53a937037717ac79c125922e37193da Mon Sep 17 00:00:00 2001 From: xiaoyaobing <1109050030@qq.com> Date: Tue, 3 May 2022 00:08:32 +0800 Subject: [PATCH 084/298] tinywl/tinywl: clean up tinywl_output when wlr_output is gone Add destroy event processing. Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3416 --- tinywl/tinywl.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 2ab0bcc01..7f6de6bc8 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -73,6 +73,7 @@ struct tinywl_output { struct tinywl_server *server; struct wlr_output *wlr_output; struct wl_listener frame; + struct wl_listener destroy; }; struct tinywl_view { @@ -549,6 +550,15 @@ static void output_frame(struct wl_listener *listener, void *data) { wlr_scene_output_send_frame_done(scene_output, &now); } +static void output_destroy(struct wl_listener *listener, void *data) { + struct tinywl_output *output = wl_container_of(listener, output, destroy); + + wl_list_remove(&output->frame.link); + wl_list_remove(&output->destroy.link); + wl_list_remove(&output->link); + free(output); +} + static void server_new_output(struct wl_listener *listener, void *data) { /* This event is raised by the backend when a new output (aka a display or * monitor) becomes available. */ @@ -582,6 +592,11 @@ static void server_new_output(struct wl_listener *listener, void *data) { /* Sets up a listener for the frame notify event. */ output->frame.notify = output_frame; wl_signal_add(&wlr_output->events.frame, &output->frame); + + /* Sets up a listener for the destroy notify event. */ + output->destroy.notify = output_destroy; + wl_signal_add(&wlr_output->events.destroy, &output->destroy); + wl_list_insert(&server->outputs, &output->link); /* Adds this to the output layout. The add_auto function arranges outputs From 7ad67e0f1db486bf0994128f9750115722eef6d5 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Sat, 30 Apr 2022 22:43:49 -0400 Subject: [PATCH 085/298] render/gles: add support for some 16-bpc unsigned shm formats These formats require EXT_texture_norm16, which in turn needs OpenGL ES 3.1. The EXT_texture_norm16 extension does not support passing gl_internalformat = GL_RGBA to glTexImage2D, as can be done for formats available in OpenGL ES 2.0, so this commit adds a field to wlr_gles2_pixel_format to provide a more specific internalformat parameter to glTexImage2D. --- include/render/gles2.h | 3 +++ render/gles2/pixel_format.c | 18 ++++++++++++++++++ render/gles2/renderer.c | 3 +++ render/gles2/texture.c | 7 ++++++- render/pixel_format.c | 12 ++++++++++++ 5 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 245b2804e..714bacf56 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -17,6 +17,8 @@ struct wlr_gles2_pixel_format { uint32_t drm_format; + // optional field, if empty then internalformat = format + GLint gl_internalformat; GLint gl_format, gl_type; bool has_alpha; }; @@ -45,6 +47,7 @@ struct wlr_gles2_renderer { bool OES_egl_image; bool EXT_texture_type_2_10_10_10_REV; bool OES_texture_half_float_linear; + bool EXT_texture_norm16; } exts; struct { diff --git a/render/gles2/pixel_format.c b/render/gles2/pixel_format.c index b155bbbe9..acaac5ceb 100644 --- a/render/gles2/pixel_format.c +++ b/render/gles2/pixel_format.c @@ -93,6 +93,20 @@ static const struct wlr_gles2_pixel_format formats[] = { .gl_type = GL_HALF_FLOAT_OES, .has_alpha = true, }, + { + .drm_format = DRM_FORMAT_XBGR16161616, + .gl_internalformat = GL_RGBA16_EXT, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT, + .has_alpha = false, + }, + { + .drm_format = DRM_FORMAT_ABGR16161616, + .gl_internalformat = GL_RGBA16_EXT, + .gl_format = GL_RGBA, + .gl_type = GL_UNSIGNED_SHORT, + .has_alpha = true, + }, #endif }; @@ -112,6 +126,10 @@ bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer, && !renderer->exts.OES_texture_half_float_linear) { return false; } + if (format->gl_type == GL_UNSIGNED_SHORT + && !renderer->exts.EXT_texture_norm16) { + return false; + } /* * Note that we don't need to check for GL_EXT_texture_format_BGRA8888 * here, since we've already checked if we have it at renderer creation diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 67b8ead47..5ffd6f85f 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -765,6 +765,9 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { renderer->exts.OES_texture_half_float_linear = check_gl_ext(exts_str, "GL_OES_texture_half_float_linear"); + renderer->exts.EXT_texture_norm16 = + check_gl_ext(exts_str, "GL_EXT_texture_norm16"); + if (check_gl_ext(exts_str, "GL_KHR_debug")) { renderer->exts.KHR_debug = true; load_gl_proc(&renderer->procs.glDebugMessageCallbackKHR, diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 8d6f3fc24..574207448 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -210,6 +210,11 @@ static struct wlr_texture *gles2_texture_from_pixels( texture->has_alpha = fmt->has_alpha; texture->drm_format = fmt->drm_format; + GLint internal_format = fmt->gl_internalformat; + if (!internal_format) { + internal_format = fmt->gl_format; + } + struct wlr_egl_context prev_ctx; wlr_egl_save_context(&prev_ctx); wlr_egl_make_current(renderer->egl); @@ -222,7 +227,7 @@ static struct wlr_texture *gles2_texture_from_pixels( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8)); - glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, fmt->gl_format, fmt->gl_type, data); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); diff --git a/render/pixel_format.c b/render/pixel_format.c index bd59af8b1..e6417fd7c 100644 --- a/render/pixel_format.c +++ b/render/pixel_format.c @@ -128,6 +128,18 @@ static const struct wlr_pixel_format_info pixel_format_info[] = { .bpp = 64, .has_alpha = true, }, + { + .drm_format = DRM_FORMAT_XBGR16161616, + .opaque_substitute = DRM_FORMAT_INVALID, + .bpp = 64, + .has_alpha = false, + }, + { + .drm_format = DRM_FORMAT_ABGR16161616, + .opaque_substitute = DRM_FORMAT_XBGR16161616, + .bpp = 64, + .has_alpha = true, + }, }; static const size_t pixel_format_info_size = From 352064d76d459b499b39a99f889f96f40987f0e9 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 12:00:26 +0200 Subject: [PATCH 086/298] xwayland: add wlr_xwayland_server_options.terminate_delay This allows users to specify a delay after which the Xwayland process terminates itself when there are no more X11 clients connected. --- include/wlr/xwayland.h | 1 + include/xwayland/meson.build | 3 +++ xwayland/server.c | 15 ++++++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index d4a483931..165ea944d 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -24,6 +24,7 @@ struct wlr_xwayland_server_options { bool lazy; bool enable_wm; bool no_touch_pointer_emulation; + int terminate_delay; // in seconds, 0 to terminate immediately }; struct wlr_xwayland_server { diff --git a/include/xwayland/meson.build b/include/xwayland/meson.build index 1dad9259b..adec52fcd 100644 --- a/include/xwayland/meson.build +++ b/include/xwayland/meson.build @@ -1,11 +1,13 @@ have_listenfd = false have_no_touch_pointer_emulation = false +have_terminate_delay = false if xwayland.found() xwayland_path = xwayland.get_variable('xwayland') have_listenfd = xwayland.get_variable('have_listenfd', default_value: 'false') == 'true' have_no_touch_pointer_emulation = xwayland.get_variable( 'have_no_touch_pointer_emulation', default_value: 'false') == 'true' + have_terminate_delay = xwayland.get_variable(pkgconfig: 'have_terminate_delay') == 'true' else xwayland_path = xwayland_prog.full_path() endif @@ -14,6 +16,7 @@ xwayland_config_data = configuration_data() xwayland_config_data.set_quoted('XWAYLAND_PATH', xwayland_path) xwayland_config_data.set10('HAVE_XWAYLAND_LISTENFD', have_listenfd) xwayland_config_data.set10('HAVE_XWAYLAND_NO_TOUCH_POINTER_EMULATION', have_no_touch_pointer_emulation) +xwayland_config_data.set10('HAVE_XWAYLAND_TERMINATE_DELAY', have_terminate_delay) configure_file( output: 'config.h', configuration: xwayland_config_data, diff --git a/xwayland/server.c b/xwayland/server.c index e0cf5aa5e..8502fcec5 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -49,9 +49,18 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server, argv[i++] = "Xwayland"; argv[i++] = server->display_name; argv[i++] = "-rootless"; - argv[i++] = "-terminate"; argv[i++] = "-core"; + argv[i++] = "-terminate"; +#if HAVE_XWAYLAND_TERMINATE_DELAY + char terminate_delay[16]; + if (server->options.terminate_delay > 0) { + snprintf(terminate_delay, sizeof(terminate_delay), "%d", + server->options.terminate_delay); + argv[i++] = terminate_delay; + } +#endif + #if HAVE_XWAYLAND_LISTENFD argv[i++] = "-listenfd"; argv[i++] = listenfd0; @@ -436,6 +445,10 @@ struct wlr_xwayland_server *wlr_xwayland_server_create( server->wl_display = wl_display; server->options = *options; +#if !HAVE_XWAYLAND_TERMINATE_DELAY + server->options.terminate_delay = 0; +#endif + server->x_fd[0] = server->x_fd[1] = -1; server->wl_fd[0] = server->wl_fd[1] = -1; server->wm_fd[0] = server->wm_fd[1] = -1; From f575e445ec36dec5fe7f5674a4dae8096a833d6f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 25 Jun 2021 13:49:47 +0200 Subject: [PATCH 087/298] xwayland: terminate when no client is connected Automatically shutdown Xwayland 10s after all X11 clients have gone away. --- include/xwayland/xwm.h | 1 + xwayland/meson.build | 6 ++++++ xwayland/xwayland.c | 3 +++ xwayland/xwm.c | 9 +++++++++ 4 files changed, 19 insertions(+) diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index 0cdf6ea1a..41e35ef39 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -122,6 +122,7 @@ struct wlr_xwm { const xcb_query_extension_reply_t *xfixes; const xcb_query_extension_reply_t *xres; + uint32_t xfixes_major_version; #if HAS_XCB_ERRORS xcb_errors_context_t *errors_context; #endif diff --git a/xwayland/meson.build b/xwayland/meson.build index b7bbcaf1c..4d8ed5f45 100644 --- a/xwayland/meson.build +++ b/xwayland/meson.build @@ -74,3 +74,9 @@ wlr_files += files( ) wlr_deps += xwayland_libs features += { 'xwayland': true } + +have = cc.has_function('xcb_xfixes_set_client_disconnect_mode', dependencies: xwayland_libs) +add_project_arguments( + '-DHAS_XCB_XFIXES_SET_CLIENT_DISCONNECT_MODE=@0@'.format(have.to_int()), + language: 'c', +) diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index e09b05cfc..cb62fcc14 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -88,6 +88,9 @@ struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, struct wlr_xwayland_server_options options = { .lazy = lazy, .enable_wm = true, +#if HAS_XCB_XFIXES_SET_CLIENT_DISCONNECT_MODE + .terminate_delay = lazy ? 10 : 0, +#endif }; xwayland->server = wlr_xwayland_server_create(wl_display, &options); if (xwayland->server == NULL) { diff --git a/xwayland/xwm.c b/xwayland/xwm.c index a80e47643..b398f2abf 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -1842,6 +1842,7 @@ static void xwm_get_resources(struct wlr_xwm *xwm) { wlr_log(WLR_DEBUG, "xfixes version: %" PRIu32 ".%" PRIu32, xfixes_reply->major_version, xfixes_reply->minor_version); + xwm->xfixes_major_version = xfixes_reply->major_version; free(xfixes_reply); @@ -2103,6 +2104,14 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { sizeof(supported)/sizeof(*supported), supported); +#if HAS_XCB_XFIXES_SET_CLIENT_DISCONNECT_MODE + if (xwm->xwayland->server->options.terminate_delay > 0 && + xwm->xfixes_major_version >= 6) { + xcb_xfixes_set_client_disconnect_mode(xwm->xcb_conn, + XCB_XFIXES_CLIENT_DISCONNECT_FLAGS_TERMINATE); + } +#endif + xcb_flush(xwm->xcb_conn); xwm_set_net_active_window(xwm, XCB_WINDOW_NONE); From 12d84f8c36bb8e6e8ea5f7803a91d58d6a554e38 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 3 May 2022 02:50:41 +0200 Subject: [PATCH 088/298] examples/egl_common: switch rgba format The current ARGB2101010 has really "corase" control over the alpha. Particularily, examples/layer-shell would look really strange with certain parameters. For examples, when passing an alpha of 0.84, the box would not appear transparent at all anymore. Patched as suggested by @mstoeckl -- thank you! --- examples/egl_common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/egl_common.c b/examples/egl_common.c index 616715083..f095a4879 100644 --- a/examples/egl_common.c +++ b/examples/egl_common.c @@ -20,10 +20,10 @@ PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT; const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, 1, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; From 0326ceff903660809385e5d46e9239a4d98d9495 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 1 May 2022 16:03:44 +0300 Subject: [PATCH 089/298] examples/layer-shell: premultiply alpha --- examples/layer-shell.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/layer-shell.c b/examples/layer-shell.c index 56a8d4aa5..f2e0aaa71 100644 --- a/examples/layer-shell.c +++ b/examples/layer-shell.c @@ -124,9 +124,10 @@ static void draw(void) { glViewport(0, 0, width, height); if (buttons) { - glClearColor(1, 1, 1, alpha); + glClearColor(alpha, alpha, alpha, alpha); } else { - glClearColor(demo.color[0], demo.color[1], demo.color[2], alpha); + glClearColor(demo.color[0] * alpha, demo.color[1] * alpha, + demo.color[2] * alpha, alpha); } glClear(GL_COLOR_BUFFER_BIT); @@ -151,7 +152,8 @@ static void draw_popup(void) { eglMakeCurrent(egl_display, popup_egl_surface, popup_egl_surface, egl_context); glViewport(0, 0, popup_width, popup_height); - glClearColor(popup_red, 0.5f, 0.5f, popup_alpha); + glClearColor(popup_red * popup_alpha, 0.5f * popup_alpha, + 0.5f * popup_alpha, popup_alpha); popup_alpha += alpha_mod; if (popup_alpha < 0.01 || popup_alpha >= 1.0f) { alpha_mod *= -1.0; From 8b0d4947cc77907f010a69bb9cd212a456cfdf08 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 10 May 2022 14:36:24 +0300 Subject: [PATCH 090/298] xdg-toplevel: store states on the stack --- types/xdg_shell/wlr_xdg_toplevel.c | 66 +++++++----------------------- 1 file changed, 15 insertions(+), 51 deletions(-) diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 786cfdad9..1cb12ec93 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -31,39 +31,19 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( } *configure = toplevel->scheduled; - struct wl_array states; - wl_array_init(&states); + size_t nstates = 0; + uint32_t states[32]; if (configure->maximized) { - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, "Could not allocate state for maximized xdg_toplevel"); - goto error_out; - } - *s = XDG_TOPLEVEL_STATE_MAXIMIZED; + states[nstates++] = XDG_TOPLEVEL_STATE_MAXIMIZED; } if (configure->fullscreen) { - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, "Could not allocate state for fullscreen xdg_toplevel"); - goto error_out; - } - *s = XDG_TOPLEVEL_STATE_FULLSCREEN; + states[nstates++] = XDG_TOPLEVEL_STATE_FULLSCREEN; } if (configure->resizing) { - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, "Could not allocate state for resizing xdg_toplevel"); - goto error_out; - } - *s = XDG_TOPLEVEL_STATE_RESIZING; + states[nstates++] = XDG_TOPLEVEL_STATE_RESIZING; } if (configure->activated) { - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, "Could not allocate state for activated xdg_toplevel"); - goto error_out; - } - *s = XDG_TOPLEVEL_STATE_ACTIVATED; + states[nstates++] = XDG_TOPLEVEL_STATE_ACTIVATED; } if (configure->tiled) { if (wl_resource_get_version(toplevel->resource) >= @@ -82,40 +62,24 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( if ((configure->tiled & tiled[i].edge) == 0) { continue; } - - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, - "Could not allocate state for tiled xdg_toplevel"); - goto error_out; - } - *s = tiled[i].state; + states[nstates++] = tiled[i].state; } } else if (!configure->maximized) { - // This version doesn't support tiling, best we can do is make the - // toplevel maximized - uint32_t *s = wl_array_add(&states, sizeof(uint32_t)); - if (!s) { - wlr_log(WLR_ERROR, - "Could not allocate state for maximized xdg_toplevel"); - goto error_out; - } - *s = XDG_TOPLEVEL_STATE_MAXIMIZED; + states[nstates++] = XDG_TOPLEVEL_STATE_MAXIMIZED; } } + assert(nstates <= sizeof(states) / sizeof(states[0])); uint32_t width = configure->width; uint32_t height = configure->height; - xdg_toplevel_send_configure(toplevel->resource, width, height, &states); + struct wl_array wl_states = { + .size = nstates * sizeof(states[0]), + .data = states, + }; + xdg_toplevel_send_configure(toplevel->resource, + width, height, &wl_states); - wl_array_release(&states); return configure; - -error_out: - wl_array_release(&states); - free(configure); - wl_resource_post_no_memory(toplevel->resource); - return NULL; } void handle_xdg_toplevel_committed(struct wlr_xdg_toplevel *toplevel) { From 7b7562eb658f180ddb8c712803d8c646613a86c3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 19 Mar 2022 13:58:16 +0100 Subject: [PATCH 091/298] backend/headless: allow variable refresh rate Instead of waking up each 16ms to emit a frame event, arm the timer when the output is committed. This allows the headless backend to idle when nothing changes on screen, and behaves similarly to the other backends. --- backend/headless/output.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/headless/output.c b/backend/headless/output.c index f03d6ee0d..10de845f3 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -70,6 +70,8 @@ static bool output_commit(struct wlr_output *wlr_output) { wlr_output_send_present(wlr_output, &present_event); } + wl_event_source_timer_update(output->frame_timer, output->frame_delay); + return true; } @@ -93,7 +95,6 @@ bool wlr_output_is_headless(struct wlr_output *wlr_output) { static int signal_frame(void *data) { struct wlr_headless_output *output = data; wlr_output_send_frame(&output->wlr_output); - wl_event_source_timer_update(output->frame_timer, output->frame_delay); return 0; } From fa9b61004b79460357556b67e95ad2740bf12751 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 19 Mar 2022 14:00:43 +0100 Subject: [PATCH 092/298] tinywl: don't crash when there is no keyboard Running with WLR_BACKENDS=headless, there is no keyboard device. Avoid crashes like so: ../tinywl/tinywl.c:136:2: runtime error: member access within null pointer of type 'struct wlr_keyboard' ../tinywl/tinywl.c:136:2: runtime error: member access within null pointer of type 'struct wlr_keyboard' AddressSanitizer:DEADLYSIGNAL ================================================================= ==331107==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000120 (pc 0x556ed03e4e99 bp 0x7ffce834bc10 sp 0x7ffce834bbb0 T0) ==331107==The signal is caused by a READ memory access. ==331107==Hint: address points to the zero page. #0 0x556ed03e4e99 in focus_view ../tinywl/tinywl.c:136 #1 0x556ed03eb3be in xdg_toplevel_map ../tinywl/tinywl.c:603 #2 0x7f75d6f768db in wlr_signal_emit_safe ../util/signal.c:29 #3 0x7f75d6e9cac7 in xdg_surface_role_commit ../types/xdg_shell/wlr_xdg_surface.c:315 #4 0x7f75d6eb6944 in surface_commit_state ../types/wlr_compositor.c:466 #5 0x7f75d6eb7b02 in surface_handle_commit ../types/wlr_compositor.c:523 #6 0x7f75d5714d49 (/usr/lib/libffi.so.8+0x6d49) #7 0x7f75d5714266 (/usr/lib/libffi.so.8+0x6266) #8 0x7f75d68cb322 (/usr/lib/libwayland-server.so.0+0xd322) #9 0x7f75d68c65cb (/usr/lib/libwayland-server.so.0+0x85cb) #10 0x7f75d68c91c9 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xb1c9) #11 0x7f75d68c6d36 in wl_display_run (/usr/lib/libwayland-server.so.0+0x8d36) #12 0x556ed03eef55 in main ../tinywl/tinywl.c:905 #13 0x7f75d5d2330f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f) #14 0x7f75d5d233c0 in __libc_start_main@GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0) #15 0x556ed03e46e4 in _start (/home/simon/src/wlroots/build/tinywl/tinywl+0x136e4) --- tinywl/tinywl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 7f6de6bc8..633b3f257 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -136,8 +136,10 @@ static void focus_view(struct tinywl_view *view, struct wlr_surface *surface) { * track of this and automatically send key events to the appropriate * clients without additional work on your part. */ - wlr_seat_keyboard_notify_enter(seat, view->xdg_toplevel->base->surface, - keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); + if (keyboard != NULL) { + wlr_seat_keyboard_notify_enter(seat, view->xdg_toplevel->base->surface, + keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); + } } static void keyboard_handle_modifiers( From e646d882cf4949d290fff2ba3b7ae4c124f6f13d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 6 May 2022 11:58:17 +0200 Subject: [PATCH 093/298] backend/drm: fetch EDID manufacturer from udev_hwdb Maintaining our internal table up-to-date is tedious: one needs to manually go through the PnP ID registry [1] and check whether we're missing any entry. udev_hwdb already has an API to fetch a manufacturer name from its PnP ID. Use that instead. [1]: https://uefi.org/pnp_id_list --- backend/drm/backend.c | 26 +++++++++ backend/drm/drm.c | 2 +- backend/drm/util.c | 113 ++++++++++++------------------------- include/backend/drm/drm.h | 1 + include/backend/drm/util.h | 6 +- 5 files changed, 67 insertions(+), 81 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 10f324a02..b9e7274b2 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ static void backend_destroy(struct wlr_backend *backend) { finish_drm_resources(drm); + udev_hwdb_unref(drm->hwdb); free(drm->name); wlr_session_close_file(drm->session, drm->dev); wl_event_source_remove(drm->drm_event); @@ -172,6 +174,23 @@ static void handle_parent_destroy(struct wl_listener *listener, void *data) { backend_destroy(&drm->backend); } +static struct udev_hwdb *create_udev_hwdb(void) { + struct udev *udev = udev_new(); + if (!udev) { + wlr_log(WLR_ERROR, "udev_new failed"); + return NULL; + } + + struct udev_hwdb *hwdb = udev_hwdb_new(udev); + udev_unref(udev); + if (!hwdb) { + wlr_log(WLR_ERROR, "udev_hwdb_new failed"); + return NULL; + } + + return hwdb; +} + struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, struct wlr_session *session, struct wlr_device *dev, struct wlr_backend *parent) { @@ -226,6 +245,12 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, drm->session_active.notify = handle_session_active; wl_signal_add(&session->events.active, &drm->session_active); + drm->hwdb = create_udev_hwdb(); + if (!drm->hwdb) { + wlr_log(WLR_INFO, "Failed to load udev_hwdb, " + "falling back to PnP IDs instead of manufacturer names"); + } + if (!check_drm_features(drm)) { goto error_event; } @@ -275,6 +300,7 @@ error_mgpu_renderer: error_resources: finish_drm_resources(drm); error_event: + udev_hwdb_unref(drm->hwdb); wl_list_remove(&drm->session_active.link); wl_event_source_remove(drm->drm_event); error_fd: diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 5a828426a..af7e7836f 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1314,7 +1314,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, size_t edid_len = 0; uint8_t *edid = get_drm_prop_blob(drm->fd, wlr_conn->id, wlr_conn->props.edid, &edid_len); - parse_edid(&wlr_conn->output, edid_len, edid); + parse_edid(wlr_conn, edid_len, edid); free(edid); char *subconnector = NULL; diff --git a/backend/drm/util.c b/backend/drm/util.c index 3cf656fb3..33446fd75 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -2,9 +2,11 @@ #include #include #include +#include #include #include #include +#include "backend/drm/drm.h" #include "backend/drm/util.h" int32_t calculate_refresh_rate(const drmModeModeInfo *mode) { @@ -26,94 +28,51 @@ int32_t calculate_refresh_rate(const drmModeModeInfo *mode) { return refresh; } -// Constructed from http://edid.tv/manufacturer -static const char *get_manufacturer(uint16_t id) { -#define ID(a, b, c) ((a & 0x1f) << 10) | ((b & 0x1f) << 5) | (c & 0x1f) - switch (id) { - case ID('A', 'A', 'A'): return "Avolites Ltd"; - case ID('A', 'C', 'I'): return "Ancor Communications Inc"; - case ID('A', 'C', 'R'): return "Acer Technologies"; - case ID('A', 'D', 'A'): return "Addi-Data GmbH"; - case ID('A', 'P', 'P'): return "Apple Computer Inc"; - case ID('A', 'S', 'K'): return "Ask A/S"; - case ID('A', 'V', 'T'): return "Avtek (Electronics) Pty Ltd"; - case ID('B', 'N', 'O'): return "Bang & Olufsen"; - case ID('B', 'N', 'Q'): return "BenQ Corporation"; - case ID('C', 'M', 'N'): return "Chimei Innolux Corporation"; - case ID('C', 'M', 'O'): return "Chi Mei Optoelectronics corp."; - case ID('C', 'R', 'O'): return "Extraordinary Technologies PTY Limited"; - case ID('D', 'E', 'L'): return "Dell Inc."; - case ID('D', 'G', 'C'): return "Data General Corporation"; - case ID('D', 'O', 'N'): return "DENON, Ltd."; - case ID('E', 'N', 'C'): return "Eizo Nanao Corporation"; - case ID('E', 'P', 'H'): return "Epiphan Systems Inc."; - case ID('E', 'X', 'P'): return "Data Export Corporation"; - case ID('F', 'N', 'I'): return "Funai Electric Co., Ltd."; - case ID('F', 'U', 'S'): return "Fujitsu Siemens Computers GmbH"; - case ID('G', 'S', 'M'): return "Goldstar Company Ltd"; - case ID('H', 'I', 'Q'): return "Kaohsiung Opto Electronics Americas, Inc."; - case ID('H', 'S', 'D'): return "HannStar Display Corp"; - case ID('H', 'T', 'C'): return "Hitachi Ltd"; - case ID('H', 'W', 'P'): return "Hewlett Packard"; - case ID('I', 'N', 'T'): return "Interphase Corporation"; - case ID('I', 'N', 'X'): return "Communications Supply Corporation (A division of WESCO)"; - case ID('I', 'T', 'E'): return "Integrated Tech Express Inc"; - case ID('I', 'V', 'M'): return "Iiyama North America"; - case ID('L', 'E', 'N'): return "Lenovo Group Limited"; - case ID('M', 'A', 'X'): return "Rogen Tech Distribution Inc"; - case ID('M', 'E', 'G'): return "Abeam Tech Ltd"; - case ID('M', 'E', 'I'): return "Panasonic Industry Company"; - case ID('M', 'T', 'C'): return "Mars-Tech Corporation"; - case ID('M', 'T', 'X'): return "Matrox"; - case ID('N', 'E', 'C'): return "NEC Corporation"; - case ID('N', 'E', 'X'): return "Nexgen Mediatech Inc."; - case ID('O', 'N', 'K'): return "ONKYO Corporation"; - case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD."; - case ID('O', 'T', 'M'): return "Optoma Corporation"; - case ID('O', 'V', 'R'): return "Oculus VR, Inc."; - case ID('P', 'H', 'L'): return "Philips Consumer Electronics Company"; - case ID('P', 'I', 'O'): return "Pioneer Electronic Corporation"; - case ID('P', 'N', 'R'): return "Planar Systems, Inc."; - case ID('Q', 'D', 'S'): return "Quanta Display Inc."; - case ID('R', 'A', 'T'): return "Rent-A-Tech"; - case ID('R', 'E', 'N'): return "Renesas Technology Corp."; - case ID('S', 'A', 'M'): return "Samsung Electric Company"; - case ID('S', 'A', 'N'): return "Sanyo Electric Co., Ltd."; - case ID('S', 'E', 'C'): return "Seiko Epson Corporation"; - case ID('S', 'H', 'P'): return "Sharp Corporation"; - case ID('S', 'I', 'I'): return "Silicon Image, Inc."; - case ID('S', 'N', 'Y'): return "Sony"; - case ID('S', 'T', 'D'): return "STD Computer Inc"; - case ID('S', 'V', 'S'): return "SVSI"; - case ID('S', 'Y', 'N'): return "Synaptics Inc"; - case ID('T', 'C', 'L'): return "Technical Concepts Ltd"; - case ID('T', 'O', 'P'): return "Orion Communications Co., Ltd."; - case ID('T', 'S', 'B'): return "Toshiba America Info Systems Inc"; - case ID('T', 'S', 'T'): return "Transtream Inc"; - case ID('U', 'N', 'K'): return "Unknown"; - case ID('V', 'E', 'S'): return "Vestel Elektronik Sanayi ve Ticaret A. S."; - case ID('V', 'I', 'T'): return "Visitech AS"; - case ID('V', 'I', 'Z'): return "VIZIO, Inc"; - case ID('V', 'L', 'V'): return "Valve"; - case ID('V', 'S', 'C'): return "ViewSonic Corporation"; - case ID('Y', 'M', 'H'): return "Yamaha Corporation"; - default: return "Unknown"; +static const char *get_manufacturer(struct udev_hwdb *hwdb, uint16_t code) { + static char pnp_id[4]; + + // The ASCII 3-letter manufacturer PnP ID is encoded in 5-bit codes + pnp_id[0] = ((code >> 10) & 0x1F) + '@'; + pnp_id[1] = ((code >> 5) & 0x1F) + '@'; + pnp_id[2] = ((code >> 0) & 0x1F) + '@'; + pnp_id[3] = '\0'; + + if (hwdb == NULL) { + return pnp_id; } -#undef ID + + char query[32]; + snprintf(query, sizeof(query), "acpi:%s:", pnp_id); + struct udev_list_entry *acpi_entry = + udev_hwdb_get_properties_list_entry(hwdb, query, 0); + if (acpi_entry == NULL) { + return pnp_id; + } + + struct udev_list_entry *vendor_entry = + udev_list_entry_get_by_name(acpi_entry, "ID_VENDOR_FROM_DATABASE"); + if (vendor_entry == NULL) { + return pnp_id; + } + + return udev_list_entry_get_value(vendor_entry); } /* See https://en.wikipedia.org/wiki/Extended_Display_Identification_Data for layout of EDID data. * We don't parse the EDID properly. We just expect to receive valid data. */ -void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data) { +void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) { + struct wlr_output *output = &conn->output; + if (!data || len < 128) { - snprintf(output->make, sizeof(output->make), ""); - snprintf(output->model, sizeof(output->model), ""); + snprintf(output->make, sizeof(output->make), "Unknown"); + snprintf(output->model, sizeof(output->model), "Unknown"); return; } uint16_t id = (data[8] << 8) | data[9]; - snprintf(output->make, sizeof(output->make), "%s", get_manufacturer(id)); + snprintf(output->make, sizeof(output->make), "%s", + get_manufacturer(conn->backend->hwdb, id)); uint16_t model = data[10] | (data[11] << 8); snprintf(output->model, sizeof(output->model), "0x%04X", model); diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index c5d3358f9..dbc47364b 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -58,6 +58,7 @@ struct wlr_drm_backend { const struct wlr_drm_interface *iface; clockid_t clock; bool addfb2_modifiers; + struct udev_hwdb *hwdb; int fd; char *name; diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h index b4cdee7d7..323894b56 100644 --- a/include/backend/drm/util.h +++ b/include/backend/drm/util.h @@ -2,15 +2,15 @@ #define BACKEND_DRM_UTIL_H #include -#include #include #include +struct wlr_drm_connector; + // Calculates a more accurate refresh rate (mHz) than what mode itself provides int32_t calculate_refresh_rate(const drmModeModeInfo *mode); // Populates the make/model/phys_{width,height} of output from the edid data -void parse_edid(struct wlr_output *restrict output, size_t len, - const uint8_t *data); +void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data); // Returns the string representation of a DRM output type const char *conn_get_name(uint32_t type_id); From 19896e7fb63db73c4a66b68a79d7cbd039198a1d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 12 May 2022 19:58:50 +0200 Subject: [PATCH 094/298] util/shm: clear mode permission bits in allocate_shm_file_pair This ensures the file cannot be re-opened with write permissions. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3429 --- util/shm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/util/shm.c b/util/shm.c index e0d84e8e7..6fddebbb8 100644 --- a/util/shm.c +++ b/util/shm.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,14 @@ bool allocate_shm_file_pair(size_t size, int *rw_fd_ptr, int *ro_fd_ptr) { shm_unlink(name); + // Make sure the file cannot be re-opened in read-write mode (e.g. via + // "/proc/self/fd/" on Linux) + if (fchmod(rw_fd, 0) != 0) { + close(rw_fd); + close(ro_fd); + return false; + } + int ret; do { ret = ftruncate(rw_fd, size); From 8fe3aa29da56be16faa73aca947647bd60cd4a94 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 11 May 2022 13:57:51 +0200 Subject: [PATCH 095/298] xdg-shell: specify version in wlr_xdg_shell_create With protocol additions such as [1], compositors currently have no way to opt out of the version upgrade. The protocol upgrade will always be backwards-compatible but may require new compositor features. The status quo doesn't make it possible to ship a protocol addition without breaking the wlroots API. This will be an issue for API stabilization [2]. To address this, let compositors provide a maximum version in the function creating the global. We need to support all previous versions of the interface anyways because of older clients. This mechanism works the same way as Wayland clients passing a version in wl_global.bind. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3514 [2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1008 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3397 --- examples/scene-graph.c | 2 +- include/wlr/types/wlr_xdg_shell.h | 7 ++++++- tinywl/tinywl.c | 7 ++++--- types/xdg_shell/wlr_xdg_shell.c | 8 ++++++-- types/xdg_shell/wlr_xdg_toplevel.c | 3 ++- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/examples/scene-graph.c b/examples/scene-graph.c index c3ce05893..f57ef1f2d 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) { struct wlr_compositor *compositor = wlr_compositor_create(server.display, server.renderer); - wlr_xdg_shell_create(server.display); + wlr_xdg_shell_create(server.display, 2); server.new_output.notify = server_handle_new_output; wl_signal_add(&server.backend->events.new_output, &server.new_output); diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 95c6ee6c1..e61683171 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -17,6 +17,7 @@ struct wlr_xdg_shell { struct wl_global *global; + uint32_t version; struct wl_list clients; struct wl_list popup_grabs; uint32_t ping_timeout; @@ -263,7 +264,11 @@ struct wlr_xdg_toplevel_show_window_menu_event { uint32_t x, y; }; -struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display); +/** + * Create the xdg_wm_base global with the specified version. + */ +struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display, + uint32_t version); /** Get the corresponding wlr_xdg_surface from a resource. * diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 633b3f257..783cc1828 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -853,13 +853,14 @@ int main(int argc, char *argv[]) { server.scene = wlr_scene_create(); wlr_scene_attach_output_layout(server.scene, server.output_layout); - /* Set up the xdg-shell. The xdg-shell is a Wayland protocol which is used - * for application windows. For more detail on shells, refer to my article: + /* Set up xdg-shell version 2. The xdg-shell is a Wayland protocol which is + * used for application windows. For more detail on shells, refer to my + * article: * * https://drewdevault.com/2018/07/29/Wayland-shells.html */ wl_list_init(&server.views); - server.xdg_shell = wlr_xdg_shell_create(server.wl_display); + server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 2); server.new_xdg_surface.notify = server_new_xdg_surface; wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface); diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 0b1302622..0d40b553d 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -137,20 +137,24 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { free(xdg_shell); } -struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display) { +struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display, + uint32_t version) { + assert(version <= WM_BASE_VERSION); + struct wlr_xdg_shell *xdg_shell = calloc(1, sizeof(struct wlr_xdg_shell)); if (!xdg_shell) { return NULL; } + xdg_shell->version = version; xdg_shell->ping_timeout = 10000; wl_list_init(&xdg_shell->clients); wl_list_init(&xdg_shell->popup_grabs); struct wl_global *global = wl_global_create(display, - &xdg_wm_base_interface, WM_BASE_VERSION, xdg_shell, xdg_shell_bind); + &xdg_wm_base_interface, version, xdg_shell, xdg_shell_bind); if (!global) { free(xdg_shell); return NULL; diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 1cb12ec93..750efedac 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -114,7 +114,7 @@ void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel, if (toplevel->parent) { wl_list_remove(&toplevel->parent_unmap.link); } - + if (parent && parent->base->mapped) { toplevel->parent = parent; toplevel->parent_unmap.notify = handle_parent_unmap; @@ -497,6 +497,7 @@ uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_toplevel *toplevel, uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, uint32_t tiled) { + assert(toplevel->base->client->shell->version >= 2); toplevel->scheduled.tiled = tiled; return wlr_xdg_surface_schedule_configure(toplevel->base); } From 039a31df9a8708cdc0d054c105b4d078b3817dea Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:16:52 -0400 Subject: [PATCH 096/298] wlr_scene: Allow buffer in wlr_scene_buffer to be NULL This is useful to emulate an unmapped surface. --- include/wlr/types/wlr_scene.h | 4 ++++ types/scene/wlr_scene.c | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 7c2238fb9..6cc842b46 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -107,6 +107,8 @@ struct wlr_scene_rect { /** A scene-graph node displaying a buffer */ struct wlr_scene_buffer { struct wlr_scene_node node; + + // May be NULL struct wlr_buffer *buffer; // private state @@ -267,6 +269,8 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta /** * Add a node displaying a buffer to the scene-graph. + * + * If the buffer is NULL, this node will not be displayed. */ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, struct wlr_buffer *buffer); diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index d88dd55f2..777f8cb63 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -358,7 +358,9 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, } scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent); - scene_buffer->buffer = wlr_buffer_lock(buffer); + if (buffer) { + scene_buffer->buffer = wlr_buffer_lock(buffer); + } scene_node_damage_whole(&scene_buffer->node); @@ -447,7 +449,7 @@ static void scene_node_get_size(struct wlr_scene_node *node, if (scene_buffer->dst_width > 0 && scene_buffer->dst_height > 0) { *width = scene_buffer->dst_width; *height = scene_buffer->dst_height; - } else { + } else if (scene_buffer->buffer) { if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) { *height = scene_buffer->buffer->width; *width = scene_buffer->buffer->height; @@ -838,6 +840,9 @@ static void render_node_iterator(struct wlr_scene_node *node, break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + if (!scene_buffer->buffer) { + return; + } struct wlr_renderer *renderer = output->renderer; texture = scene_buffer_get_texture(scene_buffer, renderer); From 61dab42c70fd3e0ee211a8b52f387b0c1018510f Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:17:51 -0400 Subject: [PATCH 097/298] wlr_scene: Add setter for buffer of a wlr_scene_buffer --- include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 6cc842b46..eaa7b07c4 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -275,6 +275,14 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, struct wlr_buffer *buffer); +/** + * Sets the buffer's backing buffer. + * + * If the buffer is NULL, the buffer node will not be displayed. + */ +void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, + struct wlr_buffer *buffer); + /** * Set the source rectangle describing the region of the buffer which will be * sampled to render this node. This allows cropping the buffer. diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 777f8cb63..e1e381de4 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -367,6 +367,27 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, return scene_buffer; } +void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, + struct wlr_buffer *buffer) { + if (buffer == scene_buffer->buffer) { + return; + } + + scene_node_damage_whole(&scene_buffer->node); + + wlr_texture_destroy(scene_buffer->texture); + scene_buffer->texture = NULL; + wlr_buffer_unlock(scene_buffer->buffer); + + if (buffer) { + scene_buffer->buffer = wlr_buffer_lock(buffer); + } else { + scene_buffer->buffer = NULL; + } + + scene_node_damage_whole(&scene_buffer->node); +} + void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, const struct wlr_fbox *box) { struct wlr_fbox *cur = &scene_buffer->src_box; From 6ddb9e51bd90b0074402c3e4c361f83adb0e402a Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 16 Apr 2022 05:39:22 -0400 Subject: [PATCH 098/298] wlr_scene_output: Send output leave events before destroying the output --- types/scene/wlr_scene.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index e1e381de4..656f6626a 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -982,12 +982,12 @@ static void scene_output_send_leave_iterator(struct wlr_surface *surface, } void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { - wlr_addon_finish(&scene_output->addon); - wl_list_remove(&scene_output->link); - wlr_scene_output_for_each_surface(scene_output, scene_output_send_leave_iterator, scene_output->output); + wlr_addon_finish(&scene_output->addon); + wl_list_remove(&scene_output->link); + free(scene_output); } From c46b53d0b04e52b73cfe041e4bc87656b1d1ce94 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 18 May 2022 18:08:35 -0400 Subject: [PATCH 099/298] wlr_scene: Add output_enter/output_leave signals When we destroy a scene buffer, let's make sure that we call output_leave signals before we finish the node which will call destroy listeners. --- include/wlr/types/wlr_scene.h | 7 ++ types/scene/wlr_scene.c | 167 ++++++++++++++++++++++++---------- 2 files changed, 128 insertions(+), 46 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index eaa7b07c4..a02a5c89f 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -111,8 +111,14 @@ struct wlr_scene_buffer { // May be NULL struct wlr_buffer *buffer; + struct { + struct wl_signal output_enter; // struct wlr_scene_output + struct wl_signal output_leave; // struct wlr_scene_output + } events; + // private state + uint64_t active_outputs; struct wlr_texture *texture; struct wlr_fbox src_box; int dst_width, dst_height; @@ -132,6 +138,7 @@ struct wlr_scene_output { // private state + uint8_t index; bool prev_scanout; }; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 656f6626a..5eb8165d8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -17,11 +17,6 @@ static struct wlr_scene *scene_root_from_node(struct wlr_scene_node *node) { return (struct wlr_scene *)node; } -static struct wlr_scene_tree *scene_tree_from_node(struct wlr_scene_node *node) { - assert(node->type == WLR_SCENE_NODE_TREE); - return (struct wlr_scene_tree *)node; -} - struct wlr_scene_surface *wlr_scene_surface_from_node( struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_SURFACE); @@ -73,18 +68,6 @@ static void scene_node_init(struct wlr_scene_node *node, } } -static void scene_node_finish(struct wlr_scene_node *node) { - wlr_signal_emit_safe(&node->events.destroy, NULL); - - struct wlr_scene_node *child, *child_tmp; - wl_list_for_each_safe(child, child_tmp, - &node->state.children, state.link) { - wlr_scene_node_destroy(child); - } - - scene_node_state_finish(&node->state); -} - static void scene_node_damage_whole(struct wlr_scene_node *node); void wlr_scene_node_destroy(struct wlr_scene_node *node) { @@ -93,7 +76,11 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } scene_node_damage_whole(node); - scene_node_finish(node); + + // We want to call the destroy listeners before we do anything else + // in case the destroy signal would like to remove children before they + // are recursively destroyed. + wlr_signal_emit_safe(&node->events.destroy, NULL); struct wlr_scene *scene = scene_node_get_root(node); struct wlr_scene_output *scene_output; @@ -105,12 +92,6 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } wl_list_remove(&scene->presentation_destroy.link); - - free(scene); - break; - case WLR_SCENE_NODE_TREE:; - struct wlr_scene_tree *tree = scene_tree_from_node(node); - free(tree); break; case WLR_SCENE_NODE_SURFACE:; struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); @@ -123,20 +104,36 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wl_list_remove(&scene_surface->surface_commit.link); wl_list_remove(&scene_surface->surface_destroy.link); - - free(scene_surface); - break; - case WLR_SCENE_NODE_RECT:; - struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); - free(scene_rect); break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + + uint64_t active = scene_buffer->active_outputs; + if (active) { + wl_list_for_each(scene_output, &scene->outputs, link) { + if (active & (1ull << scene_output->index)) { + wlr_signal_emit_safe(&scene_buffer->events.output_leave, + scene_output); + } + } + } + wlr_texture_destroy(scene_buffer->texture); wlr_buffer_unlock(scene_buffer->buffer); - free(scene_buffer); + break; + case WLR_SCENE_NODE_TREE: + case WLR_SCENE_NODE_RECT: break; } + + struct wlr_scene_node *child, *child_tmp; + wl_list_for_each_safe(child, child_tmp, + &node->state.children, state.link) { + wlr_scene_node_destroy(child); + } + + scene_node_state_finish(&node->state); + free(node); } struct wlr_scene *wlr_scene_create(void) { @@ -167,6 +164,8 @@ static void scene_surface_handle_surface_destroy(struct wl_listener *listener, wlr_scene_node_destroy(&scene_surface->node); } +static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); + // This function must be called whenever the coordinates/dimensions of a scene // surface or scene output change. It is not necessary to call when a scene // surface's node is enabled/disabled or obscured by other nodes. To quote the @@ -210,26 +209,62 @@ static void scene_surface_update_outputs( } } -static void scene_node_update_surface_outputs_iterator( +// This function must be called whenever the coordinates/dimensions of a scene +// buffer or scene output change. It is not necessary to call when a scene +// buffer's node is enabled/disabled or obscured by other nodes. +static void scene_buffer_update_outputs( + struct wlr_scene_buffer *scene_buffer, + int lx, int ly, struct wlr_scene *scene) { + struct wlr_box buffer_box = { .x = lx, .y = ly }; + scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height); + + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output, &scene->outputs, link) { + struct wlr_box output_box = { + .x = scene_output->x, + .y = scene_output->y, + }; + wlr_output_effective_resolution(scene_output->output, + &output_box.width, &output_box.height); + + struct wlr_box intersection; + bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box); + bool intersects_before = scene_buffer->active_outputs & (1ull << scene_output->index); + + if (intersects && !intersects_before) { + scene_buffer->active_outputs |= 1ull << scene_output->index; + wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output); + } else if (!intersects && intersects_before) { + scene_buffer->active_outputs &= ~(1ull << scene_output->index); + wlr_signal_emit_safe(&scene_buffer->events.output_leave, scene_output); + } + } +} + +static void _scene_node_update_outputs( struct wlr_scene_node *node, int lx, int ly, struct wlr_scene *scene) { if (node->type == WLR_SCENE_NODE_SURFACE) { struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); scene_surface_update_outputs(scene_surface, lx, ly, scene); + } else if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = + scene_buffer_from_node(node); + scene_buffer_update_outputs(scene_buffer, lx, ly, scene); } struct wlr_scene_node *child; wl_list_for_each(child, &node->state.children, state.link) { - scene_node_update_surface_outputs_iterator(child, lx + child->state.x, + _scene_node_update_outputs(child, lx + child->state.x, ly + child->state.y, scene); } } -static void scene_node_update_surface_outputs(struct wlr_scene_node *node) { +static void scene_node_update_outputs(struct wlr_scene_node *node) { struct wlr_scene *scene = scene_node_get_root(node); int lx, ly; wlr_scene_node_coords(node, &lx, &ly); - scene_node_update_surface_outputs_iterator(node, lx, ly, scene); + _scene_node_update_outputs(node, lx, ly, scene); } static void scene_surface_handle_surface_commit(struct wl_listener *listener, @@ -307,7 +342,7 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent scene_node_damage_whole(&scene_surface->node); - scene_node_update_surface_outputs(&scene_surface->node); + scene_node_update_outputs(&scene_surface->node); return scene_surface; } @@ -362,8 +397,13 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, scene_buffer->buffer = wlr_buffer_lock(buffer); } + wl_signal_init(&scene_buffer->events.output_enter); + wl_signal_init(&scene_buffer->events.output_leave); + scene_node_damage_whole(&scene_buffer->node); + scene_node_update_outputs(&scene_buffer->node); + return scene_buffer; } @@ -386,6 +426,8 @@ void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, } scene_node_damage_whole(&scene_buffer->node); + + scene_node_update_outputs(&scene_buffer->node); } void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, @@ -415,6 +457,8 @@ void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, scene_buffer->dst_width = width; scene_buffer->dst_height = height; scene_node_damage_whole(&scene_buffer->node); + + scene_node_update_outputs(&scene_buffer->node); } void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, @@ -559,7 +603,7 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) { node->state.y = y; scene_node_damage_whole(node); - scene_node_update_surface_outputs(node); + scene_node_update_outputs(node); } void wlr_scene_node_place_above(struct wlr_scene_node *node, @@ -634,7 +678,7 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, scene_node_damage_whole(node); - scene_node_update_surface_outputs(node); + scene_node_update_outputs(node); } bool wlr_scene_node_coords(struct wlr_scene_node *node, @@ -968,22 +1012,53 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, scene_output->output = output; scene_output->scene = scene; wlr_addon_init(&scene_output->addon, &output->addons, scene, &output_addon_impl); - wl_list_insert(&scene->outputs, &scene_output->link); + + int prev_output_index = -1; + struct wl_list *prev_output_link = &scene->outputs; + + struct wlr_scene_output *current_output; + wl_list_for_each(current_output, &scene->outputs, link) { + if (prev_output_index + 1 != current_output->index) { + break; + } + + prev_output_index = current_output->index; + prev_output_link = ¤t_output->link; + } + + scene_output->index = prev_output_index + 1; + assert(scene_output->index < 64); + wl_list_insert(prev_output_link, &scene_output->link); wlr_output_damage_add_whole(scene_output->damage); return scene_output; } -static void scene_output_send_leave_iterator(struct wlr_surface *surface, - int sx, int sy, void *data) { - struct wlr_output *output = data; - wlr_surface_send_leave(surface, output); +static void scene_node_remove_output(struct wlr_scene_node *node, + struct wlr_scene_output *output) { + if (node->type == WLR_SCENE_NODE_SURFACE) { + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_from_node(node); + wlr_surface_send_leave(scene_surface->surface, output->output); + } else if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = + scene_buffer_from_node(node); + uint64_t mask = 1ull << output->index; + if (scene_buffer->active_outputs & mask) { + scene_buffer->active_outputs &= ~mask; + wlr_signal_emit_safe(&scene_buffer->events.output_leave, output); + } + } + + struct wlr_scene_node *child; + wl_list_for_each(child, &node->state.children, state.link) { + scene_node_remove_output(child, output); + } } void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { - wlr_scene_output_for_each_surface(scene_output, - scene_output_send_leave_iterator, scene_output->output); + scene_node_remove_output(&scene_output->scene->node, scene_output); wlr_addon_finish(&scene_output->addon); wl_list_remove(&scene_output->link); @@ -1013,7 +1088,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output->y = ly; wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_surface_outputs(&scene_output->scene->node); + scene_node_update_outputs(&scene_output->scene->node); } struct check_scanout_data { From 933ff0e60c423721403b55295bd3d309b010bd8c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:01:03 -0400 Subject: [PATCH 100/298] wlr_scene: Fix missing calls to scene_node_update_outputs There were a couple places this was missing - on mode change of an output. If the resolution changes for example nodes may fall out of the view. - on commits on an output for scale or transform changes - when the transform of a buffer is changed. If the dest size is not set, the buffer may have been rotated potentially changing its size if the buffer width != height --- include/wlr/types/wlr_scene.h | 3 +++ types/scene/wlr_scene.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index a02a5c89f..b48aeff89 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -140,6 +140,9 @@ struct wlr_scene_output { uint8_t index; bool prev_scanout; + + struct wl_listener output_commit; + struct wl_listener output_mode; }; /** A layer shell scene helper */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 5eb8165d8..52d8d00b0 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -470,6 +470,8 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, scene_node_damage_whole(&scene_buffer->node); scene_buffer->transform = transform; scene_node_damage_whole(&scene_buffer->node); + + scene_node_update_outputs(&scene_buffer->node); } static struct wlr_texture *scene_buffer_get_texture( @@ -996,6 +998,24 @@ static const struct wlr_addon_interface output_addon_impl = { .destroy = scene_output_handle_destroy, }; +static void scene_output_handle_commit(struct wl_listener *listener, void *data) { + struct wlr_scene_output *scene_output = wl_container_of(listener, + scene_output, output_commit); + struct wlr_output_event_commit *event = data; + + if (event->committed & (WLR_OUTPUT_STATE_MODE | + WLR_OUTPUT_STATE_TRANSFORM | + WLR_OUTPUT_STATE_SCALE)) { + scene_node_update_outputs(&scene_output->scene->node); + } +} + +static void scene_output_handle_mode(struct wl_listener *listener, void *data) { + struct wlr_scene_output *scene_output = wl_container_of(listener, + scene_output, output_mode); + scene_node_update_outputs(&scene_output->scene->node); +} + struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, struct wlr_output *output) { struct wlr_scene_output *scene_output = calloc(1, sizeof(*scene_output)); @@ -1030,7 +1050,14 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, assert(scene_output->index < 64); wl_list_insert(prev_output_link, &scene_output->link); + scene_output->output_commit.notify = scene_output_handle_commit; + wl_signal_add(&output->events.commit, &scene_output->output_commit); + + scene_output->output_mode.notify = scene_output_handle_mode; + wl_signal_add(&output->events.mode, &scene_output->output_mode); + wlr_output_damage_add_whole(scene_output->damage); + scene_node_update_outputs(&scene->node); return scene_output; } @@ -1062,6 +1089,8 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wlr_addon_finish(&scene_output->addon); wl_list_remove(&scene_output->link); + wl_list_remove(&scene_output->output_commit.link); + wl_list_remove(&scene_output->output_mode.link); free(scene_output); } From 7e383c6a6ae0c794a0e52148d237e90e9e0d5dff Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 6 Apr 2022 07:59:54 -0400 Subject: [PATCH 101/298] wlr_scene: Make wlr_scene_render_output private This function sidesteps damage tracking and output awareness on buffers/surfaces. This function isn't a great fit for the API. Let's also inline the function and simplify it. --- include/wlr/types/wlr_scene.h | 8 -------- types/scene/wlr_scene.c | 36 +++++++++-------------------------- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index b48aeff89..c4b171e31 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -225,14 +225,6 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, * Create a new scene-graph. */ struct wlr_scene *wlr_scene_create(void); -/** - * Manually render the scene-graph on an output. The compositor needs to call - * wlr_renderer_begin before and wlr_renderer_end after calling this function. - * Damage is given in output-buffer-local coordinates and can be set to NULL to - * disable damage tracking. - */ -void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, - int lx, int ly, pixman_region32_t *damage); /** * Handle presentation feedback for all surfaces in the scene, assuming that * scene outputs and the scene rendering functions are used. diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 52d8d00b0..3de721f75 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -945,31 +945,6 @@ static void scene_node_for_each_node(struct wlr_scene_node *node, } } -void wlr_scene_render_output(struct wlr_scene *scene, struct wlr_output *output, - int lx, int ly, pixman_region32_t *damage) { - pixman_region32_t full_region; - pixman_region32_init_rect(&full_region, 0, 0, output->width, output->height); - if (damage == NULL) { - damage = &full_region; - } - - struct wlr_renderer *renderer = output->renderer; - assert(renderer); - - if (output->enabled && pixman_region32_not_empty(damage)) { - struct render_data data = { - .output = output, - .damage = damage, - .presentation = scene->presentation, - }; - scene_node_for_each_node(&scene->node, -lx, -ly, - render_node_iterator, &data); - wlr_renderer_scissor(renderer, NULL); - } - - pixman_region32_fini(&full_region); -} - static void scene_handle_presentation_destroy(struct wl_listener *listener, void *data) { struct wlr_scene *scene = @@ -1254,8 +1229,15 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_renderer_clear(renderer, (float[4]){ 0.0, 0.0, 0.0, 1.0 }); } - wlr_scene_render_output(scene_output->scene, output, - scene_output->x, scene_output->y, &damage); + struct render_data data = { + .output = output, + .damage = &damage, + .presentation = scene_output->scene->presentation, + }; + scene_node_for_each_node(&scene_output->scene->node, + -scene_output->x, -scene_output->y, + render_node_iterator, &data); + wlr_renderer_scissor(renderer, NULL); wlr_output_render_software_cursors(output, &damage); wlr_renderer_end(renderer); From dfeb1309a83ef3ab5ceb189d0b721c2b7cf5680c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:21:21 -0400 Subject: [PATCH 102/298] wlr_scene: Add presentation signal for wlr_scene_buffer --- include/wlr/types/wlr_scene.h | 1 + types/scene/wlr_scene.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index c4b171e31..99d6ca61d 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -114,6 +114,7 @@ struct wlr_scene_buffer { struct { struct wl_signal output_enter; // struct wlr_scene_output struct wl_signal output_leave; // struct wlr_scene_output + struct wl_signal output_present; // struct wlr_scene_output } events; // private state diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 3de721f75..86d75ab3f 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -399,6 +399,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, wl_signal_init(&scene_buffer->events.output_enter); wl_signal_init(&scene_buffer->events.output_leave); + wl_signal_init(&scene_buffer->events.output_present); scene_node_damage_whole(&scene_buffer->node); @@ -847,7 +848,7 @@ static void render_texture(struct wlr_output *output, } struct render_data { - struct wlr_output *output; + struct wlr_scene_output *scene_output; pixman_region32_t *damage; // May be NULL @@ -857,7 +858,8 @@ struct render_data { static void render_node_iterator(struct wlr_scene_node *node, int x, int y, void *_data) { struct render_data *data = _data; - struct wlr_output *output = data->output; + struct wlr_scene_output *scene_output = data->scene_output; + struct wlr_output *output = scene_output->output; pixman_region32_t *output_damage = data->damage; struct wlr_box dst_box = { @@ -923,6 +925,8 @@ static void render_node_iterator(struct wlr_scene_node *node, render_texture(output, output_damage, texture, &scene_buffer->src_box, &dst_box, matrix); + + wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); break; } } @@ -1184,6 +1188,12 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { } } + if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = + scene_buffer_from_node(node); + wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); + } + return wlr_output_commit(output); } @@ -1230,7 +1240,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { } struct render_data data = { - .output = output, + .scene_output = scene_output, .damage = &damage, .presentation = scene_output->scene->presentation, }; From a53eccf2af16cef55bb5ad85204545601584e15e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 24 Apr 2022 22:32:58 -0400 Subject: [PATCH 103/298] wlr_scene: Add primary_output property to wlr_scene_buffer --- include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 99d6ca61d..a4d05274b 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -117,6 +117,14 @@ struct wlr_scene_buffer { struct wl_signal output_present; // struct wlr_scene_output } events; + /** + * The output that the largest area of this buffer is displayed on. + * This may be NULL if the buffer is not currently displayed on any + * outputs. This is the output that should be used for frame callbacks, + * presentation feedback, etc. + */ + struct wlr_scene_output *primary_output; + // private state uint64_t active_outputs; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 86d75ab3f..cdb04c9e8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -218,6 +218,9 @@ static void scene_buffer_update_outputs( struct wlr_box buffer_box = { .x = lx, .y = ly }; scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height); + int largest_overlap = 0; + scene_buffer->primary_output = NULL; + struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { struct wlr_box output_box = { @@ -231,6 +234,14 @@ static void scene_buffer_update_outputs( bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box); bool intersects_before = scene_buffer->active_outputs & (1ull << scene_output->index); + if (intersects) { + int overlap = intersection.width * intersection.height; + if (overlap > largest_overlap) { + largest_overlap = overlap; + scene_buffer->primary_output = scene_output; + } + } + if (intersects && !intersects_before) { scene_buffer->active_outputs |= 1ull << scene_output->index; wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output); From 09c7fe0f904d4e91cce2a9414e2bcfe050f0c8d4 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:23:10 -0400 Subject: [PATCH 104/298] wlr_scene: Add frame_done signal for wlr_scene_buffer Let's also change the name of the function. Motivation [1]. [1] https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3496#note_1357824 --- include/wlr/types/wlr_scene.h | 7 +++++++ types/scene/wlr_scene.c | 27 +++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index a4d05274b..6e7b34401 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -115,6 +115,7 @@ struct wlr_scene_buffer { struct wl_signal output_enter; // struct wlr_scene_output struct wl_signal output_leave; // struct wlr_scene_output struct wl_signal output_present; // struct wlr_scene_output + struct wl_signal frame_done; // struct timespec } events; /** @@ -319,6 +320,12 @@ void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, enum wl_output_transform transform); +/** + * Calls the buffer's frame_done signal. + */ +void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, + struct timespec *now); + /** * Add a viewport for the specified output to the scene-graph. * diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index cdb04c9e8..87f571d9c 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -411,6 +411,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, wl_signal_init(&scene_buffer->events.output_enter); wl_signal_init(&scene_buffer->events.output_leave); wl_signal_init(&scene_buffer->events.output_present); + wl_signal_init(&scene_buffer->events.frame_done); scene_node_damage_whole(&scene_buffer->node); @@ -486,6 +487,11 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, scene_node_update_outputs(&scene_buffer->node); } +void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, + struct timespec *now) { + wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); +} + static struct wlr_texture *scene_buffer_get_texture( struct wlr_scene_buffer *scene_buffer, struct wlr_renderer *renderer) { struct wlr_client_buffer *client_buffer = @@ -1280,8 +1286,8 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { return wlr_output_commit(output); } -static void scene_output_send_frame_done_iterator(struct wlr_scene_node *node, - struct wlr_output *output, struct timespec *now) { +static void scene_node_send_frame_done(struct wlr_scene_node *node, + struct wlr_scene_output *scene_output, struct timespec *now) { if (!node->state.enabled) { return; } @@ -1289,21 +1295,30 @@ static void scene_output_send_frame_done_iterator(struct wlr_scene_node *node, if (node->type == WLR_SCENE_NODE_SURFACE) { struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - if (scene_surface->primary_output == output) { + if (scene_surface->primary_output == scene_output->output) { wlr_surface_send_frame_done(scene_surface->surface, now); } } + if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = + scene_buffer_from_node(node); + + if (scene_buffer->primary_output == scene_output) { + wlr_scene_buffer_send_frame_done(scene_buffer, now); + } + } + struct wlr_scene_node *child; wl_list_for_each(child, &node->state.children, state.link) { - scene_output_send_frame_done_iterator(child, output, now); + scene_node_send_frame_done(child, scene_output, now); } } void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, struct timespec *now) { - scene_output_send_frame_done_iterator(&scene_output->scene->node, - scene_output->output, now); + scene_node_send_frame_done(&scene_output->scene->node, + scene_output, now); } static void scene_output_for_each_surface(const struct wlr_box *output_box, From 34be5da072ed452be50b6d3664a97cfa5bb62521 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:24:05 -0400 Subject: [PATCH 105/298] wlr_scene: Add a way to choose when input interactions happen on a buffer --- include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 6e7b34401..4c1f5ea9b 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -28,6 +28,11 @@ struct wlr_output_layout; struct wlr_xdg_surface; struct wlr_layer_surface_v1; +struct wlr_scene_buffer; + +typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)( + struct wlr_scene_buffer *buffer, int sx, int sy); + enum wlr_scene_node_type { WLR_SCENE_NODE_ROOT, WLR_SCENE_NODE_TREE, @@ -118,6 +123,9 @@ struct wlr_scene_buffer { struct wl_signal frame_done; // struct timespec } events; + // May be NULL + wlr_scene_buffer_point_accepts_input_func_t point_accepts_input; + /** * The output that the largest area of this buffer is displayed on. * This may be NULL if the buffer is not currently displayed on any diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 87f571d9c..5c110c3a8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -771,12 +771,22 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); intersects = wlr_surface_point_accepts_input(scene_surface->surface, lx, ly); break; - case WLR_SCENE_NODE_RECT: - case WLR_SCENE_NODE_BUFFER:; + case WLR_SCENE_NODE_RECT:; int width, height; scene_node_get_size(node, &width, &height); intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; break; + case WLR_SCENE_NODE_BUFFER:; + struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + + if (scene_buffer->point_accepts_input) { + intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly); + } else { + int width, height; + scene_node_get_size(node, &width, &height); + intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; + } + break; } if (intersects) { From 73a656e8ac1523a09323101f95700e8ec388bee6 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 18 May 2022 22:37:05 -0400 Subject: [PATCH 106/298] wlr_scene: Add a function to also specify damage when applying a buffer to wlr_scene_buffer --- include/wlr/types/wlr_scene.h | 9 ++++ types/scene/wlr_scene.c | 97 +++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 4c1f5ea9b..033d4cc64 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -303,6 +303,15 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, struct wlr_buffer *buffer); +/** + * Sets the buffer's backing buffer with a custom damage region. + * + * The damage region is in buffer-local coordinates. If the region is NULL, + * the whole buffer node will be damaged. + */ +void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, + struct wlr_buffer *buffer, pixman_region32_t *region); + /** * Set the source rectangle describing the region of the buffer which will be * sampled to render this node. This allows cropping the buffer. diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 5c110c3a8..96b70df50 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -420,27 +420,94 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, return scene_buffer; } -void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, - struct wlr_buffer *buffer) { - if (buffer == scene_buffer->buffer) { +void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, + struct wlr_buffer *buffer, pixman_region32_t *damage) { + // specifying a region for a NULL buffer doesn't make sense. We need to know + // about the buffer to scale the buffer local coordinates down to scene + // coordinates. + assert(buffer || !damage); + + if (buffer != scene_buffer->buffer) { + if (!damage) { + scene_node_damage_whole(&scene_buffer->node); + } + + wlr_texture_destroy(scene_buffer->texture); + scene_buffer->texture = NULL; + wlr_buffer_unlock(scene_buffer->buffer); + + if (buffer) { + scene_buffer->buffer = wlr_buffer_lock(buffer); + } else { + scene_buffer->buffer = NULL; + } + + scene_node_update_outputs(&scene_buffer->node); + + if (!damage) { + scene_node_damage_whole(&scene_buffer->node); + } + } + + if (!damage) { return; } - scene_node_damage_whole(&scene_buffer->node); - - wlr_texture_destroy(scene_buffer->texture); - scene_buffer->texture = NULL; - wlr_buffer_unlock(scene_buffer->buffer); - - if (buffer) { - scene_buffer->buffer = wlr_buffer_lock(buffer); - } else { - scene_buffer->buffer = NULL; + int lx, ly; + if (!wlr_scene_node_coords(&scene_buffer->node, &lx, &ly)) { + return; } - scene_node_damage_whole(&scene_buffer->node); + struct wlr_fbox box = scene_buffer->src_box; + if (wlr_fbox_empty(&box)) { + box.x = 0; + box.y = 0; - scene_node_update_outputs(&scene_buffer->node); + if (scene_buffer->transform & WL_OUTPUT_TRANSFORM_90) { + box.width = buffer->height; + box.height = buffer->width; + } else { + box.width = buffer->width; + box.height = buffer->height; + } + } + + double scale_x, scale_y; + if (scene_buffer->dst_width || scene_buffer->dst_height) { + scale_x = scene_buffer->dst_width / box.width; + scale_y = scene_buffer->dst_height / box.height; + } else { + scale_x = buffer->width / box.width; + scale_y = buffer->height / box.height; + } + + pixman_region32_t trans_damage; + pixman_region32_init(&trans_damage); + wlr_region_transform(&trans_damage, damage, + scene_buffer->transform, buffer->width, buffer->height); + pixman_region32_intersect_rect(&trans_damage, &trans_damage, + box.x, box.y, box.width, box.height); + + struct wlr_scene *scene = scene_node_get_root(&scene_buffer->node); + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output, &scene->outputs, link) { + float output_scale = scene_output->output->scale; + pixman_region32_t output_damage; + pixman_region32_init(&output_damage); + wlr_region_scale_xy(&output_damage, &trans_damage, + output_scale * scale_x, output_scale * scale_y); + pixman_region32_translate(&output_damage, + (lx - scene_output->x) * output_scale, (ly - scene_output->y) * output_scale); + wlr_output_damage_add(scene_output->damage, &output_damage); + pixman_region32_fini(&output_damage); + } + + pixman_region32_fini(&trans_damage); +} + +void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, + struct wlr_buffer *buffer) { + wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL); } void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, From 39c059b70ee86be3de84f48bb62965fbf5047cd2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 28 Mar 2022 06:19:45 -0400 Subject: [PATCH 107/298] wlr_scene: Make scene_buffer_from_node public --- include/wlr/types/wlr_scene.h | 2 ++ types/scene/wlr_scene.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 033d4cc64..07cb0a784 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -271,6 +271,8 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent struct wlr_scene_surface *wlr_scene_surface_from_node(struct wlr_scene_node *node); +struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node); + /** * Add a node displaying a solid-colored rectangle to the scene-graph. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 96b70df50..6e940cbc9 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -29,7 +29,7 @@ static struct wlr_scene_rect *scene_rect_from_node( return (struct wlr_scene_rect *)node; } -static struct wlr_scene_buffer *scene_buffer_from_node( +struct wlr_scene_buffer *wlr_scene_buffer_from_node( struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_BUFFER); return (struct wlr_scene_buffer *)node; @@ -106,7 +106,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wl_list_remove(&scene_surface->surface_destroy.link); break; case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); uint64_t active = scene_buffer->active_outputs; if (active) { @@ -260,7 +260,7 @@ static void _scene_node_update_outputs( scene_surface_update_outputs(scene_surface, lx, ly, scene); } else if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = - scene_buffer_from_node(node); + wlr_scene_buffer_from_node(node); scene_buffer_update_outputs(scene_buffer, lx, ly, scene); } @@ -597,7 +597,7 @@ static void scene_node_get_size(struct wlr_scene_node *node, *height = scene_rect->height; break; case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); if (scene_buffer->dst_width > 0 && scene_buffer->dst_height > 0) { *width = scene_buffer->dst_width; *height = scene_buffer->dst_height; @@ -844,7 +844,7 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; break; case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); if (scene_buffer->point_accepts_input) { intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly); @@ -1002,7 +1002,7 @@ static void render_node_iterator(struct wlr_scene_node *node, output->transform_matrix); break; case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); if (!scene_buffer->buffer) { return; } @@ -1143,7 +1143,7 @@ static void scene_node_remove_output(struct wlr_scene_node *node, wlr_surface_send_leave(scene_surface->surface, output->output); } else if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = - scene_buffer_from_node(node); + wlr_scene_buffer_from_node(node); uint64_t mask = 1ull << output->index; if (scene_buffer->active_outputs & mask) { scene_buffer->active_outputs &= ~mask; @@ -1252,7 +1252,7 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { buffer = &scene_surface->surface->buffer->base; break; case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node); + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); if (scene_buffer->buffer == NULL || !wlr_fbox_empty(&scene_buffer->src_box) || scene_buffer->transform != output->transform) { @@ -1284,7 +1284,7 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = - scene_buffer_from_node(node); + wlr_scene_buffer_from_node(node); wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); } @@ -1379,7 +1379,7 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = - scene_buffer_from_node(node); + wlr_scene_buffer_from_node(node); if (scene_buffer->primary_output == scene_output) { wlr_scene_buffer_send_frame_done(scene_buffer, now); From 5f562465717ae4d5afd518cd3adf5c84e83ce2d4 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:01:44 -0400 Subject: [PATCH 108/298] wlr_scene: Pull scene_node_get_root into a private header We will need this for surface emulation on buffers. --- include/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 include/types/wlr_scene.h diff --git a/include/types/wlr_scene.h b/include/types/wlr_scene.h new file mode 100644 index 000000000..64c11bc66 --- /dev/null +++ b/include/types/wlr_scene.h @@ -0,0 +1,8 @@ +#ifndef TYPES_WLR_SCENE_H +#define TYPES_WLR_SCENE_H + +#include + +struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node); + +#endif diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 6e940cbc9..823ddcf08 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -10,6 +10,7 @@ #include #include #include +#include "types/wlr_scene.h" #include "util/signal.h" static struct wlr_scene *scene_root_from_node(struct wlr_scene_node *node) { @@ -35,7 +36,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_from_node( return (struct wlr_scene_buffer *)node; } -static struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { +struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { while (node->parent != NULL) { node = node->parent; } From 20cc1ce0b93c20a0e46f8b7dc6b27b1c0dfd1e42 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 12 Apr 2022 11:47:59 -0400 Subject: [PATCH 109/298] wlr_scene: Change out surface specific iterator functions Instead iterate over wlr_scene_buffer --- include/wlr/types/wlr_scene.h | 24 +++++++++++++--------- types/scene/wlr_scene.c | 38 +++++++++++++++++------------------ 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 07cb0a784..e1818b374 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -28,11 +28,18 @@ struct wlr_output_layout; struct wlr_xdg_surface; struct wlr_layer_surface_v1; +struct wlr_scene_node; struct wlr_scene_buffer; +typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node, + int sx, int sy, void *data); + typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)( struct wlr_scene_buffer *buffer, int sx, int sy); +typedef void (*wlr_scene_buffer_iterator_func_t)( + struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); + enum wlr_scene_node_type { WLR_SCENE_NODE_ROOT, WLR_SCENE_NODE_TREE, @@ -176,9 +183,6 @@ struct wlr_scene_layer_surface_v1 { struct wl_listener layer_surface_unmap; }; -typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node, - int sx, int sy, void *data); - /** * Immediately destroy the scene-graph node. */ @@ -224,12 +228,12 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, */ bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx, int *ly); /** - * Call `iterator` on each surface in the scene-graph, with the surface's + * Call `iterator` on each buffer in the scene-graph, with the buffer's * position in layout coordinates. The function is called from root to leaves * (in rendering order). */ -void wlr_scene_node_for_each_surface(struct wlr_scene_node *node, - wlr_surface_iterator_func_t iterator, void *user_data); +void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, + wlr_scene_buffer_iterator_func_t iterator, void *user_data); /** * Find the topmost node in this scene-graph that contains the point at the * given layout-local coordinates. (For surface nodes, this means accepting @@ -373,12 +377,12 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output); void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, struct timespec *now); /** - * Call `iterator` on each surface in the scene-graph visible on the output, - * with the surface's position in layout coordinates. The function is called + * Call `iterator` on each buffer in the scene-graph visible on the output, + * with the buffer's position in layout coordinates. The function is called * from root to leaves (in rendering order). */ -void wlr_scene_output_for_each_surface(struct wlr_scene_output *scene_output, - wlr_surface_iterator_func_t iterator, void *user_data); +void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, + wlr_scene_buffer_iterator_func_t iterator, void *user_data); /** * Get a scene-graph output from a wlr_output. * diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 823ddcf08..89d48c111 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -785,8 +785,8 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node, return enabled; } -static void scene_node_for_each_surface(struct wlr_scene_node *node, - int lx, int ly, wlr_surface_iterator_func_t user_iterator, +static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, + int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { if (!node->state.enabled) { return; @@ -795,20 +795,20 @@ static void scene_node_for_each_surface(struct wlr_scene_node *node, lx += node->state.x; ly += node->state.y; - if (node->type == WLR_SCENE_NODE_SURFACE) { - struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - user_iterator(scene_surface->surface, lx, ly, user_data); + if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + user_iterator(scene_buffer, lx, ly, user_data); } struct wlr_scene_node *child; wl_list_for_each(child, &node->state.children, state.link) { - scene_node_for_each_surface(child, lx, ly, user_iterator, user_data); + scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data); } } -void wlr_scene_node_for_each_surface(struct wlr_scene_node *node, - wlr_surface_iterator_func_t user_iterator, void *user_data) { - scene_node_for_each_surface(node, 0, 0, user_iterator, user_data); +void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, + wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { + scene_node_for_each_scene_buffer(node, 0, 0, user_iterator, user_data); } struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, @@ -1399,9 +1399,9 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, scene_output, now); } -static void scene_output_for_each_surface(const struct wlr_box *output_box, +static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, struct wlr_scene_node *node, int lx, int ly, - wlr_surface_iterator_func_t user_iterator, void *user_data) { + wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { if (!node->state.enabled) { return; } @@ -1409,30 +1409,30 @@ static void scene_output_for_each_surface(const struct wlr_box *output_box, lx += node->state.x; ly += node->state.y; - if (node->type == WLR_SCENE_NODE_SURFACE) { + if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_box node_box = { .x = lx, .y = ly }; scene_node_get_size(node, &node_box.width, &node_box.height); struct wlr_box intersection; if (wlr_box_intersection(&intersection, output_box, &node_box)) { - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - user_iterator(scene_surface->surface, lx, ly, user_data); + struct wlr_scene_buffer *scene_buffer = + wlr_scene_buffer_from_node(node); + user_iterator(scene_buffer, lx, ly, user_data); } } struct wlr_scene_node *child; wl_list_for_each(child, &node->state.children, state.link) { - scene_output_for_each_surface(output_box, child, lx, ly, + scene_output_for_each_scene_buffer(output_box, child, lx, ly, user_iterator, user_data); } } -void wlr_scene_output_for_each_surface(struct wlr_scene_output *scene_output, - wlr_surface_iterator_func_t iterator, void *user_data) { +void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, + wlr_scene_buffer_iterator_func_t iterator, void *user_data) { struct wlr_box box = { .x = scene_output->x, .y = scene_output->y }; wlr_output_effective_resolution(scene_output->output, &box.width, &box.height); - scene_output_for_each_surface(&box, &scene_output->scene->node, 0, 0, + scene_output_for_each_scene_buffer(&box, &scene_output->scene->node, 0, 0, iterator, user_data); } From f2dbcc33582b734f2fc95dac3b12320a19fa7b6e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 20 Mar 2022 20:56:13 -0400 Subject: [PATCH 110/298] wlr_scene: Make presentation object public --- include/wlr/types/wlr_scene.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index e1818b374..f390c2780 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -76,10 +76,11 @@ struct wlr_scene { struct wl_list outputs; // wlr_scene_output.link - // private state - // May be NULL struct wlr_presentation *presentation; + + // private state + struct wl_listener presentation_destroy; }; From 5f43e1732a5933513790ebe306607a89bc9c0ad9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:25:34 -0400 Subject: [PATCH 111/298] wlr_scene: Introduce addons to scene nodes --- include/wlr/types/wlr_scene.h | 2 ++ types/scene/wlr_scene.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index f390c2780..020881506 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -68,6 +68,8 @@ struct wlr_scene_node { } events; void *data; + + struct wlr_addon_set addons; }; /** The root scene-graph node. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 89d48c111..f4fab207c 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -67,6 +67,8 @@ static void scene_node_init(struct wlr_scene_node *node, if (parent != NULL) { wl_list_insert(parent->state.children.prev, &node->state.link); } + + wlr_addon_set_init(&node->addons); } static void scene_node_damage_whole(struct wlr_scene_node *node); @@ -133,6 +135,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_scene_node_destroy(child); } + wlr_addon_set_finish(&node->addons); scene_node_state_finish(&node->state); free(node); } From dc9bc5683ad3427afddc04afb383dd56723b9016 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 14:26:50 -0400 Subject: [PATCH 112/298] wlr_scene: Refactor wlr_scene_surface to be a helper on top of wlr_scene_buffer --- examples/scene-graph.c | 4 +- include/wlr/types/wlr_scene.h | 26 ++-- tinywl/tinywl.c | 11 +- types/meson.build | 1 + types/scene/subsurface_tree.c | 4 +- types/scene/surface.c | 179 +++++++++++++++++++++++++++ types/scene/wlr_scene.c | 227 +--------------------------------- 7 files changed, 208 insertions(+), 244 deletions(-) create mode 100644 types/scene/surface.c diff --git a/examples/scene-graph.c b/examples/scene-graph.c index f57ef1f2d..98f98cfd4 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -99,7 +99,7 @@ static void surface_handle_commit(struct wl_listener *listener, void *data) { static void surface_handle_destroy(struct wl_listener *listener, void *data) { struct surface *surface = wl_container_of(listener, surface, destroy); - wlr_scene_node_destroy(&surface->scene_surface->node); + wlr_scene_node_destroy(&surface->scene_surface->buffer->node); wlr_scene_node_destroy(&surface->border->node); wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->link); @@ -129,7 +129,7 @@ static void server_handle_new_surface(struct wl_listener *listener, surface->scene_surface = wlr_scene_surface_create(&server->scene->node, wlr_surface); - wlr_scene_node_set_position(&surface->scene_surface->node, + wlr_scene_node_set_position(&surface->scene_surface->buffer->node, pos + border_width, pos + border_width); } diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 020881506..f33025745 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -43,7 +43,6 @@ typedef void (*wlr_scene_buffer_iterator_func_t)( enum wlr_scene_node_type { WLR_SCENE_NODE_ROOT, WLR_SCENE_NODE_TREE, - WLR_SCENE_NODE_SURFACE, WLR_SCENE_NODE_RECT, WLR_SCENE_NODE_BUFFER, }; @@ -93,21 +92,17 @@ struct wlr_scene_tree { /** A scene-graph node displaying a single surface. */ struct wlr_scene_surface { - struct wlr_scene_node node; + struct wlr_scene_buffer *buffer; struct wlr_surface *surface; - /** - * The output that the largest area of this surface is displayed on. - * This may be NULL if the surface is not currently displayed on any - * outputs. This is the output that should be used for frame callbacks, - * presentation feedback, etc. - */ - struct wlr_output *primary_output; - // private state - int prev_width, prev_height; + struct wlr_addon addon; + struct wl_listener output_enter; + struct wl_listener output_leave; + struct wl_listener output_present; + struct wl_listener frame_done; struct wl_listener surface_destroy; struct wl_listener surface_commit; }; @@ -276,10 +271,15 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent); struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, struct wlr_surface *surface); -struct wlr_scene_surface *wlr_scene_surface_from_node(struct wlr_scene_node *node); - struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node); +/** + * If this buffer is backed by a surface, then the wlr_scene_surface is + * returned. If not, NULL will be returned. + */ +struct wlr_scene_surface *wlr_scene_surface_from_buffer( + struct wlr_scene_buffer *scene_buffer); + /** * Add a node displaying a solid-colored rectangle to the scene-graph. */ diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 783cc1828..bf3fb4339 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -341,10 +341,17 @@ static struct tinywl_view *desktop_view_at( * surface in the surface tree of a tinywl_view. */ struct wlr_scene_node *node = wlr_scene_node_at( &server->scene->node, lx, ly, sx, sy); - if (node == NULL || node->type != WLR_SCENE_NODE_SURFACE) { + if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) { return NULL; } - *surface = wlr_scene_surface_from_node(node)->surface; + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_from_buffer(scene_buffer); + if (!scene_surface) { + return NULL; + } + + *surface = scene_surface->surface; /* Find the node corresponding to the tinywl_view at the root of this * surface tree, it is the only one for which we set the data field. */ while (node != NULL && node->data == NULL) { diff --git a/types/meson.build b/types/meson.build index 199815a90..2900561e1 100644 --- a/types/meson.build +++ b/types/meson.build @@ -8,6 +8,7 @@ wlr_files += files( 'output/render.c', 'output/transform.c', 'scene/subsurface_tree.c', + 'scene/surface.c', 'scene/wlr_scene.c', 'scene/output_layout.c', 'scene/xdg_shell.c', diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 8384db8fb..1cb2977c6 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -81,9 +81,9 @@ static void subsurface_tree_reconfigure( } if (prev != NULL) { - wlr_scene_node_place_above(&subsurface_tree->scene_surface->node, prev); + wlr_scene_node_place_above(&subsurface_tree->scene_surface->buffer->node, prev); } - prev = &subsurface_tree->scene_surface->node; + prev = &subsurface_tree->scene_surface->buffer->node; wl_list_for_each(subsurface, &surface->current.subsurfaces_above, current.link) { diff --git a/types/scene/surface.c b/types/scene/surface.c new file mode 100644 index 000000000..e6a8b6b6c --- /dev/null +++ b/types/scene/surface.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include "types/wlr_scene.h" + +static void handle_scene_buffer_output_enter( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, output_enter); + struct wlr_scene_output *output = data; + + wlr_surface_send_enter(surface->surface, output->output); +} + +static void handle_scene_buffer_output_leave( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, output_leave); + struct wlr_scene_output *output = data; + + wlr_surface_send_leave(surface->surface, output->output); +} + +static void handle_scene_buffer_output_present( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, output_present); + struct wlr_scene_output *scene_output = data; + + if (surface->buffer->primary_output == scene_output) { + struct wlr_scene *root = scene_node_get_root(&surface->buffer->node); + struct wlr_presentation *presentation = root->presentation; + + if (presentation) { + wlr_presentation_surface_sampled_on_output( + presentation, surface->surface, scene_output->output); + } + } +} + +static void handle_scene_buffer_frame_done( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, frame_done); + struct timespec *now = data; + + wlr_surface_send_frame_done(surface->surface, now); +} + +static void scene_surface_handle_surface_destroy( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, surface_destroy); + + wlr_scene_node_destroy(&surface->buffer->node); +} + +static void set_buffer_with_surface_state(struct wlr_scene_buffer *scene_buffer, + struct wlr_surface *surface) { + struct wlr_surface_state *state = &surface->current; + + struct wlr_fbox src_box; + wlr_surface_get_buffer_source_box(surface, &src_box); + wlr_scene_buffer_set_source_box(scene_buffer, &src_box); + + wlr_scene_buffer_set_dest_size(scene_buffer, state->width, state->height); + wlr_scene_buffer_set_transform(scene_buffer, state->transform); + + if (surface->buffer) { + wlr_scene_buffer_set_buffer_with_damage(scene_buffer, + &surface->buffer->base, &surface->buffer_damage); + } else { + wlr_scene_buffer_set_buffer(scene_buffer, NULL); + } +} + +static void handle_scene_surface_surface_commit( + struct wl_listener *listener, void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, surface_commit); + struct wlr_scene_buffer *scene_buffer = surface->buffer; + + set_buffer_with_surface_state(scene_buffer, surface->surface); + + // Even if the surface hasn't submitted damage, schedule a new frame if + // the client has requested a wl_surface.frame callback. Check if the node + // is visible. If not, the client will never receive a frame_done event + // anyway so it doesn't make sense to schedule here. + int lx, ly; + bool enabled = wlr_scene_node_coords(&scene_buffer->node, &lx, &ly); + + if (!wl_list_empty(&surface->surface->current.frame_callback_list) && + surface->buffer->primary_output != NULL && enabled) { + wlr_output_schedule_frame(surface->buffer->primary_output->output); + } +} + +static bool scene_buffer_point_accepts_input(struct wlr_scene_buffer *scene_buffer, + int sx, int sy) { + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_from_buffer(scene_buffer); + + return wlr_surface_point_accepts_input(scene_surface->surface, sx, sy); +} + +static void surface_addon_destroy(struct wlr_addon *addon) { + struct wlr_scene_surface *surface = wl_container_of(addon, surface, addon); + + wlr_addon_finish(&surface->addon); + + wl_list_remove(&surface->output_enter.link); + wl_list_remove(&surface->output_leave.link); + wl_list_remove(&surface->output_present.link); + wl_list_remove(&surface->frame_done.link); + wl_list_remove(&surface->surface_destroy.link); + wl_list_remove(&surface->surface_commit.link); + + free(surface); +} + +static const struct wlr_addon_interface surface_addon_impl = { + .name = "wlr_scene_surface", + .destroy = surface_addon_destroy, +}; + +struct wlr_scene_surface *wlr_scene_surface_from_buffer( + struct wlr_scene_buffer *scene_buffer) { + struct wlr_addon *addon = wlr_addon_find(&scene_buffer->node.addons, + scene_buffer, &surface_addon_impl); + if (!addon) { + return NULL; + } + + struct wlr_scene_surface *surface = wl_container_of(addon, surface, addon); + return surface; +} + +struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, + struct wlr_surface *wlr_surface) { + struct wlr_scene_surface *surface = calloc(1, sizeof(*surface)); + if (surface == NULL) { + return NULL; + } + + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(parent, NULL); + if (!scene_buffer) { + free(surface); + return NULL; + } + + surface->buffer = scene_buffer; + surface->surface = wlr_surface; + scene_buffer->point_accepts_input = scene_buffer_point_accepts_input; + + surface->output_enter.notify = handle_scene_buffer_output_enter; + wl_signal_add(&scene_buffer->events.output_enter, &surface->output_enter); + + surface->output_leave.notify = handle_scene_buffer_output_leave; + wl_signal_add(&scene_buffer->events.output_leave, &surface->output_leave); + + surface->output_present.notify = handle_scene_buffer_output_present; + wl_signal_add(&scene_buffer->events.output_present, &surface->output_present); + + surface->frame_done.notify = handle_scene_buffer_frame_done; + wl_signal_add(&scene_buffer->events.frame_done, &surface->frame_done); + + surface->surface_destroy.notify = scene_surface_handle_surface_destroy; + wl_signal_add(&wlr_surface->events.destroy, &surface->surface_destroy); + + surface->surface_commit.notify = handle_scene_surface_surface_commit; + wl_signal_add(&wlr_surface->events.commit, &surface->surface_commit); + + wlr_addon_init(&surface->addon, &scene_buffer->node.addons, + scene_buffer, &surface_addon_impl); + + set_buffer_with_surface_state(scene_buffer, wlr_surface); + + return surface; +} diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index f4fab207c..2435edefe 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -18,12 +18,6 @@ static struct wlr_scene *scene_root_from_node(struct wlr_scene_node *node) { return (struct wlr_scene *)node; } -struct wlr_scene_surface *wlr_scene_surface_from_node( - struct wlr_scene_node *node) { - assert(node->type == WLR_SCENE_NODE_SURFACE); - return (struct wlr_scene_surface *)node; -} - static struct wlr_scene_rect *scene_rect_from_node( struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_RECT); @@ -96,18 +90,6 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wl_list_remove(&scene->presentation_destroy.link); break; - case WLR_SCENE_NODE_SURFACE:; - struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - - wl_list_for_each(scene_output, &scene->outputs, link) { - // This is a noop if wlr_surface_send_enter() wasn't previously called for - // the given output. - wlr_surface_send_leave(scene_surface->surface, scene_output->output); - } - - wl_list_remove(&scene_surface->surface_commit.link); - wl_list_remove(&scene_surface->surface_destroy.link); - break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); @@ -161,58 +143,8 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent) { return tree; } -static void scene_surface_handle_surface_destroy(struct wl_listener *listener, - void *data) { - struct wlr_scene_surface *scene_surface = - wl_container_of(listener, scene_surface, surface_destroy); - wlr_scene_node_destroy(&scene_surface->node); -} - static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); -// This function must be called whenever the coordinates/dimensions of a scene -// surface or scene output change. It is not necessary to call when a scene -// surface's node is enabled/disabled or obscured by other nodes. To quote the -// protocol: "The surface might be hidden even if no leave event has been sent." -static void scene_surface_update_outputs( - struct wlr_scene_surface *scene_surface, - int lx, int ly, struct wlr_scene *scene) { - struct wlr_box surface_box = { - .x = lx, - .y = ly, - .width = scene_surface->surface->current.width, - .height = scene_surface->surface->current.height, - }; - - int largest_overlap = 0; - scene_surface->primary_output = NULL; - - struct wlr_scene_output *scene_output; - wl_list_for_each(scene_output, &scene->outputs, link) { - struct wlr_box output_box = { - .x = scene_output->x, - .y = scene_output->y, - }; - wlr_output_effective_resolution(scene_output->output, - &output_box.width, &output_box.height); - - struct wlr_box intersection; - if (wlr_box_intersection(&intersection, &surface_box, &output_box)) { - int overlap = intersection.width * intersection.height; - if (overlap > largest_overlap) { - largest_overlap = overlap; - scene_surface->primary_output = scene_output->output; - } - - // These enter/leave functions are a noop if the event has already been - // sent for the given output. - wlr_surface_send_enter(scene_surface->surface, scene_output->output); - } else { - wlr_surface_send_leave(scene_surface->surface, scene_output->output); - } - } -} - // This function must be called whenever the coordinates/dimensions of a scene // buffer or scene output change. It is not necessary to call when a scene // buffer's node is enabled/disabled or obscured by other nodes. @@ -258,11 +190,7 @@ static void scene_buffer_update_outputs( static void _scene_node_update_outputs( struct wlr_scene_node *node, int lx, int ly, struct wlr_scene *scene) { - if (node->type == WLR_SCENE_NODE_SURFACE) { - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - scene_surface_update_outputs(scene_surface, lx, ly, scene); - } else if (node->type == WLR_SCENE_NODE_BUFFER) { + if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); scene_buffer_update_outputs(scene_buffer, lx, ly, scene); @@ -282,86 +210,6 @@ static void scene_node_update_outputs(struct wlr_scene_node *node) { _scene_node_update_outputs(node, lx, ly, scene); } -static void scene_surface_handle_surface_commit(struct wl_listener *listener, - void *data) { - struct wlr_scene_surface *scene_surface = - wl_container_of(listener, scene_surface, surface_commit); - struct wlr_surface *surface = scene_surface->surface; - - struct wlr_scene *scene = scene_node_get_root(&scene_surface->node); - - int lx, ly; - bool enabled = wlr_scene_node_coords(&scene_surface->node, &lx, &ly); - - if (surface->current.width != scene_surface->prev_width || - surface->current.height != scene_surface->prev_height) { - scene_surface_update_outputs(scene_surface, lx, ly, scene); - scene_surface->prev_width = surface->current.width; - scene_surface->prev_height = surface->current.height; - } - - if (!enabled) { - return; - } - - // Even if the surface hasn't submitted damage, schedule a new frame if - // the client has requested a wl_surface.frame callback. - if (!wl_list_empty(&surface->current.frame_callback_list) && - scene_surface->primary_output != NULL) { - wlr_output_schedule_frame(scene_surface->primary_output); - } - - if (!pixman_region32_not_empty(&surface->buffer_damage)) { - return; - } - - struct wlr_scene_output *scene_output; - wl_list_for_each(scene_output, &scene->outputs, link) { - struct wlr_output *output = scene_output->output; - - pixman_region32_t damage; - pixman_region32_init(&damage); - wlr_surface_get_effective_damage(surface, &damage); - - pixman_region32_translate(&damage, - lx - scene_output->x, ly - scene_output->y); - - wlr_region_scale(&damage, &damage, output->scale); - if (ceil(output->scale) > surface->current.scale) { - // When scaling up a surface it'll become blurry, so we need to - // expand the damage region. - wlr_region_expand(&damage, &damage, - ceil(output->scale) - surface->current.scale); - } - wlr_output_damage_add(scene_output->damage, &damage); - pixman_region32_fini(&damage); - } -} - -struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, - struct wlr_surface *surface) { - struct wlr_scene_surface *scene_surface = - calloc(1, sizeof(struct wlr_scene_surface)); - if (scene_surface == NULL) { - return NULL; - } - scene_node_init(&scene_surface->node, WLR_SCENE_NODE_SURFACE, parent); - - scene_surface->surface = surface; - - scene_surface->surface_destroy.notify = scene_surface_handle_surface_destroy; - wl_signal_add(&surface->events.destroy, &scene_surface->surface_destroy); - - scene_surface->surface_commit.notify = scene_surface_handle_surface_commit; - wl_signal_add(&surface->events.commit, &scene_surface->surface_commit); - - scene_node_damage_whole(&scene_surface->node); - - scene_node_update_outputs(&scene_surface->node); - - return scene_surface; -} - struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, int width, int height, const float color[static 4]) { struct wlr_scene_rect *scene_rect = @@ -589,12 +437,6 @@ static void scene_node_get_size(struct wlr_scene_node *node, case WLR_SCENE_NODE_ROOT: case WLR_SCENE_NODE_TREE: return; - case WLR_SCENE_NODE_SURFACE:; - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - *width = scene_surface->surface->current.width; - *height = scene_surface->surface->current.height; - break; case WLR_SCENE_NODE_RECT:; struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); *width = scene_rect->width; @@ -838,10 +680,6 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, case WLR_SCENE_NODE_ROOT: case WLR_SCENE_NODE_TREE: break; - case WLR_SCENE_NODE_SURFACE:; - struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - intersects = wlr_surface_point_accepts_input(scene_surface->surface, lx, ly); - break; case WLR_SCENE_NODE_RECT:; int width, height; scene_node_get_size(node, &width, &height); @@ -948,9 +786,6 @@ static void render_texture(struct wlr_output *output, struct render_data { struct wlr_scene_output *scene_output; pixman_region32_t *damage; - - // May be NULL - struct wlr_presentation *presentation; }; static void render_node_iterator(struct wlr_scene_node *node, @@ -975,30 +810,6 @@ static void render_node_iterator(struct wlr_scene_node *node, case WLR_SCENE_NODE_TREE: /* Root or tree node has nothing to render itself */ break; - case WLR_SCENE_NODE_SURFACE:; - struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - struct wlr_surface *surface = scene_surface->surface; - - texture = wlr_surface_get_texture(surface); - if (texture == NULL) { - return; - } - - transform = wlr_output_transform_invert(surface->current.transform); - wlr_matrix_project_box(matrix, &dst_box, transform, 0.0, - output->transform_matrix); - - struct wlr_fbox src_box = {0}; - wlr_surface_get_buffer_source_box(surface, &src_box); - - render_texture(output, output_damage, texture, - &src_box, &dst_box, matrix); - - if (data->presentation != NULL && scene_surface->primary_output == output) { - wlr_presentation_surface_sampled_on_output(data->presentation, - surface, output); - } - break; case WLR_SCENE_NODE_RECT:; struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); @@ -1141,11 +952,7 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, static void scene_node_remove_output(struct wlr_scene_node *node, struct wlr_scene_output *output) { - if (node->type == WLR_SCENE_NODE_SURFACE) { - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - wlr_surface_send_leave(scene_surface->surface, output->output); - } else if (node->type == WLR_SCENE_NODE_BUFFER) { + if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); uint64_t mask = 1ull << output->index; @@ -1246,15 +1053,6 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { struct wlr_scene_node *node = check_scanout_data.node; struct wlr_buffer *buffer; switch (node->type) { - case WLR_SCENE_NODE_SURFACE:; - struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node); - if (scene_surface->surface->buffer == NULL || - scene_surface->surface->current.viewport.has_src || - scene_surface->surface->current.transform != output->transform) { - return false; - } - buffer = &scene_surface->surface->buffer->base; - break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); if (scene_buffer->buffer == NULL || @@ -1274,18 +1072,6 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { return false; } - struct wlr_presentation *presentation = scene_output->scene->presentation; - if (presentation != NULL && node->type == WLR_SCENE_NODE_SURFACE) { - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - // Since outputs may overlap, we still need to check this even though - // we know that the surface size matches the size of this output. - if (scene_surface->primary_output == output) { - wlr_presentation_surface_sampled_on_output(presentation, - scene_surface->surface, output); - } - } - if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); @@ -1340,7 +1126,6 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct render_data data = { .scene_output = scene_output, .damage = &damage, - .presentation = scene_output->scene->presentation, }; scene_node_for_each_node(&scene_output->scene->node, -scene_output->x, -scene_output->y, @@ -1373,14 +1158,6 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, return; } - if (node->type == WLR_SCENE_NODE_SURFACE) { - struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_node(node); - if (scene_surface->primary_output == scene_output->output) { - wlr_surface_send_frame_done(scene_surface->surface, now); - } - } - if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); From 17b2b06633729f1826715c1d0b84614aa3cedb3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Mon, 28 Feb 2022 13:49:32 +0100 Subject: [PATCH 113/298] seat: Allow to cancel touches After cancelation we destroy the touch points associated with this surface as the Wayland spec says: No further events are sent to the clients from that particular gesture. Touch cancellation applies to all touch points currently active on this client's surface. The client is responsible for finalizing the touch points, future touch points on this surface may re-use the touch point ID. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2999 --- include/wlr/types/wlr_seat.h | 21 ++++++++++++++++-- types/seat/wlr_seat_touch.c | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index ebbcfd479..1946873ae 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -119,9 +119,11 @@ struct wlr_touch_grab_interface { void (*enter)(struct wlr_seat_touch_grab *grab, uint32_t time_msec, struct wlr_touch_point *point); void (*frame)(struct wlr_seat_touch_grab *grab); - // XXX this will conflict with the actual touch cancel which is different so - // we need to rename this + // Cancel grab void (*cancel)(struct wlr_seat_touch_grab *grab); + // Send wl_touch::cancel + void (*wl_cancel)(struct wlr_seat_touch_grab *grab, + struct wlr_surface *surface); }; /** @@ -613,6 +615,14 @@ void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time_msec, void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time_msec, int32_t touch_id, double sx, double sy); +/** + * Notify the seat that this is a global gesture and the client should cancel + * processing it. The event will go to the client for the surface given. + * This function does not respect touch grabs: you probably want + * `wlr_seat_touch_notify_cancel()` instead. + */ +void wlr_seat_touch_send_cancel(struct wlr_seat *seat, struct wlr_surface *surface); + void wlr_seat_touch_send_frame(struct wlr_seat *seat); /** @@ -639,6 +649,13 @@ void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time_msec, void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time_msec, int32_t touch_id, double sx, double sy); +/** + * Notify the seat that this is a global gesture and the client should + * cancel processing it. Defers to any grab of the touch device. + */ +void wlr_seat_touch_notify_cancel(struct wlr_seat *seat, + struct wlr_surface *surface); + void wlr_seat_touch_notify_frame(struct wlr_seat *seat); /** diff --git a/types/seat/wlr_seat_touch.c b/types/seat/wlr_seat_touch.c index 65a8c7c06..abc17ae2c 100644 --- a/types/seat/wlr_seat_touch.c +++ b/types/seat/wlr_seat_touch.c @@ -41,6 +41,11 @@ static void default_touch_cancel(struct wlr_seat_touch_grab *grab) { // cannot be cancelled } +static void default_touch_wl_cancel(struct wlr_seat_touch_grab *grab, + struct wlr_surface *surface) { + wlr_seat_touch_send_cancel(grab->seat, surface); +} + const struct wlr_touch_grab_interface default_touch_grab_impl = { .down = default_touch_down, .up = default_touch_up, @@ -48,6 +53,7 @@ const struct wlr_touch_grab_interface default_touch_grab_impl = { .enter = default_touch_enter, .frame = default_touch_frame, .cancel = default_touch_cancel, + .wl_cancel = default_touch_wl_cancel, }; @@ -238,6 +244,26 @@ void wlr_seat_touch_notify_frame(struct wlr_seat *seat) { } } +void wlr_seat_touch_notify_cancel(struct wlr_seat *seat, + struct wlr_surface *surface) { + struct wlr_seat_touch_grab *grab = seat->touch_state.grab; + if (grab->interface->wl_cancel) { + grab->interface->wl_cancel(grab, surface); + } + + struct wl_client *client = wl_resource_get_client(surface->resource); + struct wlr_seat_client *seat_client = wlr_seat_client_for_wl_client(seat, client); + if (seat_client == NULL) { + return; + } + struct wlr_touch_point *point, *tmp; + wl_list_for_each_safe(point, tmp, &seat->touch_state.touch_points, link) { + if (point->client == seat_client) { + touch_point_destroy(point); + } + } +} + static void handle_point_focus_destroy(struct wl_listener *listener, void *data) { struct wlr_touch_point *point = @@ -376,6 +402,22 @@ void wlr_seat_touch_send_frame(struct wlr_seat *seat) { } } +void wlr_seat_touch_send_cancel(struct wlr_seat *seat, struct wlr_surface *surface) { + struct wl_client *client = wl_resource_get_client(surface->resource); + struct wlr_seat_client *seat_client = wlr_seat_client_for_wl_client(seat, client); + if (seat_client == NULL) { + return; + } + + struct wl_resource *resource; + wl_resource_for_each(resource, &seat_client->touches) { + if (seat_client_from_touch_resource(resource) == NULL) { + continue; + } + wl_touch_send_cancel(resource); + } +} + int wlr_seat_touch_num_points(struct wlr_seat *seat) { return wl_list_length(&seat->touch_state.touch_points); } From 02e648c1b2be5aee77893b38bd4fc9923c359fe8 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 18 May 2022 14:43:48 +0000 Subject: [PATCH 114/298] xwayland: Add support for -force-xrandr-emulation --- include/wlr/xwayland.h | 1 + include/xwayland/meson.build | 4 ++++ xwayland/server.c | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 165ea944d..f1c76f69c 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -24,6 +24,7 @@ struct wlr_xwayland_server_options { bool lazy; bool enable_wm; bool no_touch_pointer_emulation; + bool force_xrandr_emulation; int terminate_delay; // in seconds, 0 to terminate immediately }; diff --git a/include/xwayland/meson.build b/include/xwayland/meson.build index adec52fcd..b621bd89f 100644 --- a/include/xwayland/meson.build +++ b/include/xwayland/meson.build @@ -1,5 +1,6 @@ have_listenfd = false have_no_touch_pointer_emulation = false +have_force_xrandr_emulation = false have_terminate_delay = false if xwayland.found() xwayland_path = xwayland.get_variable('xwayland') @@ -7,6 +8,8 @@ if xwayland.found() default_value: 'false') == 'true' have_no_touch_pointer_emulation = xwayland.get_variable( 'have_no_touch_pointer_emulation', default_value: 'false') == 'true' + have_force_xrandr_emulation = xwayland.get_variable( + 'have_force_xrandr_emulation', default_value: 'false') == 'true' have_terminate_delay = xwayland.get_variable(pkgconfig: 'have_terminate_delay') == 'true' else xwayland_path = xwayland_prog.full_path() @@ -16,6 +19,7 @@ xwayland_config_data = configuration_data() xwayland_config_data.set_quoted('XWAYLAND_PATH', xwayland_path) xwayland_config_data.set10('HAVE_XWAYLAND_LISTENFD', have_listenfd) xwayland_config_data.set10('HAVE_XWAYLAND_NO_TOUCH_POINTER_EMULATION', have_no_touch_pointer_emulation) +xwayland_config_data.set10('HAVE_XWAYLAND_FORCE_XRANDR_EMULATION', have_force_xrandr_emulation) xwayland_config_data.set10('HAVE_XWAYLAND_TERMINATE_DELAY', have_terminate_delay) configure_file( output: 'config.h', diff --git a/xwayland/server.c b/xwayland/server.c index 8502fcec5..0086ad65e 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -90,6 +90,14 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server, server->options.no_touch_pointer_emulation = false; #endif +#if HAVE_XWAYLAND_FORCE_XRANDR_EMULATION + if (server->options.force_xrandr_emulation) { + argv[i++] = "-force-xrandr-emulation"; + } +#else + server->options.force_xrandr_emulation = false; +#endif + argv[i++] = NULL; assert(i < sizeof(argv) / sizeof(argv[0])); From ee122c9c2a6c6d0e9286ee434375245f4ed5d04c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 22 May 2022 10:36:25 +0300 Subject: [PATCH 115/298] scene/output: check for NULL in destructor --- types/scene/wlr_scene.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 2435edefe..303325fdf 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -969,6 +969,10 @@ static void scene_node_remove_output(struct wlr_scene_node *node, } void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { + if (scene_output == NULL) { + return; + } + scene_node_remove_output(&scene_output->scene->node, scene_output); wlr_addon_finish(&scene_output->addon); From 9cae8745138e5136abd43713f9edc4806a46ef4f Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Fri, 3 Dec 2021 21:40:32 -0500 Subject: [PATCH 116/298] screencopy-v1: Fix frame stride for formats with bpp != 32 --- types/wlr_screencopy_v1.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index e2c020db5..c656a916b 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -542,6 +542,12 @@ static void capture_output(struct wl_client *wl_client, "Failed to capture output: no read format supported by renderer"); goto error; } + const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(drm_format); + if (!info) { + wlr_log(WLR_ERROR, + "Failed to capture output: no pixel format info matching read format"); + goto error; + } frame->format = convert_drm_format_to_wl_shm(drm_format); if (output->allocator && @@ -569,7 +575,7 @@ static void capture_output(struct wl_client *wl_client, } frame->box = buffer_box; - frame->stride = 4 * buffer_box.width; // TODO: depends on read format + frame->stride = (info->bpp / 8) * buffer_box.width; zwlr_screencopy_frame_v1_send_buffer(frame->resource, frame->format, buffer_box.width, buffer_box.height, frame->stride); From cde3700386cc967a9c0805a07310b35e56974440 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 23 May 2022 09:44:39 +0200 Subject: [PATCH 117/298] xwayland: use dict to collect supported features --- include/xwayland/meson.build | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/include/xwayland/meson.build b/include/xwayland/meson.build index b621bd89f..fcc5bd3af 100644 --- a/include/xwayland/meson.build +++ b/include/xwayland/meson.build @@ -1,26 +1,29 @@ -have_listenfd = false -have_no_touch_pointer_emulation = false -have_force_xrandr_emulation = false -have_terminate_delay = false +xwayland_feature_names = [ + 'listenfd', + 'no_touch_pointer_emulation', + 'force_xrandr_emulation', + 'terminate_delay', +] + +xwayland_features = {} if xwayland.found() xwayland_path = xwayland.get_variable('xwayland') - have_listenfd = xwayland.get_variable('have_listenfd', - default_value: 'false') == 'true' - have_no_touch_pointer_emulation = xwayland.get_variable( - 'have_no_touch_pointer_emulation', default_value: 'false') == 'true' - have_force_xrandr_emulation = xwayland.get_variable( - 'have_force_xrandr_emulation', default_value: 'false') == 'true' - have_terminate_delay = xwayland.get_variable(pkgconfig: 'have_terminate_delay') == 'true' + foreach name : xwayland_feature_names + have = xwayland.get_variable('have_' + name, default_value: 'false') == 'true' + xwayland_features += { name: have } + endforeach else xwayland_path = xwayland_prog.full_path() + foreach name : xwayland_feature_names + xwayland_features += { name: false } + endforeach endif xwayland_config_data = configuration_data() xwayland_config_data.set_quoted('XWAYLAND_PATH', xwayland_path) -xwayland_config_data.set10('HAVE_XWAYLAND_LISTENFD', have_listenfd) -xwayland_config_data.set10('HAVE_XWAYLAND_NO_TOUCH_POINTER_EMULATION', have_no_touch_pointer_emulation) -xwayland_config_data.set10('HAVE_XWAYLAND_FORCE_XRANDR_EMULATION', have_force_xrandr_emulation) -xwayland_config_data.set10('HAVE_XWAYLAND_TERMINATE_DELAY', have_terminate_delay) +foreach name, have : xwayland_features + xwayland_config_data.set10('HAVE_XWAYLAND_' + name.to_upper(), have) +endforeach configure_file( output: 'config.h', configuration: xwayland_config_data, From 4ac19e9f9cf38bc146ba42cc7ce89b29e748b30f Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 16 May 2022 20:35:31 +0300 Subject: [PATCH 118/298] util/addon: avoid calling finish() twice No functional change. --- include/wlr/util/addon.h | 5 +++-- util/addon.c | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/wlr/util/addon.h b/include/wlr/util/addon.h index 382252ae2..c64200cf9 100644 --- a/include/wlr/util/addon.h +++ b/include/wlr/util/addon.h @@ -20,6 +20,7 @@ struct wlr_addon; struct wlr_addon_interface { const char *name; + // Has to call wlr_addon_finish() void (*destroy)(struct wlr_addon *addon); }; @@ -34,10 +35,10 @@ void wlr_addon_set_init(struct wlr_addon_set *set); void wlr_addon_set_finish(struct wlr_addon_set *set); void wlr_addon_init(struct wlr_addon *addon, struct wlr_addon_set *set, - const void *owner, const struct wlr_addon_interface *impl); + const void *owner, const struct wlr_addon_interface *impl); void wlr_addon_finish(struct wlr_addon *addon); struct wlr_addon *wlr_addon_find(struct wlr_addon_set *set, const void *owner, - const struct wlr_addon_interface *impl); + const struct wlr_addon_interface *impl); #endif diff --git a/util/addon.c b/util/addon.c index c9b373a76..10aed744a 100644 --- a/util/addon.c +++ b/util/addon.c @@ -12,7 +12,6 @@ void wlr_addon_set_init(struct wlr_addon_set *set) { void wlr_addon_set_finish(struct wlr_addon_set *set) { struct wlr_addon *addon, *tmp; wl_list_for_each_safe(addon, tmp, &set->addons, link) { - wlr_addon_finish(addon); addon->impl->destroy(addon); } } @@ -34,7 +33,6 @@ void wlr_addon_init(struct wlr_addon *addon, struct wlr_addon_set *set, void wlr_addon_finish(struct wlr_addon *addon) { wl_list_remove(&addon->link); - wl_list_init(&addon->link); } struct wlr_addon *wlr_addon_find(struct wlr_addon_set *set, const void *owner, From 17f5414b1ab198481f82d23e6903b48768785117 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 20 May 2022 18:28:08 -0400 Subject: [PATCH 119/298] wlr_scene: Parse out WLR_SCENE_DEBUG_DAMAGE --- docs/env_vars.md | 6 ++++++ include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/docs/env_vars.md b/docs/env_vars.md index 609ca97bd..22626c6b0 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -45,6 +45,12 @@ wlroots reads these environment variables * *WLR_RENDERER_ALLOW_SOFTWARE*: allows the gles2 renderer to use software rendering +## scenes + +* *WLR_SCENE_DEBUG_DAMAGE*: specifies debug options for screen damage related +tasks for compositors that use scenes. (available options: NONE, RERENDER, +HIGHLIGHT) + # Generic * *DISPLAY*: if set probe X11 backend in `wlr_backend_autocreate` diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index f33025745..2625dd80a 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -71,6 +71,12 @@ struct wlr_scene_node { struct wlr_addon_set addons; }; +enum wlr_scene_debug_damage_option { + WLR_SCENE_DEBUG_DAMAGE_NONE, + WLR_SCENE_DEBUG_DAMAGE_RERENDER, + WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT +}; + /** The root scene-graph node. */ struct wlr_scene { struct wlr_scene_node node; @@ -83,6 +89,8 @@ struct wlr_scene { // private state struct wl_listener presentation_destroy; + + enum wlr_scene_debug_damage_option debug_damage_option; }; /** A sub-tree in the scene-graph. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 303325fdf..4241a57cf 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -130,6 +130,23 @@ struct wlr_scene *wlr_scene_create(void) { scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); + + char *debug_damage = getenv("WLR_SCENE_DEBUG_DAMAGE"); + if (debug_damage) { + wlr_log(WLR_INFO, "Loading WLR_SCENE_DEBUG_DAMAGE option: %s", debug_damage); + } + + if (!debug_damage || strcmp(debug_damage, "none") == 0) { + scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_NONE; + } else if (strcmp(debug_damage, "rerender") == 0) { + scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_RERENDER; + } else if (strcmp(debug_damage, "highlight") == 0) { + scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT; + } else { + wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DEBUG_DAMAGE option: %s", debug_damage); + scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_NONE; + } + return scene; } From b6fc882782ef17fac09c773adcc5cee9127cba72 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 20 May 2022 18:31:41 -0400 Subject: [PATCH 120/298] wlr_scene: Hook up RERENDER logic --- types/scene/wlr_scene.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 4241a57cf..6f0591bce 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1104,6 +1104,8 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct wlr_output *output = scene_output->output; + enum wlr_scene_debug_damage_option debug_damage = + scene_output->scene->debug_damage_option; struct wlr_renderer *renderer = output->renderer; assert(renderer != NULL); @@ -1120,6 +1122,10 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { return true; } + if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_RERENDER) { + wlr_output_damage_add_whole(scene_output->damage); + } + bool needs_frame; pixman_region32_t damage; pixman_region32_init(&damage); From 41124592dd55b11e39a18b0aa843511e3e4597bb Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 23 May 2022 15:58:49 -0400 Subject: [PATCH 121/298] wlr_scene: Hook up HIGHLIGHT logic This will display red translucent rectangles on the screen regions that have been damaged. These rectangles will fade out over the span of 250 msecs. If the area is damaged again while the region is fading out, the timer is reset. Let's also disable direct scan out when this option is enabled, or else we won't be able to render the highlight damage regions. --- include/wlr/types/wlr_scene.h | 1 + types/scene/wlr_scene.c | 102 +++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 2625dd80a..0802014ed 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -91,6 +91,7 @@ struct wlr_scene { struct wl_listener presentation_destroy; enum wlr_scene_debug_damage_option debug_damage_option; + struct wl_list damage_highlight_regions; }; /** A sub-tree in the scene-graph. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 6f0591bce..676fe1270 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1,3 +1,4 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -12,6 +13,9 @@ #include #include "types/wlr_scene.h" #include "util/signal.h" +#include "util/time.h" + +#define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 static struct wlr_scene *scene_root_from_node(struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_ROOT); @@ -67,6 +71,18 @@ static void scene_node_init(struct wlr_scene_node *node, static void scene_node_damage_whole(struct wlr_scene_node *node); +struct highlight_region { + pixman_region32_t region; + struct timespec when; + struct wl_list link; +}; + +static void highlight_region_destroy(struct highlight_region *damage) { + wl_list_remove(&damage->link); + pixman_region32_fini(&damage->region); + free(damage); +} + void wlr_scene_node_destroy(struct wlr_scene_node *node) { if (node == NULL) { return; @@ -88,6 +104,11 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_scene_output_destroy(scene_output); } + struct highlight_region *damage, *tmp_damage; + wl_list_for_each_safe(damage, tmp_damage, &scene->damage_highlight_regions, link) { + highlight_region_destroy(damage); + } + wl_list_remove(&scene->presentation_destroy.link); break; case WLR_SCENE_NODE_BUFFER:; @@ -130,6 +151,7 @@ struct wlr_scene *wlr_scene_create(void) { scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); + wl_list_init(&scene->damage_highlight_regions); char *debug_damage = getenv("WLR_SCENE_DEBUG_DAMAGE"); if (debug_damage) { @@ -1056,6 +1078,13 @@ static void check_scanout_iterator(struct wlr_scene_node *node, } static bool scene_output_scanout(struct wlr_scene_output *scene_output) { + if (scene_output->scene->debug_damage_option == + WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { + // We don't want to enter direct scan out if we have highlight regions + // enabled. Otherwise, we won't be able to render the damage regions. + return false; + } + struct wlr_output *output = scene_output->output; struct wlr_box viewport_box = { .x = scene_output->x, .y = scene_output->y }; @@ -1126,6 +1155,45 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_output_damage_add_whole(scene_output->damage); } + struct timespec now; + if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { + struct wl_list *regions = &scene_output->scene->damage_highlight_regions; + clock_gettime(CLOCK_MONOTONIC, &now); + + // add the current frame's damage if there is damage + if (pixman_region32_not_empty(&scene_output->damage->current)) { + struct highlight_region *current_damage = + calloc(1, sizeof(*current_damage)); + if (current_damage) { + pixman_region32_init(¤t_damage->region); + pixman_region32_copy(¤t_damage->region, + &scene_output->damage->current); + memcpy(¤t_damage->when, &now, sizeof(now)); + wl_list_insert(regions, ¤t_damage->link); + } + } + + pixman_region32_t acc_damage; + pixman_region32_init(&acc_damage); + struct highlight_region *damage, *tmp_damage; + wl_list_for_each_safe(damage, tmp_damage, regions, link) { + // remove overlaping damage regions + pixman_region32_subtract(&damage->region, &damage->region, &acc_damage); + pixman_region32_union(&acc_damage, &acc_damage, &damage->region); + + // if this damage is too old or has nothing in it, get rid of it + struct timespec time_diff; + timespec_sub(&time_diff, &now, &damage->when); + if (timespec_to_msec(&time_diff) >= HIGHLIGHT_DAMAGE_FADEOUT_TIME || + !pixman_region32_not_empty(&damage->region)) { + highlight_region_destroy(damage); + } + } + + wlr_output_damage_add(scene_output->damage, &acc_damage); + pixman_region32_fini(&acc_damage); + } + bool needs_frame; pixman_region32_t damage; pixman_region32_init(&damage); @@ -1158,6 +1226,31 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { -scene_output->x, -scene_output->y, render_node_iterator, &data); wlr_renderer_scissor(renderer, NULL); + + if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { + struct highlight_region *damage; + wl_list_for_each(damage, &scene_output->scene->damage_highlight_regions, link) { + struct timespec time_diff; + timespec_sub(&time_diff, &now, &damage->when); + int64_t time_diff_ms = timespec_to_msec(&time_diff); + float alpha = 1.0 - (double)time_diff_ms / HIGHLIGHT_DAMAGE_FADEOUT_TIME; + + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(&damage->region, &nrects); + for (int i = 0; i < nrects; ++i) { + struct wlr_box box = { + .x = rects[i].x1, + .y = rects[i].y1, + .width = rects[i].x2 - rects[i].x1, + .height = rects[i].y2 - rects[i].y1, + }; + + float color[4] = { alpha * .5, 0.0, 0.0, alpha * .5 }; + wlr_render_rect(renderer, &box, color, output->transform_matrix); + } + } + } + wlr_output_render_software_cursors(output, &damage); wlr_renderer_end(renderer); @@ -1176,7 +1269,14 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_output_set_damage(output, &frame_damage); pixman_region32_fini(&frame_damage); - return wlr_output_commit(output); + bool success = wlr_output_commit(output); + + if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT && + !wl_list_empty(&scene_output->scene->damage_highlight_regions)) { + wlr_output_schedule_frame(scene_output->output); + } + + return success; } static void scene_node_send_frame_done(struct wlr_scene_node *node, From 078d8dd472259f341f5efc7ac8f38347b3732cc0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 12:13:54 +0200 Subject: [PATCH 122/298] build: bump version to 0.16.0-dev Same as [1]. [1]: https://github.com/swaywm/sway/pull/6730 --- include/wlr/meson.build | 3 ++- meson.build | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/wlr/meson.build b/include/wlr/meson.build index ae9c17a3e..f7ca413de 100644 --- a/include/wlr/meson.build +++ b/include/wlr/meson.build @@ -1,4 +1,5 @@ -version_array = meson.project_version().split('.') +version_base = meson.project_version().split('-')[0] +version_array = version_base.split('.') version_data = configuration_data() version_data.set_quoted('WLR_VERSION_STR', meson.project_version()) version_data.set('WLR_VERSION_MAJOR', version_array[0]) diff --git a/meson.build b/meson.build index 2350f7da7..5d45073de 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'wlroots', 'c', - version: '0.16.0', + version: '0.16.0-dev', license: 'MIT', meson_version: '>=0.58.1', default_options: [ From ad06c12c89791dad0c3858a75102277127158063 Mon Sep 17 00:00:00 2001 From: Steven Newbury Date: Tue, 8 Feb 2022 12:02:51 +0000 Subject: [PATCH 123/298] util: Fix infinite loop in recursive function When testing Xwayland multi-HiDPI support with Wine + SimCity4 I encountered a 100% CPU lockup from sway. This turned out to be triggering a bug in the wlroots pointer contraint code. region_confine() contains multiple recursive calls where arguments are modified and resubmitted to the function. One of the calls is however made using the original arguments, if/when this triggers it results in the same codepath being followed each loop so the condition always applies. It makes much more sense if this was intended to apply the clamped values x,y instead of the original x1,y1, and indeed this fixes the infinite loop and results in correct behaviour. --- util/region.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/region.c b/util/region.c index 817d7b1a6..c5bd9e85e 100644 --- a/util/region.c +++ b/util/region.c @@ -214,7 +214,7 @@ static void region_confine(pixman_region32_t *region, double x1, double y1, doub int y_ext = floor(y) + (dy == 0 ? 0 : dy > 0 ? 1 : -1); if (pixman_region32_contains_point(region, x_ext, y_ext, &box)) { - return region_confine(region, x1, y1, x2, y2, x2_out, y2_out, box); + return region_confine(region, x, y, x2, y2, x2_out, y2_out, box); } else if (dx == 0 || dy == 0) { *x2_out = x; *y2_out = y; From e59f4d4ffa9ac2c7add84278b716b7e1c7ac74f3 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 17 Dec 2021 15:42:57 +0100 Subject: [PATCH 124/298] backend/drm: allow non-linear modifiers for multi-GPU Prior to [1], if an entry in a DRM format set was different than a single LINEAR modifier, implicit modifiers were always allowed. This has changed and now implicit modifiers are only allowed if INVALID is in the list of modifiers. So now we can safely enable explicit modifiers for cross-GPU imports, without risking receiving buffers with an implicit modifier. This should improve perf a bit on setups where two GPUs from the same vendor are used. This fixes the first bullet point from [2]. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3231 [2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3331 --- backend/drm/backend.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index b9e7274b2..267bbfb29 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -275,15 +275,17 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, goto error_mgpu_renderer; } - // Force a linear layout. In case explicit modifiers aren't supported, - // the meaning of implicit modifiers changes from one GPU to the other. - // In case explicit modifiers are supported, we still have no guarantee - // that the buffer producer will support these, so they might fallback - // to implicit modifiers. + // Forbid implicit modifiers, because their meaning changes from one + // GPU to another. for (size_t i = 0; i < texture_formats->len; i++) { const struct wlr_drm_format *fmt = texture_formats->formats[i]; - wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, - DRM_FORMAT_MOD_LINEAR); + for (size_t j = 0; j < fmt->len; j++) { + uint64_t mod = fmt->modifiers[j]; + if (mod == DRM_FORMAT_MOD_INVALID) { + continue; + } + wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, mod); + } } } From f91f38b79af2bcd091da7347e83066dea679a1bd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 15:55:41 +0200 Subject: [PATCH 125/298] backend/drm: remove wlr_drm_surface.{width,height} This information is stored in wlr_swapchain, no need to duplicate it. --- backend/drm/renderer.c | 52 ++++++++++++++++------------------ include/backend/drm/renderer.h | 6 +--- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 792de938f..601553138 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -48,31 +48,6 @@ void finish_drm_renderer(struct wlr_drm_renderer *renderer) { wlr_renderer_destroy(renderer->wlr_rend); } -bool init_drm_surface(struct wlr_drm_surface *surf, - struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, - const struct wlr_drm_format *drm_format) { - if (surf->width == width && surf->height == height) { - return true; - } - - surf->renderer = renderer; - surf->width = width; - surf->height = height; - - wlr_swapchain_destroy(surf->swapchain); - surf->swapchain = NULL; - - surf->swapchain = wlr_swapchain_create(renderer->allocator, width, height, - drm_format); - if (surf->swapchain == NULL) { - wlr_log(WLR_ERROR, "Failed to create swapchain"); - memset(surf, 0, sizeof(*surf)); - return false; - } - - return true; -} - static void finish_drm_surface(struct wlr_drm_surface *surf) { if (!surf || !surf->renderer) { return; @@ -83,12 +58,33 @@ static void finish_drm_surface(struct wlr_drm_surface *surf) { memset(surf, 0, sizeof(*surf)); } +bool init_drm_surface(struct wlr_drm_surface *surf, + struct wlr_drm_renderer *renderer, int width, int height, + const struct wlr_drm_format *drm_format) { + if (surf->swapchain->width == width && surf->swapchain->height == height) { + return true; + } + + finish_drm_surface(surf); + + surf->swapchain = wlr_swapchain_create(renderer->allocator, width, height, + drm_format); + if (surf->swapchain == NULL) { + wlr_log(WLR_ERROR, "Failed to create swapchain"); + return false; + } + + surf->renderer = renderer; + + return true; +} + struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, struct wlr_buffer *buffer) { struct wlr_renderer *renderer = surf->renderer->wlr_rend; - if (surf->width != (uint32_t)buffer->width || - surf->height != (uint32_t)buffer->height) { + if (surf->swapchain->width != buffer->width || + surf->swapchain->height != buffer->height) { wlr_log(WLR_ERROR, "Surface size doesn't match buffer size"); return NULL; } @@ -106,7 +102,7 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf, float mat[9]; wlr_matrix_identity(mat); - wlr_matrix_scale(mat, surf->width, surf->height); + wlr_matrix_scale(mat, surf->swapchain->width, surf->swapchain->height); if (!wlr_renderer_begin_with_buffer(renderer, dst)) { wlr_buffer_unlock(dst); diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h index 52a2a0536..77ed4127a 100644 --- a/include/backend/drm/renderer.h +++ b/include/backend/drm/renderer.h @@ -19,10 +19,6 @@ struct wlr_drm_renderer { struct wlr_drm_surface { struct wlr_drm_renderer *renderer; - - uint32_t width; - uint32_t height; - struct wlr_swapchain *swapchain; }; @@ -40,7 +36,7 @@ bool init_drm_renderer(struct wlr_drm_backend *drm, void finish_drm_renderer(struct wlr_drm_renderer *renderer); bool init_drm_surface(struct wlr_drm_surface *surf, - struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height, + struct wlr_drm_renderer *renderer, int width, int height, const struct wlr_drm_format *drm_format); bool drm_fb_import(struct wlr_drm_fb **fb, struct wlr_drm_backend *drm, From 27383a1929348daf01e18349f215c998b6ef8c2f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 14:04:16 +0200 Subject: [PATCH 126/298] contributing: add section about documentation conventions Document the existing conventions. Use `mystruct.foo` instead of `mystruct::foo` because `::` is pretty alien to C. Instead of backticks, use a different format to reference declarations in our docs: See foo(). See struct foo. See union bar. See enum baz. See typedef meh. This is inspired by the kernel's documentation style [1]. This format has the upside of being pretty natural to write and read, and can be automatically processed by documentation generators. [1]: https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#cross-referencing-from-restructuredtext --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 65446c184..b67855cb8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -216,6 +216,19 @@ Try to keep the use of macros to a minimum, especially if a function can do the job. If you do need to use them, try to keep them close to where they're being used and `#undef` them after. +### Documentation + +* Documentation comments for declarations start with `/**` and end with `*/`. +* Cross-reference other declarations by ending function names with `()`, and + writing `struct`, `union`, `enum` or `typedef` before types. +* Document fields which can be NULL with a `// may be NULL` comment, optionally + with more details describing when this can happen. +* Document the bits of a bitfield with a `// enum bar` comment. +* Document the `data` argument of a `struct wl_signal` with a `// struct foo` + comment. +* Document the contents and container of a `struct wl_list` with a + `// content.link` and `// container.list` comment. + ### Example ```c From 28d89779af6de0340533b2674a98ab6ecc238599 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 18:46:59 +0200 Subject: [PATCH 127/298] Reformat doc comments Unify the way we document our APIs. See CONTRIBUTING.md for the rules. --- include/wlr/backend.h | 15 ++-- include/wlr/backend/drm.h | 5 +- include/wlr/backend/headless.h | 6 +- include/wlr/backend/interface.h | 4 +- include/wlr/backend/libinput.h | 4 +- include/wlr/backend/session.h | 17 ++--- include/wlr/backend/wayland.h | 22 +++--- include/wlr/backend/x11.h | 16 ++--- include/wlr/interfaces/wlr_buffer.h | 8 +-- include/wlr/interfaces/wlr_keyboard.h | 2 +- include/wlr/interfaces/wlr_output.h | 4 +- include/wlr/interfaces/wlr_tablet_pad.h | 8 ++- include/wlr/render/allocator.h | 4 +- include/wlr/render/drm_format_set.h | 2 +- include/wlr/render/egl.h | 2 +- include/wlr/render/wlr_renderer.h | 12 ++-- include/wlr/render/wlr_texture.h | 2 +- include/wlr/types/wlr_buffer.h | 24 +++---- include/wlr/types/wlr_compositor.h | 11 +-- include/wlr/types/wlr_cursor.h | 25 +++---- include/wlr/types/wlr_data_control_v1.h | 4 +- include/wlr/types/wlr_data_device.h | 14 ++-- include/wlr/types/wlr_drm_lease_v1.h | 26 +++---- include/wlr/types/wlr_export_dmabuf_v1.h | 4 +- .../wlr_foreign_toplevel_management_v1.h | 32 +++++---- include/wlr/types/wlr_fullscreen_shell_v1.h | 2 +- include/wlr/types/wlr_gamma_control_v1.h | 2 +- include/wlr/types/wlr_idle.h | 2 +- include/wlr/types/wlr_idle_inhibit_v1.h | 4 +- include/wlr/types/wlr_input_method_v2.h | 16 ++--- include/wlr/types/wlr_keyboard.h | 10 +-- include/wlr/types/wlr_keyboard_group.h | 22 +++--- .../types/wlr_keyboard_shortcuts_inhibit_v1.h | 6 +- include/wlr/types/wlr_layer_shell_v1.h | 23 +++--- include/wlr/types/wlr_linux_dmabuf_v1.h | 6 +- include/wlr/types/wlr_output.h | 44 ++++++------ include/wlr/types/wlr_output_damage.h | 6 +- include/wlr/types/wlr_output_layout.h | 6 +- include/wlr/types/wlr_output_management_v1.h | 24 +++---- .../types/wlr_output_power_management_v1.h | 6 +- .../wlr/types/wlr_pointer_constraints_v1.h | 6 +- include/wlr/types/wlr_pointer_gestures_v1.h | 6 +- include/wlr/types/wlr_presentation_time.h | 20 +++--- include/wlr/types/wlr_primary_selection_v1.h | 8 +-- include/wlr/types/wlr_relative_pointer_v1.h | 6 +- include/wlr/types/wlr_scene.h | 10 +-- include/wlr/types/wlr_screencopy_v1.h | 4 +- include/wlr/types/wlr_seat.h | 70 +++++++++---------- include/wlr/types/wlr_server_decoration.h | 4 +- include/wlr/types/wlr_session_lock_v1.h | 8 +-- include/wlr/types/wlr_tablet_pad.h | 4 +- include/wlr/types/wlr_tablet_v2.h | 16 ++--- include/wlr/types/wlr_text_input_v3.h | 18 ++--- include/wlr/types/wlr_viewporter.h | 4 +- include/wlr/types/wlr_virtual_keyboard_v1.h | 6 +- include/wlr/types/wlr_virtual_pointer_v1.h | 6 +- include/wlr/types/wlr_xcursor_manager.h | 18 ++--- include/wlr/types/wlr_xdg_activation_v1.h | 2 +- include/wlr/types/wlr_xdg_decoration_v1.h | 8 +-- include/wlr/types/wlr_xdg_foreign_registry.h | 8 +-- include/wlr/types/wlr_xdg_foreign_v1.h | 8 +-- include/wlr/types/wlr_xdg_foreign_v2.h | 8 +-- include/wlr/types/wlr_xdg_shell.h | 31 ++++---- include/wlr/util/box.h | 23 +++--- include/wlr/util/log.h | 17 +++-- 65 files changed, 399 insertions(+), 372 deletions(-) diff --git a/include/wlr/backend.h b/include/wlr/backend.h index d781f74de..86decad41 100644 --- a/include/wlr/backend.h +++ b/include/wlr/backend.h @@ -14,22 +14,25 @@ struct wlr_backend_impl; +/** + * A backend provides a set of input and output devices. + */ struct wlr_backend { const struct wlr_backend_impl *impl; struct { - /** Raised when destroyed, passed the wlr_backend reference */ + /** Raised when destroyed */ struct wl_signal destroy; - /** Raised when new inputs are added, passed the wlr_input_device */ + /** Raised when new inputs are added, passed the struct wlr_input_device */ struct wl_signal new_input; - /** Raised when new outputs are added, passed the wlr_output */ + /** Raised when new outputs are added, passed the struct wlr_output */ struct wl_signal new_output; } events; }; /** * Automatically initializes the most suitable backend given the environment. - * Will always return a multibackend. The backend is created but not started. + * Will always return a multi-backend. The backend is created but not started. * Returns NULL on failure. */ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display); @@ -41,11 +44,11 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display); bool wlr_backend_start(struct wlr_backend *backend); /** * Destroy the backend and clean up all of its resources. Normally called - * automatically when the wl_display is destroyed. + * automatically when the struct wl_display is destroyed. */ void wlr_backend_destroy(struct wlr_backend *backend); /** - * Obtains the wlr_session reference from this backend if there is any. + * Obtains the struct wlr_session reference from this backend if there is any. * Might return NULL for backends that don't use a session. */ struct wlr_session *wlr_backend_get_session(struct wlr_backend *backend); diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 800bc585f..1617aa151 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -48,8 +48,9 @@ bool wlr_output_is_drm(struct wlr_output *output); uint32_t wlr_drm_connector_get_id(struct wlr_output *output); /** - * Tries to open non-master DRM FD. The compositor must not call `drmSetMaster` + * Tries to open non-master DRM FD. The compositor must not call drmSetMaster() * on the returned FD. + * * Returns a valid opened DRM FD, or -1 on error. */ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend); @@ -71,7 +72,7 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs, void wlr_drm_lease_terminate(struct wlr_drm_lease *lease); /** - * Add mode to the list of available modes + * Add mode to the list of available modes. */ typedef struct _drmModeModeInfo drmModeModeInfo; struct wlr_output_mode *wlr_drm_connector_add_mode(struct wlr_output *output, diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h index ff55746ff..2516f3a68 100644 --- a/include/wlr/backend/headless.h +++ b/include/wlr/backend/headless.h @@ -18,9 +18,9 @@ */ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display); /** - * Create a new headless output backed by an in-memory EGL framebuffer. You can - * read pixels from this framebuffer via wlr_renderer_read_pixels but it is - * otherwise not displayed. + * Create a new headless output. + * + * The buffers presented on the output won't be displayed to the user. */ struct wlr_output *wlr_headless_add_output(struct wlr_backend *backend, unsigned int width, unsigned int height); diff --git a/include/wlr/backend/interface.h b/include/wlr/backend/interface.h index f0cafb015..d5bb9bca0 100644 --- a/include/wlr/backend/interface.h +++ b/include/wlr/backend/interface.h @@ -23,8 +23,8 @@ struct wlr_backend_impl { }; /** - * Initializes common state on a wlr_backend and sets the implementation to the - * provided wlr_backend_impl reference. + * Initializes common state on a struct wlr_backend and sets the implementation + * to the provided struct wlr_backend_impl reference. */ void wlr_backend_init(struct wlr_backend *backend, const struct wlr_backend_impl *impl); diff --git a/include/wlr/backend/libinput.h b/include/wlr/backend/libinput.h index 94197b7ab..83d281f9d 100644 --- a/include/wlr/backend/libinput.h +++ b/include/wlr/backend/libinput.h @@ -18,7 +18,9 @@ struct wlr_input_device; struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, struct wlr_session *session); -/** Gets the underlying libinput_device handle for the given wlr_input_device */ +/** + * Gets the underlying struct libinput_device handle for the given input device. + */ struct libinput_device *wlr_libinput_get_device_handle( struct wlr_input_device *dev); diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h index c8461ff7c..e5deda574 100644 --- a/include/wlr/backend/session.h +++ b/include/wlr/backend/session.h @@ -79,36 +79,33 @@ struct wlr_device_change_event { * This should not be called if another program is already in control * of the terminal (Xorg, another Wayland compositor, etc.). * - * If libseat support is not enabled, or if a standalone backend is to be used, - * then you must have CAP_SYS_ADMIN or be root. It is safe to drop privileges - * after this is called. - * * Returns NULL on error. */ struct wlr_session *wlr_session_create(struct wl_display *disp); /* * Closes a previously opened session and restores the virtual terminal. - * You should call wlr_session_close_file on each files you opened - * with wlr_session_open_file before you call this. + * You should call wlr_session_close_file() on each files you opened + * with wlr_session_open_file() before you call this. */ void wlr_session_destroy(struct wlr_session *session); /* * Opens the file at path. - * This can only be used to open DRM or evdev (input) devices. + * + * This can only be used to open DRM or evdev (input) devices. Files opened via + * this function must be closed by calling wlr_session_close_file(). * * When the session becomes inactive: + * * - DRM files lose their DRM master status * - evdev files become invalid and should be closed - * - * Returns -errno on error. */ struct wlr_device *wlr_session_open_file(struct wlr_session *session, const char *path); /* - * Closes a file previously opened with wlr_session_open_file. + * Closes a file previously opened with wlr_session_open_file(). */ void wlr_session_close_file(struct wlr_session *session, struct wlr_device *device); diff --git a/include/wlr/backend/wayland.h b/include/wlr/backend/wayland.h index 0aed3aa14..a5b5e7a30 100644 --- a/include/wlr/backend/wayland.h +++ b/include/wlr/backend/wayland.h @@ -9,18 +9,18 @@ struct wlr_input_device; /** - * Creates a new wlr_wl_backend. This backend will be created with no outputs; - * you must use wlr_wl_output_create to add them. + * Creates a new Wayland backend. This backend will be created with no outputs; + * you must use wlr_wl_output_create() to add them. * * The `remote` argument is the name of the host compositor wayland socket. Set * to NULL for the default behaviour (WAYLAND_DISPLAY env variable or wayland-0 - * default) + * default). */ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char *remote); /** - * Returns the remote wl_display used by the Wayland backend. + * Returns the remote struct wl_display used by the Wayland backend. */ struct wl_display *wlr_wl_backend_get_remote_display(struct wlr_backend *backend); @@ -28,37 +28,37 @@ struct wl_display *wlr_wl_backend_get_remote_display(struct wlr_backend *backend * Adds a new output to this backend. You may remove outputs by destroying them. * Note that if called before initializing the backend, this will return NULL * and your outputs will be created during initialization (and given to you via - * the output_add signal). + * the new_output signal). */ struct wlr_output *wlr_wl_output_create(struct wlr_backend *backend); /** - * True if the given backend is a wlr_wl_backend. + * Check whether the provided backend is a Wayland backend. */ bool wlr_backend_is_wl(struct wlr_backend *backend); /** - * True if the given input device is a wlr_wl_input_device. + * Check whether the provided input device is a Wayland input device. */ bool wlr_input_device_is_wl(struct wlr_input_device *device); /** - * True if the given output is a wlr_wl_output. + * Check whether the provided output device is a Wayland output device. */ bool wlr_output_is_wl(struct wlr_output *output); /** - * Sets the title of a wlr_output which is a Wayland window. + * Sets the title of a struct wlr_output which is a Wayland toplevel. */ void wlr_wl_output_set_title(struct wlr_output *output, const char *title); /** - * Returns the remote wl_surface used by the Wayland output. + * Returns the remote struct wl_surface used by the Wayland output. */ struct wl_surface *wlr_wl_output_get_surface(struct wlr_output *output); /** - * Returns the remote wl_seat for a Wayland input device. + * Returns the remote struct wl_seat for a Wayland input device. */ struct wl_seat *wlr_wl_input_device_get_seat(struct wlr_input_device *dev); diff --git a/include/wlr/backend/x11.h b/include/wlr/backend/x11.h index c6aaaf80a..54d91c758 100644 --- a/include/wlr/backend/x11.h +++ b/include/wlr/backend/x11.h @@ -11,11 +11,11 @@ struct wlr_input_device; /** - * Creates a new wlr_x11_backend. This backend will be created with no outputs; - * you must use wlr_x11_output_create to add them. + * Creates a new X11 backend. This backend will be created with no outputs; + * you must use wlr_x11_output_create() to add them. * * The `x11_display` argument is the name of the X Display socket. Set - * to NULL for the default behaviour of XOpenDisplay. + * to NULL for the default behaviour of XOpenDisplay(). */ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, const char *x11_display); @@ -24,27 +24,27 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, * Adds a new output to this backend. You may remove outputs by destroying them. * Note that if called before initializing the backend, this will return NULL * and your outputs will be created during initialization (and given to you via - * the output_add signal). + * the new_output signal). */ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend); /** - * True if the given backend is a wlr_x11_backend. + * Check whether this backend is an X11 backend. */ bool wlr_backend_is_x11(struct wlr_backend *backend); /** - * True if the given input device is a wlr_x11_input_device. + * Check whether this input device is an X11 input device. */ bool wlr_input_device_is_x11(struct wlr_input_device *device); /** - * True if the given output is a wlr_x11_output. + * Check whether this output device is an X11 output device. */ bool wlr_output_is_x11(struct wlr_output *output); /** - * Sets the title of a wlr_output which is an X11 window. + * Sets the title of a struct wlr_output which is an X11 window. */ void wlr_x11_output_set_title(struct wlr_output *output, const char *title); diff --git a/include/wlr/interfaces/wlr_buffer.h b/include/wlr/interfaces/wlr_buffer.h index 05ccc1e7e..820300f65 100644 --- a/include/wlr/interfaces/wlr_buffer.h +++ b/include/wlr/interfaces/wlr_buffer.h @@ -31,16 +31,16 @@ struct wlr_buffer_resource_interface { /** * Initialize a buffer. This function should be called by producers. The * initialized buffer is referenced: once the producer is done with the buffer - * they should call wlr_buffer_drop. + * they should call wlr_buffer_drop(). */ void wlr_buffer_init(struct wlr_buffer *buffer, const struct wlr_buffer_impl *impl, int width, int height); /** - * Allows the registration of a wl_resource implementation. + * Allows the registration of a struct wl_resource implementation. * - * The matching function will be called for the wl_resource when creating a - * wlr_buffer from a wl_resource. + * The matching function will be called for the struct wl_resource when creating + * a struct wlr_buffer from a struct wl_resource. */ void wlr_buffer_register_resource_interface( const struct wlr_buffer_resource_interface *iface); diff --git a/include/wlr/interfaces/wlr_keyboard.h b/include/wlr/interfaces/wlr_keyboard.h index 06b079891..2ec7c8cfe 100644 --- a/include/wlr/interfaces/wlr_keyboard.h +++ b/include/wlr/interfaces/wlr_keyboard.h @@ -21,7 +21,7 @@ void wlr_keyboard_init(struct wlr_keyboard *keyboard, const struct wlr_keyboard_impl *impl, const char *name); /** - * Cleans up all of the resources owned by wlr_keyboard. + * Cleans up all of the resources owned by the struct wlr_keyboard. */ void wlr_keyboard_finish(struct wlr_keyboard *keyboard); diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index c02a588f5..4de02c0bd 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -26,7 +26,7 @@ WLR_OUTPUT_STATE_SUBPIXEL) /** - * A backend implementation of wlr_output. + * A backend implementation of struct wlr_output. * * The commit function is mandatory. Other functions are optional. */ @@ -39,7 +39,7 @@ struct wlr_output_impl { * The hotspot indicates the offset that needs to be applied to the * top-left corner of the image to match the cursor position. In other * words, the image should be displayed at (x - hotspot_x, y - hotspot_y). - * The hotspot is given in the texture's coordinate space. + * The hotspot is given in the buffer's coordinate space. */ bool (*set_cursor)(struct wlr_output *output, struct wlr_buffer *buffer, int hotspot_x, int hotspot_y); diff --git a/include/wlr/interfaces/wlr_tablet_pad.h b/include/wlr/interfaces/wlr_tablet_pad.h index e052dd837..f4a422f2f 100644 --- a/include/wlr/interfaces/wlr_tablet_pad.h +++ b/include/wlr/interfaces/wlr_tablet_pad.h @@ -19,9 +19,11 @@ void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name); /** - * Cleans up the resources owned by a wlr_tablet_pad. - * This function will not clean the memory allocated by wlr_tablet_pad_group, - * it's the responsibility of the caller to clean it. + * Cleans up the resources owned by a struct wlr_tablet_pad. + * + * This function will not clean the memory allocated by + * struct wlr_tablet_pad_group, it's the responsibility of the caller to clean + * it. */ void wlr_tablet_pad_finish(struct wlr_tablet_pad *pad); diff --git a/include/wlr/render/allocator.h b/include/wlr/render/allocator.h index 3150e36c3..f5bb7522c 100644 --- a/include/wlr/render/allocator.h +++ b/include/wlr/render/allocator.h @@ -37,7 +37,7 @@ struct wlr_allocator { }; /** - * Creates the adequate wlr_allocator given a backend and a renderer + * Creates the adequate struct wlr_allocator given a backend and a renderer. */ struct wlr_allocator *wlr_allocator_autocreate(struct wlr_backend *backend, struct wlr_renderer *renderer); @@ -50,7 +50,7 @@ void wlr_allocator_destroy(struct wlr_allocator *alloc); * Allocate a new buffer. * * When the caller is done with it, they must unreference it by calling - * wlr_buffer_drop. + * wlr_buffer_drop(). * * The `format` passed in indicates the format to use and the list of * acceptable modifiers. The order in which modifiers are listed is not diff --git a/include/wlr/render/drm_format_set.h b/include/wlr/render/drm_format_set.h index 9f4a86ea4..6dbdc7494 100644 --- a/include/wlr/render/drm_format_set.h +++ b/include/wlr/render/drm_format_set.h @@ -51,7 +51,7 @@ struct wlr_drm_format_set { void wlr_drm_format_set_finish(struct wlr_drm_format_set *set); /** - * Return a pointer to a member of this `wlr_drm_format_set` of format + * Return a pointer to a member of this struct wlr_drm_format_set of format * `format`, or NULL if none exists. */ const struct wlr_drm_format *wlr_drm_format_set_get( diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 0d84958be..e4416e0ba 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -77,7 +77,7 @@ struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, * Make the EGL context current. * * Callers are expected to clear the current context when they are done by - * calling wlr_egl_unset_current. + * calling wlr_egl_unset_current(). */ bool wlr_egl_make_current(struct wlr_egl *egl); diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index d8b04dc72..50ba6b215 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -77,13 +77,13 @@ void wlr_render_quad_with_matrix(struct wlr_renderer *r, const float color[static 4], const float matrix[static 9]); /** * Get the shared-memory formats supporting import usage. Buffers allocated - * with a format from this list may be imported via wlr_texture_from_pixels. + * with a format from this list may be imported via wlr_texture_from_pixels(). */ const uint32_t *wlr_renderer_get_shm_texture_formats( struct wlr_renderer *r, size_t *len); /** * Get the DMA-BUF formats supporting sampling usage. Buffers allocated with - * a format from this list may be imported via wlr_texture_from_dmabuf. + * a format from this list may be imported via wlr_texture_from_dmabuf(). */ const struct wlr_drm_format_set *wlr_renderer_get_dmabuf_texture_formats( struct wlr_renderer *renderer); @@ -92,7 +92,7 @@ const struct wlr_drm_format_set *wlr_renderer_get_dmabuf_texture_formats( * bytes. * * If `flags` is not NULl, the caller indicates that it accepts frame flags - * defined in `enum wlr_renderer_read_pixels_flags`. + * defined in enum wlr_renderer_read_pixels_flags. */ bool wlr_renderer_read_pixels(struct wlr_renderer *r, uint32_t fmt, uint32_t *flags, uint32_t stride, uint32_t width, uint32_t height, @@ -107,7 +107,7 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r, struct wl_display *wl_display); /** - * Initializes wl_shm on the provided wl_display. + * Initializes wl_shm on the provided struct wl_display. */ bool wlr_renderer_init_wl_shm(struct wlr_renderer *r, struct wl_display *wl_display); @@ -120,7 +120,9 @@ bool wlr_renderer_init_wl_shm(struct wlr_renderer *r, int wlr_renderer_get_drm_fd(struct wlr_renderer *r); /** - * Destroys this wlr_renderer. Textures must be destroyed separately. + * Destroys the renderer. + * + * Textures must be destroyed separately. */ void wlr_renderer_destroy(struct wlr_renderer *renderer); diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 90bb5de56..93fc221c3 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -51,7 +51,7 @@ bool wlr_texture_write_pixels(struct wlr_texture *texture, const void *data); /** - * Destroys this wlr_texture. + * Destroys the texture. */ void wlr_texture_destroy(struct wlr_texture *texture); diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 604dc17a3..17b93e5c4 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -27,8 +27,8 @@ struct wlr_shm_attributes { /** * Buffer capabilities. * - * These bits indicate the features supported by a wlr_buffer. There is one bit - * per function in wlr_buffer_impl. + * These bits indicate the features supported by a struct wlr_buffer. There is + * one bit per function in struct wlr_buffer_impl. */ enum wlr_buffer_cap { WLR_BUFFER_CAP_DATA_PTR = 1 << 0, @@ -69,7 +69,7 @@ void wlr_buffer_drop(struct wlr_buffer *buffer); /** * Lock the buffer. This function should be called by consumers to make * sure the buffer can be safely read from. Once the consumer is done with the - * buffer, they should call wlr_buffer_unlock. + * buffer, they should call wlr_buffer_unlock(). */ struct wlr_buffer *wlr_buffer_lock(struct wlr_buffer *buffer); /** @@ -82,7 +82,7 @@ void wlr_buffer_unlock(struct wlr_buffer *buffer); * returns false. * * The returned DMA-BUF attributes are valid for the lifetime of the - * wlr_buffer. The caller isn't responsible for cleaning up the DMA-BUF + * struct wlr_buffer. The caller isn't responsible for cleaning up the DMA-BUF * attributes. */ bool wlr_buffer_get_dmabuf(struct wlr_buffer *buffer, @@ -92,16 +92,16 @@ bool wlr_buffer_get_dmabuf(struct wlr_buffer *buffer, * memory, returns false. * * The returned shared memory attributes are valid for the lifetime of the - * wlr_buffer. The caller isn't responsible for cleaning up the shared memory - * attributes. + * struct wlr_buffer. The caller isn't responsible for cleaning up the shared + * memory attributes. */ bool wlr_buffer_get_shm(struct wlr_buffer *buffer, struct wlr_shm_attributes *attribs); /** - * Transforms a wl_resource into a wlr_buffer and locks it. Once the caller is - * done with the buffer, they must call wlr_buffer_unlock. + * Transforms a struct wl_resource into a struct wlr_buffer and locks it. Once + * the caller is done with the buffer, they must call wlr_buffer_unlock(). * - * The provided wl_resource must be a wl_buffer. + * The provided struct wl_resource must be a wl_buffer. */ struct wlr_buffer *wlr_buffer_from_resource(struct wl_resource *resource); @@ -126,7 +126,7 @@ enum wlr_buffer_data_ptr_access_flag { * * The returned pointer should be pointing to a valid memory region for the * operations specified in the flags. The returned pointer is only valid up to - * the next buffer_end_data_ptr_access call. + * the next wlr_buffer_end_data_ptr_access() call. */ bool wlr_buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags, void **data, uint32_t *format, size_t *stride); @@ -157,8 +157,8 @@ struct wlr_client_buffer { }; /** - * Creates a wlr_client_buffer from a given wlr_buffer by creating a texture - * from it, and copying its wl_resource. + * Creates a struct wlr_client_buffer from a given struct wlr_buffer by creating + * a texture from it, and copying its struct wl_resource. */ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, struct wlr_renderer *renderer); diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 071610b8f..bff6bc833 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -147,7 +147,7 @@ struct wlr_surface { struct wl_signal destroy; } events; - struct wl_list current_outputs; // wlr_surface_output::link + struct wl_list current_outputs; // wlr_surface_output.link struct wlr_addon_set addons; void *data; @@ -243,9 +243,10 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface, void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box); /** - * Get the wlr_surface corresponding to a wl_surface resource. This asserts - * that the resource is a valid wl_surface resource created by wlroots and - * will never return NULL. + * Get the struct wlr_surface corresponding to a wl_surface resource. + * + * This asserts that the resource is a valid wl_surface resource created by + * wlroots and will never return NULL. */ struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource); @@ -281,7 +282,7 @@ void wlr_surface_get_buffer_source_box(struct wlr_surface *surface, * Acquire a lock for the pending surface state. * * The state won't be committed before the caller releases the lock. Instead, - * the state becomes cached. The caller needs to use wlr_surface_unlock_cached + * the state becomes cached. The caller needs to use wlr_surface_unlock_cached() * to release the lock. * * Returns a surface commit sequence number for the cached state. diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 95a3e37f3..06ae2f1f0 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -18,12 +18,12 @@ struct wlr_input_device; /** * wlr_cursor implements the behavior of the "cursor", that is, the image on the * screen typically moved about with a mouse or so. It provides tracking for - * this in global coordinates, and integrates with wlr_output, - * wlr_output_layout, and wlr_input_device. You can use it to abstract multiple - * input devices over a single cursor, constrain cursor movement to the usable - * area of a wlr_output_layout and communicate position updates to the hardware - * cursor, constrain specific input devices to specific outputs or regions of - * the screen, and so on. + * this in global coordinates, and integrates with struct wlr_output, + * struct wlr_output_layout, and struct wlr_input_device. You can use it to + * abstract multiple input devices over a single cursor, constrain cursor + * movement to the usable area of a struct wlr_output_layout and communicate + * position updates to the hardware cursor, constrain specific input devices to + * specific outputs or regions of the screen, and so on. */ struct wlr_box; @@ -37,15 +37,15 @@ struct wlr_cursor { * The interpretation of these signals is the responsibility of the * compositor, but some helpers are provided for your benefit. If you * receive a relative motion event, for example, you may want to call - * wlr_cursor_move. If you receive an absolute event, call - * wlr_cursor_warp_absolute. If you pass an input device into these + * wlr_cursor_move(). If you receive an absolute event, call + * wlr_cursor_warp_absolute(). If you pass an input device into these * functions, it will apply the region/output constraints associated with * that device to the resulting cursor motion. If an output layout is * attached, these functions will constrain the resulting cursor motion to * within the usable space of the output layout. * - * Re-broadcasting these signals to, for example, a wlr_seat, is also your - * responsibility. + * Re-broadcasting these signals to, for example, a struct wlr_seat, is also + * your responsibility. */ struct { struct wl_signal motion; @@ -191,13 +191,14 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_output *output); /** - * Maps this cursor to an arbitrary region on the associated wlr_output_layout. + * Maps this cursor to an arbitrary region on the associated + * struct wlr_output_layout. */ void wlr_cursor_map_to_region(struct wlr_cursor *cur, const struct wlr_box *box); /** * Maps inputs from this input device to an arbitrary region on the associated - * wlr_output_layout. + * struct wlr_output_layout. */ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, struct wlr_input_device *dev, const struct wlr_box *box); diff --git a/include/wlr/types/wlr_data_control_v1.h b/include/wlr/types/wlr_data_control_v1.h index c7e0adf02..4435f14a2 100644 --- a/include/wlr/types/wlr_data_control_v1.h +++ b/include/wlr/types/wlr_data_control_v1.h @@ -14,7 +14,7 @@ struct wlr_data_control_manager_v1 { struct wl_global *global; - struct wl_list devices; // wlr_data_control_device_v1::link + struct wl_list devices; // wlr_data_control_device_v1.link struct { struct wl_signal destroy; @@ -27,7 +27,7 @@ struct wlr_data_control_manager_v1 { struct wlr_data_control_device_v1 { struct wl_resource *resource; struct wlr_data_control_manager_v1 *manager; - struct wl_list link; // wlr_data_control_manager_v1::devices + struct wl_list link; // wlr_data_control_manager_v1.devices struct wlr_seat *seat; struct wl_resource *selection_offer_resource; // current selection offer diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index 87c578aed..9f2481e6f 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -43,7 +43,7 @@ struct wlr_data_offer { struct wl_resource *resource; struct wlr_data_source *source; enum wlr_data_offer_type type; - struct wl_list link; // wlr_seat::{selection_offers,drag_offers} + struct wl_list link; // wlr_seat.{selection_offers,drag_offers} uint32_t actions; enum wl_data_device_manager_dnd_action preferred_action; @@ -54,7 +54,7 @@ struct wlr_data_offer { /** * A data source implementation. Only the `send` function is mandatory. Refer to - * the matching wl_data_source_* functions documentation to know what they do. + * the matching `wlr_data_source_*` functions documentation to know what they do. */ struct wlr_data_source_impl { void (*send)(struct wlr_data_source *source, const char *mime_type, @@ -131,8 +131,8 @@ struct wlr_drag { struct { struct wl_signal focus; - struct wl_signal motion; // wlr_drag_motion_event - struct wl_signal drop; // wlr_drag_drop_event + struct wl_signal motion; // struct wlr_drag_motion_event + struct wl_signal drop; // struct wlr_drag_drop_event struct wl_signal destroy; } events; @@ -155,7 +155,7 @@ struct wlr_drag_drop_event { }; /** - * Create a wl data device manager global for this display. + * Create a wl_data_device_manager global for this display. */ struct wlr_data_device_manager *wlr_data_device_manager_create( struct wl_display *display); @@ -181,7 +181,7 @@ void wlr_seat_set_selection(struct wlr_seat *seat, /** * Creates a new drag. To request to start the drag, call - * `wlr_seat_request_start_drag`. + * wlr_seat_request_start_drag(). */ struct wlr_drag *wlr_drag_create(struct wlr_seat_client *seat_client, struct wlr_data_source *source, struct wlr_surface *icon_surface); @@ -258,7 +258,7 @@ void wlr_data_source_dnd_finish(struct wlr_data_source *source); * Notifies the data source that a target accepts the drag with the specified * action. * - * This shouldn't be called after `wlr_data_source_dnd_drop` unless the + * This shouldn't be called after wlr_data_source_dnd_drop() unless the * drag-and-drop operation ended in an "ask" action. */ void wlr_data_source_dnd_action(struct wlr_data_source *source, diff --git a/include/wlr/types/wlr_drm_lease_v1.h b/include/wlr/types/wlr_drm_lease_v1.h index 5a7827ea3..314eb8cc1 100644 --- a/include/wlr/types/wlr_drm_lease_v1.h +++ b/include/wlr/types/wlr_drm_lease_v1.h @@ -15,7 +15,7 @@ struct wlr_backend; struct wlr_output; struct wlr_drm_lease_v1_manager { - struct wl_list devices; // wlr_drm_lease_device_v1::link; + struct wl_list devices; // wlr_drm_lease_device_v1.link struct wl_display *display; struct wl_listener display_destroy; @@ -23,9 +23,9 @@ struct wlr_drm_lease_v1_manager { struct { /** * Upon receiving this signal, call - * wlr_drm_lease_device_v1_grant_lease_request to grant a lease of the + * wlr_drm_lease_device_v1_grant_lease_request() to grant a lease of the * requested DRM resources, or - * wlr_drm_lease_device_v1_reject_lease_request to reject the request. + * wlr_drm_lease_device_v1_reject_lease_request() to reject the request. */ struct wl_signal request; } events; @@ -38,10 +38,10 @@ struct wlr_drm_lease_device_v1 { struct wlr_drm_lease_v1_manager *manager; struct wlr_backend *backend; - struct wl_list connectors; // wlr_drm_lease_connector_v1::link - struct wl_list leases; // wlr_drm_lease_v1::link - struct wl_list requests; // wlr_drm_lease_request_v1::link - struct wl_list link; // wlr_drm_lease_v1_manager::devices + struct wl_list connectors; // wlr_drm_lease_connector_v1.link + struct wl_list leases; // wlr_drm_lease_v1.link + struct wl_list requests; // wlr_drm_lease_request_v1.link + struct wl_list link; // wlr_drm_lease_v1_manager.devices struct wl_listener backend_destroy; @@ -51,7 +51,7 @@ struct wlr_drm_lease_device_v1 { struct wlr_drm_lease_v1; struct wlr_drm_lease_connector_v1 { - struct wl_list resources; // wl_resource_get_link + struct wl_list resources; // wl_resource_get_link() struct wlr_output *output; struct wlr_drm_lease_device_v1 *device; @@ -60,7 +60,7 @@ struct wlr_drm_lease_connector_v1 { struct wl_listener destroy; - struct wl_list link; // wlr_drm_lease_device_v1::connectors + struct wl_list link; // wlr_drm_lease_device_v1.connectors }; struct wlr_drm_lease_request_v1 { @@ -76,7 +76,7 @@ struct wlr_drm_lease_request_v1 { bool invalid; - struct wl_list link; // wlr_drm_lease_device_v1::requests + struct wl_list link; // wlr_drm_lease_device_v1.requests }; struct wlr_drm_lease_v1 { @@ -97,7 +97,8 @@ struct wlr_drm_lease_v1 { /** * Creates a DRM lease manager. A DRM lease device will be created for each - * DRM backend supplied in case of a wlr_multi_backend. + * DRM backend supplied in case of a struct wlr_multi_backend. + * * Returns NULL if no DRM backend is supplied. */ struct wlr_drm_lease_v1_manager *wlr_drm_lease_v1_manager_create( @@ -105,6 +106,7 @@ struct wlr_drm_lease_v1_manager *wlr_drm_lease_v1_manager_create( /** * Offers a wlr_output for lease. + * * Returns false if the output can't be offered to lease. */ bool wlr_drm_lease_v1_manager_offer_output( @@ -120,7 +122,7 @@ void wlr_drm_lease_v1_manager_withdraw_output( /** * Grants a client's lease request. The lease device will then provision the * DRM lease and transfer the file descriptor to the client. After calling this, - * each wlr_output leased is destroyed, and will be re-issued through + * each struct wlr_output leased is destroyed, and will be re-issued through * wlr_backend.events.new_outputs when the lease is revoked. * * This will return NULL without leasing any resources if the lease is invalid; diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h index 344e6cbf9..39e83be72 100644 --- a/include/wlr/types/wlr_export_dmabuf_v1.h +++ b/include/wlr/types/wlr_export_dmabuf_v1.h @@ -15,7 +15,7 @@ struct wlr_export_dmabuf_manager_v1 { struct wl_global *global; - struct wl_list frames; // wlr_export_dmabuf_frame_v1::link + struct wl_list frames; // wlr_export_dmabuf_frame_v1.link struct wl_listener display_destroy; @@ -27,7 +27,7 @@ struct wlr_export_dmabuf_manager_v1 { struct wlr_export_dmabuf_frame_v1 { struct wl_resource *resource; struct wlr_export_dmabuf_manager_v1 *manager; - struct wl_list link; // wlr_export_dmabuf_manager_v1::frames + struct wl_list link; // wlr_export_dmabuf_manager_v1.frames struct wlr_output *output; diff --git a/include/wlr/types/wlr_foreign_toplevel_management_v1.h b/include/wlr/types/wlr_foreign_toplevel_management_v1.h index d9030b2ea..c4abcb3dd 100644 --- a/include/wlr/types/wlr_foreign_toplevel_management_v1.h +++ b/include/wlr/types/wlr_foreign_toplevel_management_v1.h @@ -15,8 +15,8 @@ struct wlr_foreign_toplevel_manager_v1 { struct wl_event_loop *event_loop; struct wl_global *global; - struct wl_list resources; // wl_resource_get_link - struct wl_list toplevels; // wlr_foreign_toplevel_handle_v1::link + struct wl_list resources; // wl_resource_get_link() + struct wl_list toplevels; // wlr_foreign_toplevel_handle_v1.link struct wl_listener display_destroy; @@ -35,7 +35,7 @@ enum wlr_foreign_toplevel_handle_v1_state { }; struct wlr_foreign_toplevel_handle_v1_output { - struct wl_list link; // wlr_foreign_toplevel_handle_v1::outputs + struct wl_list link; // wlr_foreign_toplevel_handle_v1.outputs struct wlr_output *output; struct wlr_foreign_toplevel_handle_v1 *toplevel; @@ -54,21 +54,21 @@ struct wlr_foreign_toplevel_handle_v1 { char *title; char *app_id; struct wlr_foreign_toplevel_handle_v1 *parent; - struct wl_list outputs; // wlr_foreign_toplevel_v1_output - uint32_t state; // wlr_foreign_toplevel_v1_state + struct wl_list outputs; // wlr_foreign_toplevel_v1_output.link + uint32_t state; // enum wlr_foreign_toplevel_v1_state struct { - // wlr_foreign_toplevel_handle_v1_maximized_event + // struct wlr_foreign_toplevel_handle_v1_maximized_event struct wl_signal request_maximize; - //wlr_foreign_toplevel_handle_v1_minimized_event + // struct wlr_foreign_toplevel_handle_v1_minimized_event struct wl_signal request_minimize; - //wlr_foreign_toplevel_handle_v1_activated_event + // struct wlr_foreign_toplevel_handle_v1_activated_event struct wl_signal request_activate; - //wlr_foreign_toplevel_handle_v1_fullscreen_event + // struct wlr_foreign_toplevel_handle_v1_fullscreen_event struct wl_signal request_fullscreen; struct wl_signal request_close; - //wlr_foreign_toplevel_handle_v1_set_rectangle_event + // struct wlr_foreign_toplevel_handle_v1_set_rectangle_event struct wl_signal set_rectangle; struct wl_signal destroy; } events; @@ -108,12 +108,14 @@ struct wlr_foreign_toplevel_manager_v1 *wlr_foreign_toplevel_manager_v1_create( struct wlr_foreign_toplevel_handle_v1 *wlr_foreign_toplevel_handle_v1_create( struct wlr_foreign_toplevel_manager_v1 *manager); -/* Destroy the given toplevel handle, sending the closed event to any +/** + * Destroy the given toplevel handle, sending the closed event to any * client. Also, if the destroyed toplevel is set as a parent of any * other valid toplevel, clients still holding a handle to both are * sent a parent signal with NULL parent. If this is not desired, the * caller should ensure that any child toplevels are destroyed before - * the parent. */ + * the parent. + */ void wlr_foreign_toplevel_handle_v1_destroy( struct wlr_foreign_toplevel_handle_v1 *toplevel); @@ -136,11 +138,13 @@ void wlr_foreign_toplevel_handle_v1_set_activated( void wlr_foreign_toplevel_handle_v1_set_fullscreen( struct wlr_foreign_toplevel_handle_v1* toplevel, bool fullscreen); -/* Set the parent of a toplevel. If the parent changed from its previous +/** + * Set the parent of a toplevel. If the parent changed from its previous * value, also sends a parent event to all clients that hold handles to * both toplevel and parent (no message is sent to clients that have * previously destroyed their parent handle). NULL is allowed as the - * parent, meaning no parent exists. */ + * parent, meaning no parent exists. + */ void wlr_foreign_toplevel_handle_v1_set_parent( struct wlr_foreign_toplevel_handle_v1 *toplevel, struct wlr_foreign_toplevel_handle_v1 *parent); diff --git a/include/wlr/types/wlr_fullscreen_shell_v1.h b/include/wlr/types/wlr_fullscreen_shell_v1.h index ea8057f16..4e5b2cfe6 100644 --- a/include/wlr/types/wlr_fullscreen_shell_v1.h +++ b/include/wlr/types/wlr_fullscreen_shell_v1.h @@ -17,7 +17,7 @@ struct wlr_fullscreen_shell_v1 { struct { struct wl_signal destroy; - // wlr_fullscreen_shell_v1_present_surface_event + // struct wlr_fullscreen_shell_v1_present_surface_event struct wl_signal present_surface; } events; diff --git a/include/wlr/types/wlr_gamma_control_v1.h b/include/wlr/types/wlr_gamma_control_v1.h index b247bae34..025571487 100644 --- a/include/wlr/types/wlr_gamma_control_v1.h +++ b/include/wlr/types/wlr_gamma_control_v1.h @@ -5,7 +5,7 @@ struct wlr_gamma_control_manager_v1 { struct wl_global *global; - struct wl_list controls; // wlr_gamma_control_v1::link + struct wl_list controls; // wlr_gamma_control_v1.link struct wl_listener display_destroy; diff --git a/include/wlr/types/wlr_idle.h b/include/wlr/types/wlr_idle.h index 8e89a341f..0e1101806 100644 --- a/include/wlr/types/wlr_idle.h +++ b/include/wlr/types/wlr_idle.h @@ -23,7 +23,7 @@ struct wlr_idle { struct wl_global *global; - struct wl_list idle_timers; // wlr_idle_timeout::link + struct wl_list idle_timers; // wlr_idle_timeout.link struct wl_event_loop *event_loop; bool enabled; diff --git a/include/wlr/types/wlr_idle_inhibit_v1.h b/include/wlr/types/wlr_idle_inhibit_v1.h index 59ec83ffb..3127cfdf7 100644 --- a/include/wlr/types/wlr_idle_inhibit_v1.h +++ b/include/wlr/types/wlr_idle_inhibit_v1.h @@ -24,7 +24,7 @@ */ struct wlr_idle_inhibit_manager_v1 { - struct wl_list inhibitors; // wlr_idle_inhibit_inhibitor_v1::link + struct wl_list inhibitors; // wlr_idle_inhibit_inhibitor_v1.link struct wl_global *global; struct wl_listener display_destroy; @@ -42,7 +42,7 @@ struct wlr_idle_inhibitor_v1 { struct wl_resource *resource; struct wl_listener surface_destroy; - struct wl_list link; // wlr_idle_inhibit_manager_v1::inhibitors; + struct wl_list link; // wlr_idle_inhibit_manager_v1.inhibitors struct { struct wl_signal destroy; diff --git a/include/wlr/types/wlr_input_method_v2.h b/include/wlr/types/wlr_input_method_v2.h index e4401d299..316cecd5d 100644 --- a/include/wlr/types/wlr_input_method_v2.h +++ b/include/wlr/types/wlr_input_method_v2.h @@ -51,10 +51,10 @@ struct wlr_input_method_v2 { struct wl_listener seat_client_destroy; struct { - struct wl_signal commit; // (struct wlr_input_method_v2*) - struct wl_signal new_popup_surface; // (struct wlr_input_popup_surface_v2*) - struct wl_signal grab_keyboard; // (struct wlr_input_method_keyboard_grab_v2*) - struct wl_signal destroy; // (struct wlr_input_method_v2*) + struct wl_signal commit; // struct wlr_input_method_v2 * + struct wl_signal new_popup_surface; // struct wlr_input_popup_surface_v2 * + struct wl_signal grab_keyboard; // struct wlr_input_method_keyboard_grab_v2 * + struct wl_signal destroy; // struct wlr_input_method_v2 * } events; }; @@ -87,19 +87,19 @@ struct wlr_input_method_keyboard_grab_v2 { struct wl_listener keyboard_destroy; struct { - struct wl_signal destroy; // (struct wlr_input_method_keyboard_grab_v2*) + struct wl_signal destroy; // struct wlr_input_method_keyboard_grab_v2 * } events; }; struct wlr_input_method_manager_v2 { struct wl_global *global; - struct wl_list input_methods; // struct wlr_input_method_v2*::link + struct wl_list input_methods; // struct wlr_input_method_v2.link struct wl_listener display_destroy; struct { - struct wl_signal input_method; // (struct wlr_input_method_v2*) - struct wl_signal destroy; // (struct wlr_input_method_manager_v2*) + struct wl_signal input_method; // struct wlr_input_method_v2 * + struct wl_signal destroy; // struct wlr_input_method_manager_v2 * } events; }; diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index d8415933f..6a7eff810 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -73,8 +73,8 @@ struct wlr_keyboard { struct { /** - * The `key` event signals with a `wlr_event_keyboard_key` event that a - * key has been pressed or released on the keyboard. This event is + * The `key` event signals with a struct wlr_event_keyboard_key_event + * that a key has been pressed or released on the keyboard. This event is * emitted before the xkb state of the keyboard has been updated * (including modifiers). */ @@ -82,9 +82,9 @@ struct wlr_keyboard { /** * The `modifiers` event signals that the modifier state of the - * `wlr_keyboard` has been updated. At this time, you can read the - * modifier state of the `wlr_keyboard` and handle the updated state by - * sending it to clients. + * struct wlr_keyboard has been updated. At this time, you can read the + * modifier state of the struct wlr_keyboard and handle the updated + * state by sending it to clients. */ struct wl_signal modifiers; struct wl_signal keymap; diff --git a/include/wlr/types/wlr_keyboard_group.h b/include/wlr/types/wlr_keyboard_group.h index 3906d9489..0d5c6a2a4 100644 --- a/include/wlr/types/wlr_keyboard_group.h +++ b/include/wlr/types/wlr_keyboard_group.h @@ -14,28 +14,28 @@ struct wlr_keyboard_group { struct wlr_keyboard keyboard; - struct wl_list devices; // keyboard_group_device::link - struct wl_list keys; // keyboard_group_key::link + struct wl_list devices; // keyboard_group_device.link + struct wl_list keys; // keyboard_group_key.link struct { - /* + /** * Sent when a keyboard has entered the group with keys currently * pressed that are not pressed by any other keyboard in the group. The - * data for this signal will be a wl_array containing the key codes. - * This should be used to update the compositor's internal state. + * data for this signal will be a struct wl_array containing the key + * codes. This should be used to update the compositor's internal state. * Bindings should not be triggered based off of these key codes and * they should also not notify any surfaces of the key press. */ struct wl_signal enter; - /* + /** * Sent when a keyboard has left the group with keys currently pressed * that are not pressed by any other keyboard in the group. The data for - * this signal will be a wl_array containing the key codes. This should - * be used to update the compositor's internal state. Bindings should - * not be triggered based off of these key codes. Additionally, surfaces - * should only be notified if they received a corresponding key press - * for the key code. + * this signal will be a struct wl_array containing the key codes. This + * should be used to update the compositor's internal state. Bindings + * should not be triggered based off of these key codes. Additionally, + * surfaces should only be notified if they received a corresponding key + * press for the key code. */ struct wl_signal leave; } events; diff --git a/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h b/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h index e212e0f4f..946e75f4e 100644 --- a/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h +++ b/include/wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h @@ -23,14 +23,14 @@ */ struct wlr_keyboard_shortcuts_inhibit_manager_v1 { - // wlr_keyboard_shortcuts_inhibitor_v1::link + // wlr_keyboard_shortcuts_inhibitor_v1.link struct wl_list inhibitors; struct wl_global *global; struct wl_listener display_destroy; struct { - struct wl_signal new_inhibitor; // wlr_keyboard_shortcuts_inhibitor_v1 + struct wl_signal new_inhibitor; // struct wlr_keyboard_shortcuts_inhibitor_v1 struct wl_signal destroy; } events; @@ -46,7 +46,7 @@ struct wlr_keyboard_shortcuts_inhibitor_v1 { struct wl_listener surface_destroy; struct wl_listener seat_destroy; - // wlr_keyboard_shortcuts_inhibit_manager_v1::inhibitors + // wlr_keyboard_shortcuts_inhibit_manager_v1.inhibitors struct wl_list link; struct { diff --git a/include/wlr/types/wlr_layer_shell_v1.h b/include/wlr/types/wlr_layer_shell_v1.h index fcb72f242..e97c73117 100644 --- a/include/wlr/types/wlr_layer_shell_v1.h +++ b/include/wlr/types/wlr_layer_shell_v1.h @@ -19,11 +19,11 @@ * wlr_layer_shell_v1 allows clients to arrange themselves in "layers" on the * desktop in accordance with the wlr-layer-shell protocol. When a client is * added, the new_surface signal will be raised and passed a reference to our - * wlr_layer_surface_v1. At this time, the client will have configured the + * struct wlr_layer_surface_v1. At this time, the client will have configured the * surface as it desires, including information like desired anchors and * margins. The compositor should use this information to decide how to arrange * the layer on-screen, then determine the dimensions of the layer and call - * wlr_layer_surface_v1_configure. The client will then attach a buffer and + * wlr_layer_surface_v1_configure(). The client will then attach a buffer and * commit the surface, at which point the wlr_layer_surface_v1 map signal is * raised and the compositor should begin rendering the surface. */ @@ -69,7 +69,7 @@ struct wlr_layer_surface_v1_state { }; struct wlr_layer_surface_v1_configure { - struct wl_list link; // wlr_layer_surface_v1::configure_list + struct wl_list link; // wlr_layer_surface_v1.configure_list uint32_t serial; uint32_t width, height; @@ -80,7 +80,7 @@ struct wlr_layer_surface_v1 { struct wlr_output *output; struct wl_resource *resource; struct wlr_layer_shell_v1 *shell; - struct wl_list popups; // wlr_xdg_popup::link + struct wl_list popups; // wlr_xdg_popup.link char *namespace; @@ -93,9 +93,10 @@ struct wlr_layer_surface_v1 { struct { /** - * The destroy signal indicates that the wlr_layer_surface is about to be - * freed. It is guaranteed that the unmap signal is raised before the destroy - * signal if the layer surface is destroyed while mapped. + * The destroy signal indicates that the struct wlr_layer_surface is + * about to be freed. It is guaranteed that the unmap signal is raised + * before the destroy signal if the layer surface is destroyed while + * mapped. */ struct wl_signal destroy; /** @@ -114,7 +115,8 @@ struct wlr_layer_surface_v1 { struct wl_signal unmap; /** * The new_popup signal is raised when a new popup is created. The data - * parameter passed to the listener is a pointer to the new wlr_xdg_popup. + * parameter passed to the listener is a pointer to the new + * struct wlr_xdg_popup. */ struct wl_signal new_popup; } events; @@ -134,7 +136,7 @@ uint32_t wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface, /** * Notify the client that the surface has been closed and destroy the - * wlr_layer_surface_v1, rendering the resource inert. + * struct wlr_layer_surface_v1, rendering the resource inert. */ void wlr_layer_surface_v1_destroy(struct wlr_layer_surface_v1 *surface); @@ -178,7 +180,8 @@ struct wlr_surface *wlr_layer_surface_v1_popup_surface_at( struct wlr_layer_surface_v1 *surface, double sx, double sy, double *sub_x, double *sub_y); -/** Get the corresponding wlr_layer_surface_v1 from a resource. +/** + * Get the corresponding struct wlr_layer_surface_v1 from a resource. * * Aborts if the resource doesn't have the correct type. */ diff --git a/include/wlr/types/wlr_linux_dmabuf_v1.h b/include/wlr/types/wlr_linux_dmabuf_v1.h index df89a1219..6b5f0d682 100644 --- a/include/wlr/types/wlr_linux_dmabuf_v1.h +++ b/include/wlr/types/wlr_linux_dmabuf_v1.h @@ -35,8 +35,8 @@ struct wlr_dmabuf_v1_buffer { bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource); /** - * Returns the wlr_dmabuf_buffer if the given resource was created - * via the linux-dmabuf buffer protocol + * Returns the struct wlr_dmabuf_buffer if the given resource was created + * via the linux-dmabuf buffer protocol. */ struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource( struct wl_resource *buffer_resource); @@ -72,7 +72,7 @@ struct wlr_linux_dmabuf_v1 { }; /** - * Create linux-dmabuf interface + * Create linux-dmabuf interface. */ struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create(struct wl_display *display, struct wlr_renderer *renderer); diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index f3a02deef..48b6e6f9c 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -108,9 +108,9 @@ struct wlr_output_impl; * The `frame` event will be emitted when it is a good time for the compositor * to submit a new frame. * - * To render a new frame, compositors should call `wlr_output_attach_render`, - * render and call `wlr_output_commit`. No rendering should happen outside a - * `frame` event handler or before `wlr_output_attach_render`. + * To render a new frame, compositors should call wlr_output_attach_render(), + * render and call wlr_output_commit(). No rendering should happen outside a + * `frame` event handler or before wlr_output_attach_render(). */ struct wlr_output { const struct wlr_output_impl *impl; @@ -259,7 +259,7 @@ struct wlr_surface; * emit `frame` events. * * Whether an output is enabled is double-buffered state, see - * `wlr_output_commit`. + * wlr_output_commit(). */ void wlr_output_enable(struct wlr_output *output, bool enable); void wlr_output_create_global(struct wlr_output *output); @@ -268,8 +268,8 @@ void wlr_output_destroy_global(struct wlr_output *output); * Initialize the output's rendering subsystem with the provided allocator and * renderer. Can only be called once. * - * Call this function prior to any call to wlr_output_attach_render, - * wlr_output_commit or wlr_output_cursor_create. + * Call this function prior to any call to wlr_output_attach_render(), + * wlr_output_commit() or wlr_output_cursor_create(). * * The buffer capabilities of the provided must match the capabilities of the * output's backend. Returns false otherwise. @@ -284,7 +284,7 @@ struct wlr_output_mode *wlr_output_preferred_mode(struct wlr_output *output); /** * Sets the output mode. The output needs to be enabled. * - * Mode is double-buffered state, see `wlr_output_commit`. + * Mode is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_mode(struct wlr_output *output, struct wlr_output_mode *mode); @@ -293,14 +293,14 @@ void wlr_output_set_mode(struct wlr_output *output, * Setting `refresh` to zero lets the backend pick a preferred value. The * output needs to be enabled. * - * Custom mode is double-buffered state, see `wlr_output_commit`. + * Custom mode is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_custom_mode(struct wlr_output *output, int32_t width, int32_t height, int32_t refresh); /** * Sets a transform for the output. * - * Transform is double-buffered state, see `wlr_output_commit`. + * Transform is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_transform(struct wlr_output *output, enum wl_output_transform transform); @@ -311,7 +311,7 @@ void wlr_output_set_transform(struct wlr_output *output, * When enabled, compositors can submit frames a little bit later than the * deadline without dropping a frame. * - * Adaptive sync is double-buffered state, see `wlr_output_commit`. + * Adaptive sync is double-buffered state, see wlr_output_commit(). */ void wlr_output_enable_adaptive_sync(struct wlr_output *output, bool enabled); /** @@ -323,17 +323,17 @@ void wlr_output_enable_adaptive_sync(struct wlr_output *output, bool enabled); * hardware and software permit this. * * This only affects the format of the output buffer used when rendering, - * as with `wlr_output_attach_render`. It has no impact on the cursor buffer + * as with wlr_output_attach_render(). It has no impact on the cursor buffer * format, or on the formats supported for direct scan-out (see also - * `wlr_output_attach_buffer`). + * wlr_output_attach_buffer()). * - * This format is double-buffered state, see `wlr_output_commit`. + * This format is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_render_format(struct wlr_output *output, uint32_t format); /** * Sets a scale for the output. * - * Scale is double-buffered state, see `wlr_output_commit`. + * Scale is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_scale(struct wlr_output *output, float scale); void wlr_output_set_subpixel(struct wlr_output *output, @@ -370,22 +370,22 @@ void wlr_output_effective_resolution(struct wlr_output *output, /** * Attach the renderer's buffer to the output. Compositors must call this * function before rendering. After they are done rendering, they should call - * `wlr_output_commit` to submit the new frame. The output needs to be + * wlr_output_commit() to submit the new frame. The output needs to be * enabled. * * If non-NULL, `buffer_age` is set to the drawing buffer age in number of * frames or -1 if unknown. This is useful for damage tracking. * * If the compositor decides not to render after calling this function, it - * must call wlr_output_rollback. + * must call wlr_output_rollback(). */ bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age); /** - * Attach a buffer to the output. Compositors should call `wlr_output_commit` + * Attach a buffer to the output. Compositors should call wlr_output_commit() * to submit the new frame. The output needs to be enabled. * * Not all backends support direct scan-out on all buffers. Compositors can - * check whether a buffer is supported by calling `wlr_output_test`. + * check whether a buffer is supported by calling wlr_output_test(). */ void wlr_output_attach_buffer(struct wlr_output *output, struct wlr_buffer *buffer); @@ -409,14 +409,14 @@ void wlr_output_set_damage(struct wlr_output *output, pixman_region32_t *damage); /** * Test whether the pending output state would be accepted by the backend. If - * this function returns true, `wlr_output_commit` can only fail due to a + * this function returns true, wlr_output_commit() can only fail due to a * runtime error. * * This function doesn't mutate the pending state. */ bool wlr_output_test(struct wlr_output *output); /** - * Commit the pending output state. If `wlr_output_attach_render` has been + * Commit the pending output state. If wlr_output_attach_render() has been * called, the pending frame will be submitted for display and a `frame` event * will be scheduled. * @@ -439,11 +439,11 @@ size_t wlr_output_get_gamma_size(struct wlr_output *output); /** * Sets the gamma table for this output. `r`, `g` and `b` are gamma ramps for * red, green and blue. `size` is the length of the ramps and must not exceed - * the value returned by `wlr_output_get_gamma_size`. + * the value returned by wlr_output_get_gamma_size(). * * Providing zero-sized ramps resets the gamma table. * - * The gamma table is double-buffered state, see `wlr_output_commit`. + * The gamma table is double-buffered state, see wlr_output_commit(). */ void wlr_output_set_gamma(struct wlr_output *output, size_t size, const uint16_t *r, const uint16_t *g, const uint16_t *b); diff --git a/include/wlr/types/wlr_output_damage.h b/include/wlr/types/wlr_output_damage.h index ba5c88df1..51a5be8c9 100644 --- a/include/wlr/types/wlr_output_damage.h +++ b/include/wlr/types/wlr_output_damage.h @@ -29,9 +29,9 @@ struct wlr_box; * to submit a new frame. * * To render a new frame, compositors should call - * `wlr_output_damage_attach_render`, render and call `wlr_output_commit`. No + * wlr_output_damage_attach_render(), render and call wlr_output_commit(). No * rendering should happen outside a `frame` event handler or before - * `wlr_output_damage_attach_render`. + * wlr_output_damage_attach_render(). */ struct wlr_output_damage { struct wlr_output *output; @@ -64,7 +64,7 @@ void wlr_output_damage_destroy(struct wlr_output_damage *output_damage); /** * Attach the renderer's buffer to the output. Compositors must call this * function before rendering. After they are done rendering, they should call - * `wlr_output_set_damage` and `wlr_output_commit` to submit the new frame. + * wlr_output_set_damage() and wlr_output_commit() to submit the new frame. * * `needs_frame` will be set to true if a frame should be submitted. `damage` * will be set to the region of the output that needs to be repainted, in diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h index 3cb6e1e2d..c61e1938b 100644 --- a/include/wlr/types/wlr_output_layout.h +++ b/include/wlr/types/wlr_output_layout.h @@ -18,10 +18,10 @@ struct wlr_box; /** * Helper to arrange outputs in a 2D coordinate space. The output effective - * resolution is used, see wlr_output_effective_resolution. + * resolution is used, see wlr_output_effective_resolution(). * * Outputs added to the output layout are automatically exposed to clients (see - * wlr_output_create_global). They are no longer exposed when removed from the + * wlr_output_create_global()). They are no longer exposed when removed from the * layout. */ struct wlr_output_layout { @@ -115,7 +115,7 @@ void wlr_output_layout_get_box(struct wlr_output_layout *layout, * sensible location in the layout. The coordinates of the output in the layout * may adjust dynamically when the layout changes. If the output is already in * the layout, it will become auto configured. If the position of the output is -* set such as with `wlr_output_layout_move()`, the output will become manually +* set such as with wlr_output_layout_move(), the output will become manually * configured. */ void wlr_output_layout_add_auto(struct wlr_output_layout *layout, diff --git a/include/wlr/types/wlr_output_management_v1.h b/include/wlr/types/wlr_output_management_v1.h index c0551ac1e..0b8d8c207 100644 --- a/include/wlr/types/wlr_output_management_v1.h +++ b/include/wlr/types/wlr_output_management_v1.h @@ -16,9 +16,9 @@ struct wlr_output_manager_v1 { struct wl_display *display; struct wl_global *global; - struct wl_list resources; // wl_resource_get_link + struct wl_list resources; // wl_resource_get_link() - struct wl_list heads; // wlr_output_head_v1::link + struct wl_list heads; // wlr_output_head_v1.link uint32_t serial; bool current_configuration_dirty; @@ -33,8 +33,8 @@ struct wlr_output_manager_v1 { * event data). That is, the compositor is responsible for destroying * the configuration. */ - struct wl_signal apply; // wlr_output_configuration_v1 - struct wl_signal test; // wlr_output_configuration_v1 + struct wl_signal apply; // struct wlr_output_configuration_v1 + struct wl_signal test; // struct wlr_output_configuration_v1 struct wl_signal destroy; } events; @@ -61,16 +61,16 @@ struct wlr_output_head_v1_state { struct wlr_output_head_v1 { struct wlr_output_head_v1_state state; struct wlr_output_manager_v1 *manager; - struct wl_list link; // wlr_output_manager_v1::heads + struct wl_list link; // wlr_output_manager_v1.heads - struct wl_list resources; // wl_resource_get_link - struct wl_list mode_resources; // wl_resource_get_link + struct wl_list resources; // wl_resource_get_link() + struct wl_list mode_resources; // wl_resource_get_link() struct wl_listener output_destroy; }; struct wlr_output_configuration_v1 { - struct wl_list heads; // wlr_output_configuration_head_v1::link + struct wl_list heads; // wlr_output_configuration_head_v1.link // client state struct wlr_output_manager_v1 *manager; @@ -83,7 +83,7 @@ struct wlr_output_configuration_v1 { struct wlr_output_configuration_head_v1 { struct wlr_output_head_v1_state state; struct wlr_output_configuration_v1 *config; - struct wl_list link; // wlr_output_configuration_v1::heads + struct wl_list link; // wlr_output_configuration_v1.heads // client state struct wl_resource *resource; // can be NULL if finalized or disabled @@ -93,7 +93,7 @@ struct wlr_output_configuration_head_v1 { /** * Create a new output manager. The compositor is responsible for calling - * `wlr_output_manager_v1_set_configuration` whenever the current output + * wlr_output_manager_v1_set_configuration() whenever the current output * configuration changes. */ struct wlr_output_manager_v1 *wlr_output_manager_v1_create( @@ -111,8 +111,8 @@ void wlr_output_manager_v1_set_configuration( /** * Create a new, empty output configuration. Compositors should add current head - * status with `wlr_output_configuration_head_v1_create`. They can then call - * `wlr_output_manager_v1_set_configuration`. + * status with wlr_output_configuration_head_v1_create(). They can then call + * wlr_output_manager_v1_set_configuration(). */ struct wlr_output_configuration_v1 *wlr_output_configuration_v1_create(void); void wlr_output_configuration_v1_destroy( diff --git a/include/wlr/types/wlr_output_power_management_v1.h b/include/wlr/types/wlr_output_power_management_v1.h index 23ce814a0..688e37a4f 100644 --- a/include/wlr/types/wlr_output_power_management_v1.h +++ b/include/wlr/types/wlr_output_power_management_v1.h @@ -6,12 +6,12 @@ struct wlr_output_power_manager_v1 { struct wl_global *global; - struct wl_list output_powers; // wlr_output_power_v1::link + struct wl_list output_powers; // wlr_output_power_v1.link struct wl_listener display_destroy; struct { - struct wl_signal set_mode; // wlr_output_power_v1_set_mode_event + struct wl_signal set_mode; // struct wlr_output_power_v1_set_mode_event struct wl_signal destroy; } events; @@ -22,7 +22,7 @@ struct wlr_output_power_v1 { struct wl_resource *resource; struct wlr_output *output; struct wlr_output_power_manager_v1 *manager; - struct wl_list link; + struct wl_list link; // wlr_output_power_manager_v1.output_powers struct wl_listener output_destroy_listener; struct wl_listener output_commit_listener; diff --git a/include/wlr/types/wlr_pointer_constraints_v1.h b/include/wlr/types/wlr_pointer_constraints_v1.h index 904387298..21280ff2d 100644 --- a/include/wlr/types/wlr_pointer_constraints_v1.h +++ b/include/wlr/types/wlr_pointer_constraints_v1.h @@ -53,7 +53,7 @@ struct wlr_pointer_constraint_v1 { struct wl_listener surface_destroy; struct wl_listener seat_destroy; - struct wl_list link; // wlr_pointer_constraints_v1::constraints + struct wl_list link; // wlr_pointer_constraints_v1.constraints struct { /** @@ -69,13 +69,13 @@ struct wlr_pointer_constraint_v1 { struct wlr_pointer_constraints_v1 { struct wl_global *global; - struct wl_list constraints; // wlr_pointer_constraint_v1::link + struct wl_list constraints; // wlr_pointer_constraint_v1.link struct { /** * Called when a new pointer constraint is created. * - * data: struct wlr_pointer_constraint_v1 * + * The data pointer is a struct wlr_pointer_constraint_v1. */ struct wl_signal new_constraint; } events; diff --git a/include/wlr/types/wlr_pointer_gestures_v1.h b/include/wlr/types/wlr_pointer_gestures_v1.h index b05b1a30f..5510ce21c 100644 --- a/include/wlr/types/wlr_pointer_gestures_v1.h +++ b/include/wlr/types/wlr_pointer_gestures_v1.h @@ -16,9 +16,9 @@ struct wlr_surface; struct wlr_pointer_gestures_v1 { struct wl_global *global; - struct wl_list swipes; // wl_resource_get_link - struct wl_list pinches; // wl_resource_get_link - struct wl_list holds; // wl_resource_get_link + struct wl_list swipes; // wl_resource_get_link() + struct wl_list pinches; // wl_resource_get_link() + struct wl_list holds; // wl_resource_get_link() struct wl_listener display_destroy; diff --git a/include/wlr/types/wlr_presentation_time.h b/include/wlr/types/wlr_presentation_time.h index b1dc1868a..48bef659a 100644 --- a/include/wlr/types/wlr_presentation_time.h +++ b/include/wlr/types/wlr_presentation_time.h @@ -31,10 +31,10 @@ struct wlr_presentation { }; struct wlr_presentation_feedback { - struct wl_list resources; // wl_resource_get_link + struct wl_list resources; // wl_resource_get_link() - // Only when the wlr_presentation_surface_sampled_on_output helper has been - // called + // Only when the wlr_presentation_surface_sampled_on_output() helper has + // been called. struct wlr_output *output; bool output_committed; uint32_t output_commit_seq; @@ -50,7 +50,7 @@ struct wlr_presentation_event { uint32_t tv_nsec; uint32_t refresh; uint64_t seq; - uint32_t flags; // wp_presentation_feedback_kind + uint32_t flags; // enum wp_presentation_feedback_kind }; struct wlr_backend; @@ -64,8 +64,8 @@ struct wlr_presentation *wlr_presentation_create(struct wl_display *display, * contents (e.g. when rendering the surface's current texture, when * referencing its current buffer, or when directly scanning out its current * buffer). A wlr_presentation_feedback is returned. The compositor should call - * wlr_presentation_feedback_send_presented if this content has been displayed, - * then wlr_presentation_feedback_destroy. + * wlr_presentation_feedback_send_presented() if this content has been displayed, + * then wlr_presentation_feedback_destroy(). * * NULL is returned if the client hasn't requested presentation feedback for * this surface. @@ -79,7 +79,7 @@ void wlr_presentation_feedback_destroy( struct wlr_presentation_feedback *feedback); /** - * Fill a wlr_presentation_event from a wlr_output_event_present. + * Fill a wlr_presentation_event from a struct wlr_output_event_present. */ void wlr_presentation_event_from_output(struct wlr_presentation_event *event, const struct wlr_output_event_present *output_event); @@ -87,9 +87,9 @@ void wlr_presentation_event_from_output(struct wlr_presentation_event *event, /** * Mark the current surface's buffer as sampled on the given output. * - * Instead of calling wlr_presentation_surface_sampled and managing the - * wlr_presentation_feedback itself, the compositor can call this function - * before a wlr_output_commit call to indicate that the surface's current + * Instead of calling wlr_presentation_surface_sampled() and managing the + * struct wlr_presentation_feedback itself, the compositor can call this function + * before a wlr_output_commit() call to indicate that the surface's current * contents will be displayed on the output. */ void wlr_presentation_surface_sampled_on_output( diff --git a/include/wlr/types/wlr_primary_selection_v1.h b/include/wlr/types/wlr_primary_selection_v1.h index 7434d8317..78b542a04 100644 --- a/include/wlr/types/wlr_primary_selection_v1.h +++ b/include/wlr/types/wlr_primary_selection_v1.h @@ -14,7 +14,7 @@ struct wlr_primary_selection_v1_device_manager { struct wl_global *global; - struct wl_list devices; // wlr_primary_selection_v1_device::link + struct wl_list devices; // wlr_primary_selection_v1_device.link struct wl_listener display_destroy; @@ -31,10 +31,10 @@ struct wlr_primary_selection_v1_device_manager { struct wlr_primary_selection_v1_device { struct wlr_primary_selection_v1_device_manager *manager; struct wlr_seat *seat; - struct wl_list link; // wlr_primary_selection_v1_device_manager::devices - struct wl_list resources; // wl_resource_get_link + struct wl_list link; // wlr_primary_selection_v1_device_manager.devices + struct wl_list resources; // wl_resource_get_link() - struct wl_list offers; // wl_resource_get_link + struct wl_list offers; // wl_resource_get_link() struct wl_listener seat_destroy; struct wl_listener seat_focus_change; diff --git a/include/wlr/types/wlr_relative_pointer_v1.h b/include/wlr/types/wlr_relative_pointer_v1.h index 59dd98d62..fcd44d529 100644 --- a/include/wlr/types/wlr_relative_pointer_v1.h +++ b/include/wlr/types/wlr_relative_pointer_v1.h @@ -23,11 +23,11 @@ */ struct wlr_relative_pointer_manager_v1 { struct wl_global *global; - struct wl_list relative_pointers; // wlr_relative_pointer_v1::link + struct wl_list relative_pointers; // wlr_relative_pointer_v1.link struct { struct wl_signal destroy; - struct wl_signal new_relative_pointer; // wlr_relative_pointer_v1 + struct wl_signal new_relative_pointer; // struct wlr_relative_pointer_v1 } events; struct wl_listener display_destroy_listener; @@ -45,7 +45,7 @@ struct wlr_relative_pointer_v1 { struct wl_resource *resource; struct wl_resource *pointer_resource; struct wlr_seat *seat; - struct wl_list link; // wlr_relative_pointer_manager_v1::relative_pointers + struct wl_list link; // wlr_relative_pointer_manager_v1.relative_pointers struct { struct wl_signal destroy; diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 0802014ed..0e3857d5b 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -258,7 +258,7 @@ struct wlr_scene *wlr_scene_create(void); * Handle presentation feedback for all surfaces in the scene, assuming that * scene outputs and the scene rendering functions are used. * - * Asserts that a wlr_presentation hasn't already been set for the scene. + * Asserts that a struct wlr_presentation hasn't already been set for the scene. */ void wlr_scene_set_presentation(struct wlr_scene *scene, struct wlr_presentation *presentation); @@ -273,7 +273,7 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent); * * The child sub-surfaces are ignored. * - * wlr_surface_send_enter()/wlr_surface_send_leave() will be called + * wlr_surface_send_enter() and wlr_surface_send_leave() will be called * automatically based on the position of the surface and outputs in * the scene. */ @@ -283,7 +283,7 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node); /** - * If this buffer is backed by a surface, then the wlr_scene_surface is + * If this buffer is backed by a surface, then the struct wlr_scene_surface is * returned. If not, NULL will be returned. */ struct wlr_scene_surface *wlr_scene_surface_from_buffer( @@ -383,7 +383,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, bool wlr_scene_output_commit(struct wlr_scene_output *scene_output); /** * Call wlr_surface_send_frame_done() on all surfaces in the scene rendered by - * wlr_scene_output_commit() for which wlr_scene_surface->primary_output + * wlr_scene_output_commit() for which wlr_scene_surface.primary_output * matches the given scene_output. */ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, @@ -396,7 +396,7 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, wlr_scene_buffer_iterator_func_t iterator, void *user_data); /** - * Get a scene-graph output from a wlr_output. + * Get a scene-graph output from a struct wlr_output. * * If the output hasn't been added to the scene-graph, returns NULL. */ diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h index 9947b0156..50e398e7e 100644 --- a/include/wlr/types/wlr_screencopy_v1.h +++ b/include/wlr/types/wlr_screencopy_v1.h @@ -15,7 +15,7 @@ struct wlr_screencopy_manager_v1 { struct wl_global *global; - struct wl_list frames; // wlr_screencopy_frame_v1::link + struct wl_list frames; // wlr_screencopy_frame_v1.link struct wl_listener display_destroy; @@ -35,7 +35,7 @@ struct wlr_screencopy_v1_client { struct wlr_screencopy_frame_v1 { struct wl_resource *resource; struct wlr_screencopy_v1_client *client; - struct wl_list link; + struct wl_list link; // wlr_screencopy_manager_v1.frames enum wl_shm_format format; uint32_t fourcc; diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 1946873ae..8c1d46613 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -32,7 +32,7 @@ struct wlr_serial_ringset { /** * Contains state for a single client's bound wl_seat resource and can be used * to issue input events to that client. The lifetime of these objects is - * managed by wlr_seat; some may be NULL. + * managed by struct wlr_seat; some may be NULL. */ struct wlr_seat_client { struct wl_client *client; @@ -127,7 +127,7 @@ struct wlr_touch_grab_interface { }; /** - * Passed to `wlr_seat_touch_start_grab()` to start a grab of the touch device. + * Passed to wlr_seat_touch_start_grab() to start a grab of the touch device. * The grabber is responsible for handling touch events for the seat. */ struct wlr_seat_touch_grab { @@ -137,7 +137,7 @@ struct wlr_seat_touch_grab { }; /** - * Passed to `wlr_seat_keyboard_start_grab()` to start a grab of the keyboard. + * Passed to wlr_seat_keyboard_start_grab() to start a grab of the keyboard. * The grabber is responsible for handling keyboard events for the seat. */ struct wlr_seat_keyboard_grab { @@ -147,7 +147,7 @@ struct wlr_seat_keyboard_grab { }; /** - * Passed to `wlr_seat_pointer_start_grab()` to start a grab of the pointer. The + * Passed to wlr_seat_pointer_start_grab() to start a grab of the pointer. The * grabber is responsible for handling pointer events for the seat. */ struct wlr_seat_pointer_grab { @@ -179,7 +179,7 @@ struct wlr_seat_pointer_state { struct wl_listener surface_destroy; struct { - struct wl_signal focus_change; // wlr_seat_pointer_focus_change_event + struct wl_signal focus_change; // struct wlr_seat_pointer_focus_change_event } events; }; @@ -201,13 +201,13 @@ struct wlr_seat_keyboard_state { struct wlr_seat_keyboard_grab *default_grab; struct { - struct wl_signal focus_change; // wlr_seat_keyboard_focus_change_event + struct wl_signal focus_change; // struct wlr_seat_keyboard_focus_change_event } events; }; struct wlr_seat_touch_state { struct wlr_seat *seat; - struct wl_list touch_points; // wlr_touch_point::link + struct wl_list touch_points; // wlr_touch_point.link uint32_t grab_serial; uint32_t grab_id; @@ -230,7 +230,7 @@ struct wlr_seat { struct wlr_data_source *selection_source; uint32_t selection_serial; - struct wl_list selection_offers; // wlr_data_offer::link + struct wl_list selection_offers; // wlr_data_offer.link struct wlr_primary_selection_source *primary_selection_source; uint32_t primary_selection_serial; @@ -239,7 +239,7 @@ struct wlr_seat { struct wlr_drag *drag; struct wlr_data_source *drag_source; uint32_t drag_serial; - struct wl_list drag_offers; // wlr_data_offer::link + struct wl_list drag_offers; // wlr_data_offer.link struct wlr_seat_pointer_state pointer_state; struct wlr_seat_keyboard_state keyboard_state; @@ -260,26 +260,26 @@ struct wlr_seat { struct wl_signal touch_grab_begin; struct wl_signal touch_grab_end; - // wlr_seat_pointer_request_set_cursor_event + // struct wlr_seat_pointer_request_set_cursor_event struct wl_signal request_set_cursor; // Called when an application _wants_ to set the selection (user copies some data). - // Compositors should listen to this event and call wlr_seat_set_selection + // Compositors should listen to this event and call wlr_seat_set_selection() // if they want to accept the client's request. - struct wl_signal request_set_selection; // wlr_seat_request_set_selection_event + struct wl_signal request_set_selection; // struct wlr_seat_request_set_selection_event // Called after the data source is set for the selection. struct wl_signal set_selection; // Called when an application _wants_ to set the primary selection (user selects some data). - // Compositors should listen to this event and call wlr_seat_set_primary_selection + // Compositors should listen to this event and call wlr_seat_set_primary_selection() // if they want to accept the client's request. - struct wl_signal request_set_primary_selection; // wlr_seat_request_set_primary_selection_event + struct wl_signal request_set_primary_selection; // struct wlr_seat_request_set_primary_selection_event // Called after the primary selection source object is set. struct wl_signal set_primary_selection; - // wlr_seat_request_start_drag_event + // struct wlr_seat_request_start_drag_event struct wl_signal request_start_drag; - struct wl_signal start_drag; // wlr_drag + struct wl_signal start_drag; // struct wlr_drag struct wl_signal destroy; } events; @@ -322,16 +322,16 @@ struct wlr_seat_keyboard_focus_change_event { }; /** - * Allocates a new wlr_seat and adds a wl_seat global to the display. + * Allocates a new struct wlr_seat and adds a wl_seat global to the display. */ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name); /** - * Destroys a wlr_seat, removes its wl_seat global and clears focus for all + * Destroys a seat, removes its wl_seat global and clears focus for all * devices belonging to the seat. */ void wlr_seat_destroy(struct wlr_seat *wlr_seat); /** - * Gets a wlr_seat_client for the specified client, or returns NULL if no + * Gets a struct wlr_seat_client for the specified client, or returns NULL if no * client is bound for that client. */ struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat, @@ -359,7 +359,7 @@ bool wlr_seat_pointer_surface_has_focus(struct wlr_seat *wlr_seat, * focused surface for the pointer. This will send a leave event to the last * surface that was entered. Coordinates for the enter event are surface-local. * This function does not respect pointer grabs: you probably want - * `wlr_seat_pointer_notify_enter()` instead. + * wlr_seat_pointer_notify_enter() instead. */ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat, struct wlr_surface *surface, double sx, double sy); @@ -367,14 +367,14 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat, /** * Clear the focused surface for the pointer and leave all entered surfaces. * This function does not respect pointer grabs: you probably want - * `wlr_seat_pointer_notify_clear_focus()` instead. + * wlr_seat_pointer_notify_clear_focus() instead. */ void wlr_seat_pointer_clear_focus(struct wlr_seat *wlr_seat); /** * Send a motion event to the surface with pointer focus. Coordinates for the * motion event are surface-local. This function does not respect pointer grabs: - * you probably want `wlr_seat_pointer_notify_motion()` instead. + * you probably want wlr_seat_pointer_notify_motion() instead. */ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time_msec, double sx, double sy); @@ -382,7 +382,7 @@ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time_msec, /** * Send a button event to the surface with pointer focus. Coordinates for the * button event are surface-local. Returns the serial. This function does not - * respect pointer grabs: you probably want `wlr_seat_pointer_notify_button()` + * respect pointer grabs: you probably want wlr_seat_pointer_notify_button() * instead. */ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, @@ -390,7 +390,7 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, /** * Send an axis event to the surface with pointer focus. This function does not - * respect pointer grabs: you probably want `wlr_seat_pointer_notify_axis()` + * respect pointer grabs: you probably want wlr_seat_pointer_notify_axis() * instead. */ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time_msec, @@ -399,7 +399,7 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time_msec, /** * Send a frame event to the surface with pointer focus. This function does not - * respect pointer grabs: you probably want `wlr_seat_pointer_notify_frame()` + * respect pointer grabs: you probably want wlr_seat_pointer_notify_frame() * instead. */ void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat); @@ -485,7 +485,7 @@ struct wlr_keyboard *wlr_seat_get_keyboard(struct wlr_seat *seat); /** * Send the keyboard key to focused keyboard resources. This function does not - * respect keyboard grabs: you probably want `wlr_seat_keyboard_notify_key()` + * respect keyboard grabs: you probably want wlr_seat_keyboard_notify_key() * instead. */ void wlr_seat_keyboard_send_key(struct wlr_seat *seat, uint32_t time_msec, @@ -494,7 +494,7 @@ void wlr_seat_keyboard_send_key(struct wlr_seat *seat, uint32_t time_msec, /** * Send the modifier state to focused keyboard resources. This function does * not respect keyboard grabs: you probably want - * `wlr_seat_keyboard_notify_modifiers()` instead. + * wlr_seat_keyboard_notify_modifiers() instead. */ void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat, struct wlr_keyboard_modifiers *modifiers); @@ -503,7 +503,7 @@ void wlr_seat_keyboard_send_modifiers(struct wlr_seat *seat, * Send a keyboard enter event to the given surface and consider it to be the * focused surface for the keyboard. This will send a leave event to the last * surface that was entered. This function does not respect keyboard grabs: you - * probably want `wlr_seat_keyboard_notify_enter()` instead. + * probably want wlr_seat_keyboard_notify_enter() instead. */ void wlr_seat_keyboard_enter(struct wlr_seat *seat, struct wlr_surface *surface, uint32_t keycodes[], size_t num_keycodes, @@ -512,7 +512,7 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat, /** * Clear the focused surface for the keyboard and leave all entered surfaces. * This function does not respect keyboard grabs: you probably want - * `wlr_seat_keyboard_notify_clear_focus()` instead. + * wlr_seat_keyboard_notify_clear_focus() instead. */ void wlr_seat_keyboard_clear_focus(struct wlr_seat *wlr_seat); @@ -573,7 +573,7 @@ struct wlr_touch_point *wlr_seat_touch_get_point(struct wlr_seat *seat, /** * Notify the seat that the touch point given by `touch_id` has entered a new * surface. The surface is required. To clear focus, use - * `wlr_seat_touch_point_clear_focus()`. + * wlr_seat_touch_point_clear_focus(). */ void wlr_seat_touch_point_focus(struct wlr_seat *seat, struct wlr_surface *surface, uint32_t time_msec, @@ -591,7 +591,7 @@ void wlr_seat_touch_point_clear_focus(struct wlr_seat *seat, uint32_t time_msec, * this will add a new touch point with the given `touch_id`. The touch down may * not be valid if the surface seat client does not accept touch input. * Coordinates are surface-local. This function does not respect touch grabs: - * you probably want `wlr_seat_touch_notify_down()` instead. + * you probably want wlr_seat_touch_notify_down() instead. */ uint32_t wlr_seat_touch_send_down(struct wlr_seat *seat, struct wlr_surface *surface, uint32_t time_msec, @@ -601,7 +601,7 @@ uint32_t wlr_seat_touch_send_down(struct wlr_seat *seat, * Send a touch up event for the touch point given by the `touch_id`. The event * will go to the client for the surface given in the corresponding touch down * event. This will remove the touch point. This function does not respect touch - * grabs: you probably want `wlr_seat_touch_notify_up()` instead. + * grabs: you probably want wlr_seat_touch_notify_up() instead. */ void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time_msec, int32_t touch_id); @@ -610,7 +610,7 @@ void wlr_seat_touch_send_up(struct wlr_seat *seat, uint32_t time_msec, * Send a touch motion event for the touch point given by the `touch_id`. The * event will go to the client for the surface given in the corresponding touch * down event. This function does not respect touch grabs: you probably want - * `wlr_seat_touch_notify_motion()` instead. + * wlr_seat_touch_notify_motion() instead. */ void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time_msec, int32_t touch_id, double sx, double sy); @@ -619,7 +619,7 @@ void wlr_seat_touch_send_motion(struct wlr_seat *seat, uint32_t time_msec, * Notify the seat that this is a global gesture and the client should cancel * processing it. The event will go to the client for the surface given. * This function does not respect touch grabs: you probably want - * `wlr_seat_touch_notify_cancel()` instead. + * wlr_seat_touch_notify_cancel() instead. */ void wlr_seat_touch_send_cancel(struct wlr_seat *seat, struct wlr_surface *surface); @@ -695,7 +695,7 @@ bool wlr_seat_validate_pointer_grab_serial(struct wlr_seat *seat, /** * Check whether this serial is valid to start a touch grab action. If it's the - * case and point_ptr is non-NULL, *point_ptr is set to the touch point matching + * case and point_ptr is non-NULL, `*point_ptr` is set to the touch point matching * the serial. */ bool wlr_seat_validate_touch_grab_serial(struct wlr_seat *seat, diff --git a/include/wlr/types/wlr_server_decoration.h b/include/wlr/types/wlr_server_decoration.h index 28467a21f..7e78c5f21 100644 --- a/include/wlr/types/wlr_server_decoration.h +++ b/include/wlr/types/wlr_server_decoration.h @@ -44,8 +44,8 @@ enum wlr_server_decoration_manager_mode { */ struct wlr_server_decoration_manager { struct wl_global *global; - struct wl_list resources; // wl_resource_get_link - struct wl_list decorations; // wlr_server_decoration::link + struct wl_list resources; // wl_resource_get_link() + struct wl_list decorations; // wlr_server_decoration.link uint32_t default_mode; // enum wlr_server_decoration_manager_mode diff --git a/include/wlr/types/wlr_session_lock_v1.h b/include/wlr/types/wlr_session_lock_v1.h index b410b9e56..101fe56cc 100644 --- a/include/wlr/types/wlr_session_lock_v1.h +++ b/include/wlr/types/wlr_session_lock_v1.h @@ -31,7 +31,7 @@ struct wlr_session_lock_manager_v1 { struct wlr_session_lock_v1 { struct wl_resource *resource; - struct wl_list surfaces; // struct wlr_session_lock_surface_v1::link + struct wl_list surfaces; // struct wlr_session_lock_surface_v1.link struct { struct wl_signal new_surface; // struct wlr_session_lock_surface_v1 * @@ -48,7 +48,7 @@ struct wlr_session_lock_surface_v1_state { }; struct wlr_session_lock_surface_v1_configure { - struct wl_list link; // wlr_session_lock_surface_v1::configure_list + struct wl_list link; // wlr_session_lock_surface_v1.configure_list uint32_t serial; uint32_t width, height; @@ -56,14 +56,14 @@ struct wlr_session_lock_surface_v1_configure { struct wlr_session_lock_surface_v1 { struct wl_resource *resource; - struct wl_list link; // wlr_session_lock_v1::surfaces + struct wl_list link; // wlr_session_lock_v1.surfaces struct wlr_output *output; struct wlr_surface *surface; bool configured, mapped; - struct wl_list configure_list; // wlr_session_lock_surface_v1_configure::link + struct wl_list configure_list; // wlr_session_lock_surface_v1_configure.link struct wlr_session_lock_surface_v1_state current; struct wlr_session_lock_surface_v1_state pending; diff --git a/include/wlr/types/wlr_tablet_pad.h b/include/wlr/types/wlr_tablet_pad.h index 64420f465..32a3231db 100644 --- a/include/wlr/types/wlr_tablet_pad.h +++ b/include/wlr/types/wlr_tablet_pad.h @@ -30,14 +30,14 @@ struct wlr_tablet_pad { struct wl_signal button; struct wl_signal ring; struct wl_signal strip; - struct wl_signal attach_tablet; //struct wlr_tablet_tool + struct wl_signal attach_tablet; // struct wlr_tablet_tool } events; size_t button_count; size_t ring_count; size_t strip_count; - struct wl_list groups; // wlr_tablet_pad_group::link + struct wl_list groups; // wlr_tablet_pad_group.link struct wl_array paths; // char * void *data; diff --git a/include/wlr/types/wlr_tablet_v2.h b/include/wlr/types/wlr_tablet_v2.h index c05015b2d..548282445 100644 --- a/include/wlr/types/wlr_tablet_v2.h +++ b/include/wlr/types/wlr_tablet_v2.h @@ -41,8 +41,8 @@ struct wlr_tablet_pad_client_v2; struct wlr_tablet_manager_v2 { struct wl_global *wl_global; - struct wl_list clients; // wlr_tablet_manager_client_v2::link - struct wl_list seats; // wlr_tablet_seat_v2::link + struct wl_list clients; // wlr_tablet_manager_client_v2.link + struct wl_list seats; // wlr_tablet_seat_v2.link struct wl_listener display_destroy; @@ -54,10 +54,10 @@ struct wlr_tablet_manager_v2 { }; struct wlr_tablet_v2_tablet { - struct wl_list link; // wlr_tablet_seat_v2::tablets + struct wl_list link; // wlr_tablet_seat_v2.tablets struct wlr_tablet *wlr_tablet; struct wlr_input_device *wlr_device; - struct wl_list clients; // wlr_tablet_client_v2::tablet_link + struct wl_list clients; // wlr_tablet_client_v2.tablet_link struct wl_listener tool_destroy; @@ -65,9 +65,9 @@ struct wlr_tablet_v2_tablet { }; struct wlr_tablet_v2_tablet_tool { - struct wl_list link; // wlr_tablet_seat_v2::tablets + struct wl_list link; // wlr_tablet_seat_v2.tablets struct wlr_tablet_tool *wlr_tool; - struct wl_list clients; // wlr_tablet_tool_client_v2::tool_link + struct wl_list clients; // wlr_tablet_tool_client_v2.tool_link struct wl_listener tool_destroy; @@ -91,10 +91,10 @@ struct wlr_tablet_v2_tablet_tool { }; struct wlr_tablet_v2_tablet_pad { - struct wl_list link; // wlr_tablet_seat_v2::pads + struct wl_list link; // wlr_tablet_seat_v2.pads struct wlr_tablet_pad *wlr_pad; struct wlr_input_device *wlr_device; - struct wl_list clients; // wlr_tablet_pad_client_v2::pad_link + struct wl_list clients; // wlr_tablet_pad_client_v2.pad_link size_t group_count; uint32_t *groups; diff --git a/include/wlr/types/wlr_text_input_v3.h b/include/wlr/types/wlr_text_input_v3.h index 5bac69a65..a3c6c7eba 100644 --- a/include/wlr/types/wlr_text_input_v3.h +++ b/include/wlr/types/wlr_text_input_v3.h @@ -39,7 +39,7 @@ struct wlr_text_input_v3_state { // Tracks which features were used in the current commit. // Useful in the enabling commit, where usage means support. - uint32_t features; // OR'ed wlr_text_input_v3_features + uint32_t features; // bitfield of enum wlr_text_input_v3_features }; struct wlr_text_input_v3 { @@ -52,7 +52,7 @@ struct wlr_text_input_v3 { bool pending_enabled; bool current_enabled; // supported in the current text input, more granular than surface - uint32_t active_features; // OR'ed wlr_text_input_v3_features + uint32_t active_features; // bitfield of enum wlr_text_input_v3_features struct wl_list link; @@ -60,22 +60,22 @@ struct wlr_text_input_v3 { struct wl_listener seat_destroy; struct { - struct wl_signal enable; // (struct wlr_text_input_v3*) - struct wl_signal commit; // (struct wlr_text_input_v3*) - struct wl_signal disable; // (struct wlr_text_input_v3*) - struct wl_signal destroy; // (struct wlr_text_input_v3*) + struct wl_signal enable; // struct wlr_text_input_v3 * + struct wl_signal commit; // struct wlr_text_input_v3 * + struct wl_signal disable; // struct wlr_text_input_v3 * + struct wl_signal destroy; // struct wlr_text_input_v3 * } events; }; struct wlr_text_input_manager_v3 { struct wl_global *global; - struct wl_list text_inputs; // struct wlr_text_input_v3::resource::link + struct wl_list text_inputs; // struct wlr_text_input_v3.resource.link struct wl_listener display_destroy; struct { - struct wl_signal text_input; // (struct wlr_text_input_v3*) - struct wl_signal destroy; // (struct wlr_input_method_manager_v3*) + struct wl_signal text_input; // struct wlr_text_input_v3 * + struct wl_signal destroy; // struct wlr_input_method_manager_v3 * } events; }; diff --git a/include/wlr/types/wlr_viewporter.h b/include/wlr/types/wlr_viewporter.h index f909d9cc1..8a1793675 100644 --- a/include/wlr/types/wlr_viewporter.h +++ b/include/wlr/types/wlr_viewporter.h @@ -18,9 +18,9 @@ * * - The size of the surface texture may not match the surface size anymore. * Compositors must use the surface size only. - * - Compositors must call wlr_render_subtexture_with_matrix when rendering a + * - Compositors must call wlr_render_subtexture_with_matrix() when rendering a * surface texture with the source box returned by - * wlr_surface_get_buffer_source_box. + * wlr_surface_get_buffer_source_box(). */ struct wlr_viewporter { struct wl_global *global; diff --git a/include/wlr/types/wlr_virtual_keyboard_v1.h b/include/wlr/types/wlr_virtual_keyboard_v1.h index 8350f4134..00200c44f 100644 --- a/include/wlr/types/wlr_virtual_keyboard_v1.h +++ b/include/wlr/types/wlr_virtual_keyboard_v1.h @@ -14,12 +14,12 @@ struct wlr_virtual_keyboard_manager_v1 { struct wl_global *global; - struct wl_list virtual_keyboards; // struct wlr_virtual_keyboard_v1* + struct wl_list virtual_keyboards; // wlr_virtual_keyboard_v1.link struct wl_listener display_destroy; struct { - struct wl_signal new_virtual_keyboard; // struct wlr_virtual_keyboard_v1* + struct wl_signal new_virtual_keyboard; // struct wlr_virtual_keyboard_v1 * struct wl_signal destroy; } events; }; @@ -30,7 +30,7 @@ struct wlr_virtual_keyboard_v1 { struct wlr_seat *seat; bool has_keymap; - struct wl_list link; + struct wl_list link; // wlr_virtual_keyboard_manager_v1.virtual_keyboards }; struct wlr_virtual_keyboard_manager_v1* wlr_virtual_keyboard_manager_v1_create( diff --git a/include/wlr/types/wlr_virtual_pointer_v1.h b/include/wlr/types/wlr_virtual_pointer_v1.h index 954103e1a..d00f2758b 100644 --- a/include/wlr/types/wlr_virtual_pointer_v1.h +++ b/include/wlr/types/wlr_virtual_pointer_v1.h @@ -16,12 +16,12 @@ struct wlr_virtual_pointer_manager_v1 { struct wl_global *global; - struct wl_list virtual_pointers; // struct wlr_virtual_pointer_v1* + struct wl_list virtual_pointers; // wlr_virtual_pointer_v1.link struct wl_listener display_destroy; struct { - struct wl_signal new_virtual_pointer; // struct wlr_virtual_pointer_v1_new_pointer_event* + struct wl_signal new_virtual_pointer; // struct wlr_virtual_pointer_v1_new_pointer_event * struct wl_signal destroy; } events; }; @@ -34,7 +34,7 @@ struct wlr_virtual_pointer_v1 { enum wl_pointer_axis axis; bool axis_valid[2]; - struct wl_list link; + struct wl_list link; // wlr_virtual_pointer_manager_v1.virtual_pointers }; struct wlr_virtual_pointer_v1_new_pointer_event { diff --git a/include/wlr/types/wlr_xcursor_manager.h b/include/wlr/types/wlr_xcursor_manager.h index a95302143..f7781ca6a 100644 --- a/include/wlr/types/wlr_xcursor_manager.h +++ b/include/wlr/types/wlr_xcursor_manager.h @@ -23,9 +23,9 @@ struct wlr_xcursor_manager_theme { }; /** - * wlr_xcursor_manager dynamically loads xcursor themes at sizes necessary for - * use on outputs at arbitrary scale factors. You should call - * wlr_xcursor_manager_load for each output you will show your cursor on, with + * struct wlr_xcursor_manager dynamically loads xcursor themes at sizes necessary + * for use on outputs at arbitrary scale factors. You should call + * wlr_xcursor_manager_load() for each output you will show your cursor on, with * the scale factor parameter set to that output's scale factor. */ struct wlr_xcursor_manager { @@ -51,17 +51,17 @@ bool wlr_xcursor_manager_load(struct wlr_xcursor_manager *manager, /** * Retrieves a wlr_xcursor reference for the given cursor name at the given - * scale factor, or NULL if this wlr_xcursor_manager has not loaded a cursor - * theme at the requested scale. + * scale factor, or NULL if this struct wlr_xcursor_manager has not loaded a + * cursor theme at the requested scale. */ struct wlr_xcursor *wlr_xcursor_manager_get_xcursor( struct wlr_xcursor_manager *manager, const char *name, float scale); /** - * Set a wlr_cursor's cursor image to the specified cursor name for all scale - * factors. wlr_cursor will take over from this point and ensure the correct - * cursor is used on each output, assuming a wlr_output_layout is attached to - * it. + * Set a struct wlr_cursor's cursor image to the specified cursor name for all + * scale factors. struct wlr_cursor will take over from this point and ensure + * the correct cursor is used on each output, assuming a + * struct wlr_output_layout is attached to it. */ void wlr_xcursor_manager_set_cursor_image(struct wlr_xcursor_manager *manager, const char *name, struct wlr_cursor *cursor); diff --git a/include/wlr/types/wlr_xdg_activation_v1.h b/include/wlr/types/wlr_xdg_activation_v1.h index 97801af2a..f36be4648 100644 --- a/include/wlr/types/wlr_xdg_activation_v1.h +++ b/include/wlr/types/wlr_xdg_activation_v1.h @@ -45,7 +45,7 @@ struct wlr_xdg_activation_v1 { struct { struct wl_signal destroy; - struct wl_signal request_activate; // wlr_xdg_activation_v1_request_activate_event + struct wl_signal request_activate; // struct wlr_xdg_activation_v1_request_activate_event } events; // private state diff --git a/include/wlr/types/wlr_xdg_decoration_v1.h b/include/wlr/types/wlr_xdg_decoration_v1.h index b36515595..138eb0208 100644 --- a/include/wlr/types/wlr_xdg_decoration_v1.h +++ b/include/wlr/types/wlr_xdg_decoration_v1.h @@ -12,7 +12,7 @@ enum wlr_xdg_toplevel_decoration_v1_mode { struct wlr_xdg_decoration_manager_v1 { struct wl_global *global; - struct wl_list decorations; // wlr_xdg_toplevel_decoration::link + struct wl_list decorations; // wlr_xdg_toplevel_decoration.link struct wl_listener display_destroy; @@ -25,7 +25,7 @@ struct wlr_xdg_decoration_manager_v1 { }; struct wlr_xdg_toplevel_decoration_v1_configure { - struct wl_list link; // wlr_xdg_toplevel_decoration::configure_list + struct wl_list link; // wlr_xdg_toplevel_decoration.configure_list struct wlr_xdg_surface_configure *surface_configure; enum wlr_xdg_toplevel_decoration_v1_mode mode; }; @@ -38,7 +38,7 @@ struct wlr_xdg_toplevel_decoration_v1 { struct wl_resource *resource; struct wlr_xdg_surface *surface; struct wlr_xdg_decoration_manager_v1 *manager; - struct wl_list link; // wlr_xdg_decoration_manager_v1::link + struct wl_list link; // wlr_xdg_decoration_manager_v1.link struct wlr_xdg_toplevel_decoration_v1_state current, pending; @@ -47,7 +47,7 @@ struct wlr_xdg_toplevel_decoration_v1 { bool added; - struct wl_list configure_list; // wlr_xdg_toplevel_decoration_v1_configure::link + struct wl_list configure_list; // wlr_xdg_toplevel_decoration_v1_configure.link struct { struct wl_signal destroy; diff --git a/include/wlr/types/wlr_xdg_foreign_registry.h b/include/wlr/types/wlr_xdg_foreign_registry.h index 462a9a86e..54c91e4d7 100644 --- a/include/wlr/types/wlr_xdg_foreign_registry.h +++ b/include/wlr/types/wlr_xdg_foreign_registry.h @@ -14,8 +14,8 @@ #define WLR_XDG_FOREIGN_HANDLE_SIZE 37 /** - * wlr_xdg_foreign_registry is used for storing a list of exported surfaces with - * the xdg-foreign family of protocols. + * struct wlr_xdg_foreign_registry is used for storing a list of exported + * surfaces with the xdg-foreign family of protocols. * * It can be used to allow interoperability between clients using different * versions of the protocol (if all versions use the same registry). @@ -30,7 +30,7 @@ struct wlr_xdg_foreign_registry { }; struct wlr_xdg_foreign_exported { - struct wl_list link; // wlr_xdg_foreign_registry::exported_surfaces + struct wl_list link; // wlr_xdg_foreign_registry.exported_surfaces struct wlr_xdg_foreign_registry *registry; struct wlr_surface *surface; @@ -43,7 +43,7 @@ struct wlr_xdg_foreign_exported { }; /** - * Create an empty wlr_xdg_foreign_registry. + * Create an empty struct wlr_xdg_foreign_registry. * * It will be destroyed when the associated display is destroyed. */ diff --git a/include/wlr/types/wlr_xdg_foreign_v1.h b/include/wlr/types/wlr_xdg_foreign_v1.h index bebbb8ae6..25bc1181c 100644 --- a/include/wlr/types/wlr_xdg_foreign_v1.h +++ b/include/wlr/types/wlr_xdg_foreign_v1.h @@ -15,7 +15,7 @@ struct wlr_xdg_foreign_v1 { struct { struct wl_global *global; - struct wl_list objects; // wlr_xdg_exported_v1::link or wlr_xdg_imported_v1::link + struct wl_list objects; // wlr_xdg_exported_v1.link or wlr_xdg_imported_v1.link } exporter, importer; struct wl_listener foreign_registry_destroy; @@ -36,7 +36,7 @@ struct wlr_xdg_exported_v1 { struct wl_resource *resource; struct wl_listener xdg_surface_unmap; - struct wl_list link; // wlr_xdg_foreign_v1::exporter::objects + struct wl_list link; // wlr_xdg_foreign_v1.exporter.objects }; struct wlr_xdg_imported_v1 { @@ -44,7 +44,7 @@ struct wlr_xdg_imported_v1 { struct wl_listener exported_destroyed; struct wl_resource *resource; - struct wl_list link; // wlr_xdg_foreign_v1::importer::objects + struct wl_list link; // wlr_xdg_foreign_v1.importer.objects struct wl_list children; }; @@ -52,7 +52,7 @@ struct wlr_xdg_imported_child_v1 { struct wlr_xdg_imported_v1 *imported; struct wlr_surface *surface; - struct wl_list link; // wlr_xdg_imported_v1::children + struct wl_list link; // wlr_xdg_imported_v1.children struct wl_listener xdg_surface_unmap; struct wl_listener xdg_toplevel_set_parent; diff --git a/include/wlr/types/wlr_xdg_foreign_v2.h b/include/wlr/types/wlr_xdg_foreign_v2.h index 23c8247b7..78659e97a 100644 --- a/include/wlr/types/wlr_xdg_foreign_v2.h +++ b/include/wlr/types/wlr_xdg_foreign_v2.h @@ -15,7 +15,7 @@ struct wlr_xdg_foreign_v2 { struct { struct wl_global *global; - struct wl_list objects; // wlr_xdg_exported_v2::link or wlr_xdg_imported_v2::link + struct wl_list objects; // wlr_xdg_exported_v2.link or wlr_xdg_imported_v2.link } exporter, importer; struct wl_listener foreign_registry_destroy; @@ -36,7 +36,7 @@ struct wlr_xdg_exported_v2 { struct wl_resource *resource; struct wl_listener xdg_surface_unmap; - struct wl_list link; // wlr_xdg_foreign_v2::exporter::objects + struct wl_list link; // wlr_xdg_foreign_v2.exporter.objects }; struct wlr_xdg_imported_v2 { @@ -44,7 +44,7 @@ struct wlr_xdg_imported_v2 { struct wl_listener exported_destroyed; struct wl_resource *resource; - struct wl_list link; // wlr_xdg_foreign_v2::importer::objects + struct wl_list link; // wlr_xdg_foreign_v2.importer.objects struct wl_list children; }; @@ -52,7 +52,7 @@ struct wlr_xdg_imported_child_v2 { struct wlr_xdg_imported_v2 *imported; struct wlr_surface *surface; - struct wl_list link; // wlr_xdg_imported_v2::children + struct wl_list link; // wlr_xdg_imported_v2.children struct wl_listener xdg_surface_unmap; struct wl_listener xdg_toplevel_set_parent; diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index e61683171..51ba05845 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -44,7 +44,7 @@ struct wlr_xdg_client { struct wl_client *client; struct wl_list surfaces; - struct wl_list link; // wlr_xdg_shell::clients + struct wl_list link; // wlr_xdg_shell.clients uint32_t ping_serial; struct wl_event_source *ping_timer; @@ -85,7 +85,7 @@ struct wlr_xdg_popup { struct wlr_xdg_positioner_rules positioner_rules; - struct wl_list grab_link; // wlr_xdg_popup_grab::popups + struct wl_list grab_link; // wlr_xdg_popup_grab.popups }; // each seat gets a popup grab @@ -96,7 +96,7 @@ struct wlr_xdg_popup_grab { struct wlr_seat_touch_grab touch_grab; struct wlr_seat *seat; struct wl_list popups; - struct wl_list link; // wlr_xdg_shell::popup_grabs + struct wl_list link; // wlr_xdg_shell.popup_grabs struct wl_listener seat_destroy; }; @@ -141,7 +141,7 @@ struct wlr_xdg_toplevel { // Properties that the client has requested. Intended to be checked // by the compositor on surface map and state change requests (such as - // xdg_toplevel::set_fullscreen) and handled accordingly. + // xdg_toplevel.set_fullscreen) and handled accordingly. struct wlr_xdg_toplevel_requested requested; char *title; @@ -170,7 +170,7 @@ struct wlr_xdg_toplevel { struct wlr_xdg_surface_configure { struct wlr_xdg_surface *surface; - struct wl_list link; // wlr_xdg_surface::configure_list + struct wl_list link; // wlr_xdg_surface.configure_list uint32_t serial; struct wlr_xdg_toplevel_configure *toplevel_configure; @@ -195,7 +195,7 @@ struct wlr_xdg_surface { struct wlr_xdg_client *client; struct wl_resource *resource; struct wlr_surface *surface; - struct wl_list link; // wlr_xdg_client::surfaces + struct wl_list link; // wlr_xdg_client.surfaces enum wlr_xdg_surface_role role; union { @@ -203,7 +203,7 @@ struct wlr_xdg_surface { struct wlr_xdg_popup *popup; }; - struct wl_list popups; // wlr_xdg_popup::link + struct wl_list popups; // wlr_xdg_popup.link bool added, configured, mapped; struct wl_event_source *configure_idle; @@ -237,8 +237,8 @@ struct wlr_xdg_surface { struct wl_signal unmap; // for protocol extensions - struct wl_signal configure; // wlr_xdg_surface_configure - struct wl_signal ack_configure; // wlr_xdg_surface_configure + struct wl_signal configure; // struct wlr_xdg_surface_configure + struct wl_signal ack_configure; // struct wlr_xdg_surface_configure } events; void *data; @@ -270,7 +270,7 @@ struct wlr_xdg_toplevel_show_window_menu_event { struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display, uint32_t version); -/** Get the corresponding wlr_xdg_surface from a resource. +/** Get the corresponding struct wlr_xdg_surface from a resource. * * Aborts if the resource doesn't have the correct type. Returns NULL if the * resource is inert. @@ -278,7 +278,7 @@ struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display, struct wlr_xdg_surface *wlr_xdg_surface_from_resource( struct wl_resource *resource); -/** Get the corresponding wlr_xdg_popup from a resource. +/** Get the corresponding struct wlr_xdg_popup from a resource. * * Aborts if the resource doesn't have the correct type. Returns NULL if the * resource is inert. @@ -286,7 +286,7 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_resource( struct wlr_xdg_popup *wlr_xdg_popup_from_resource( struct wl_resource *resource); -/** Get the corresponding wlr_xdg_toplevel from a resource. +/** Get the corresponding struct wlr_xdg_toplevel from a resource. * * Aborts if the resource doesn't have the correct type. Returns NULL if the * resource is inert. @@ -294,7 +294,7 @@ struct wlr_xdg_popup *wlr_xdg_popup_from_resource( struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource( struct wl_resource *resource); -/** Get the corresponding wlr_xdg_positioner from a resource. +/** Get the corresponding struct wlr_xdg_positioner from a resource. * * Aborts if the resource doesn't have the correct type. */ @@ -345,7 +345,7 @@ uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_toplevel *toplevel, /** * Request that this toplevel consider itself in a tiled layout and some * edges are adjacent to another part of the tiling grid. `tiled_edges` is a - * bitfield of `enum wlr_edges`. Returns the associated configure serial. + * bitfield of enum wlr_edges. Returns the associated configure serial. */ uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, uint32_t tiled_edges); @@ -425,10 +425,11 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface( /** * Get the surface geometry. + * * This is either the geometry as set by the client, or defaulted to the bounds * of the surface + the subsurfaces (as specified by the protocol). * - * The x and y value can be <0 + * The x and y value can be < 0. */ void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface, struct wlr_box *box); diff --git a/include/wlr/util/box.h b/include/wlr/util/box.h index 66cfa21c6..8516688d1 100644 --- a/include/wlr/util/box.h +++ b/include/wlr/util/box.h @@ -23,7 +23,7 @@ * * The x and y coordinates are inclusive, and the width and height lengths are * exclusive. In other words, the box starts from the coordinates (x, y), and - * goes up to but not including (x + width, y + height) + * goes up to but not including (x + width, y + height). */ struct wlr_box { int x, y; @@ -33,7 +33,7 @@ struct wlr_box { /** * A floating-point box representing a rectangle region in a 2D space. * - * wlr_fbox has the same semantics as wlr_box + * struct wlr_fbox has the same semantics as struct wlr_box. */ struct wlr_fbox { double x, y; @@ -41,34 +41,35 @@ struct wlr_fbox { }; /** - * Finds the closest point within the box bounds + * Finds the closest point within the box bounds. * - * Returns NAN if the box is empty + * Returns NAN if the box is empty. */ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, double *dest_x, double *dest_y); /** - * Gives the intersecting box between two wlr_box. + * Gives the intersecting box between two struct wlr_box. * - * Returns an empty wlr_box if the provided wlr_box don't intersect. + * Returns an empty box if the provided boxes don't intersect. */ bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a, const struct wlr_box *box_b); /** - * Verifies if a point is contained within the bounds of a given wlr_box. + * Verifies if a point is contained within the bounds of a given struct wlr_box. * * For example: - * - A point at (100, 50) is not contained in the box (0, 0, 100, 50). - * - A point at (10, 10) is contained in the box (10, 0, 50, 50). + * + * - A point at (100, 50) is not contained in the box (0, 0, 100, 50). + * - A point at (10, 10) is contained in the box (10, 0, 50, 50). */ bool wlr_box_contains_point(const struct wlr_box *box, double x, double y); /** * Checks whether a box is empty or not. * - * A wlr_box is considered empty if its width and/or height is zero or negative. + * A box is considered empty if its width and/or height is zero or negative. */ bool wlr_box_empty(const struct wlr_box *box); @@ -81,7 +82,7 @@ void wlr_box_transform(struct wlr_box *dest, const struct wlr_box *box, /** * Checks whether a box is empty or not. * - * A wlr_box is considered empty if its width and/or height is zero or negative. + * A box is considered empty if its width and/or height is zero or negative. */ bool wlr_fbox_empty(const struct wlr_fbox *box); diff --git a/include/wlr/util/log.h b/include/wlr/util/log.h index aacdea99f..5e5d8393b 100644 --- a/include/wlr/util/log.h +++ b/include/wlr/util/log.h @@ -32,13 +32,20 @@ enum wlr_log_importance { typedef void (*wlr_log_func_t)(enum wlr_log_importance importance, const char *fmt, va_list args); -// Will log all messages less than or equal to `verbosity` -// If `callback` is NULL, wlr will use its default logger. -// The function can be called multiple times to update the verbosity or -// callback function. +/** + * Set the log verbosity and callback. + * + * Only messages less than or equal to the supplied verbosity will be logged. + * If the callback is NULL, the default logger is used. + * + * This function can be called multiple times to update the verbosity or + * callback function. + */ void wlr_log_init(enum wlr_log_importance verbosity, wlr_log_func_t callback); -// Returns the log verbosity provided to wlr_log_init +/** + * Get the current log verbosity configured by wlr_log_init(). + */ enum wlr_log_importance wlr_log_get_verbosity(void); #ifdef __GNUC__ From 4b77eadf065ace403495ff1f3e7d19a5b7a85cf7 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 17:50:39 +0200 Subject: [PATCH 128/298] render/egl: drop MESA_EGL_NO_X11_HEADERS This has been superseded by the standard EGL_NO_X11 switch, supported by Mesa 19.3.0+. --- include/wlr/render/egl.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index e4416e0ba..81d4dfa4d 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -9,9 +9,6 @@ #ifndef WLR_RENDER_EGL_H #define WLR_RENDER_EGL_H -#ifndef MESA_EGL_NO_X11_HEADERS -#define MESA_EGL_NO_X11_HEADERS -#endif #ifndef EGL_NO_X11 #define EGL_NO_X11 #endif From 452a8ec9401fabc054872fdbd5096c4a87fcea8a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 17:42:24 +0200 Subject: [PATCH 129/298] render/egl: add wlr_egl_get_{context,display} This allows compositors to integrate with the wlroots GLES2 renderer, if they need to perform custom GL rendering. --- include/wlr/render/egl.h | 16 ++++++++++++++++ render/egl.c | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 81d4dfa4d..062222372 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -70,6 +70,22 @@ struct wlr_egl { struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, EGLContext context); +/** + * Get the EGL display used by the struct wlr_egl. + * + * This is typically used by compositors which need to perform custom OpenGL + * operations. + */ +EGLDisplay wlr_egl_get_display(struct wlr_egl *egl); + +/** + * Get the EGL context used by the struct wlr_egl. + * + * This is typically used by compositors which need to perform custom OpenGL + * operations. + */ +EGLContext wlr_egl_get_context(struct wlr_egl *egl); + /** * Make the EGL context current. * diff --git a/render/egl.c b/render/egl.c index 81ce3b260..dfba8edd3 100644 --- a/render/egl.c +++ b/render/egl.c @@ -583,6 +583,14 @@ void wlr_egl_destroy(struct wlr_egl *egl) { free(egl); } +EGLDisplay wlr_egl_get_display(struct wlr_egl *egl) { + return egl->display; +} + +EGLContext wlr_egl_get_context(struct wlr_egl *egl) { + return egl->context; +} + bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImage image) { if (!egl->exts.KHR_image_base) { return false; From f954092f22256c807c70f2a7de376f29e864d342 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 31 Mar 2022 11:29:24 +0200 Subject: [PATCH 130/298] render/egl: make wlr_egl struct opaque Compositors can use wlr_egl_create_with_context if they need a custom EGL display or context. --- include/render/egl.h | 41 ++++++++++++++++++++++++++++++++++++++++ include/wlr/render/egl.h | 41 +--------------------------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/include/render/egl.h b/include/render/egl.h index 55e9ce80f..547254c88 100644 --- a/include/render/egl.h +++ b/include/render/egl.h @@ -3,6 +3,47 @@ #include +struct wlr_egl { + EGLDisplay display; + EGLContext context; + EGLDeviceEXT device; // may be EGL_NO_DEVICE_EXT + struct gbm_device *gbm_device; + + struct { + // Display extensions + bool KHR_image_base; + bool EXT_image_dma_buf_import; + bool EXT_image_dma_buf_import_modifiers; + bool IMG_context_priority; + + // Device extensions + bool EXT_device_drm; + bool EXT_device_drm_render_node; + + // Client extensions + bool EXT_device_query; + bool KHR_platform_gbm; + bool EXT_platform_device; + } exts; + + struct { + PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; + PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT; + PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT; + PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR; + PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT; + PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; + PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; + } procs; + + bool has_modifiers; + struct wlr_drm_format_set dmabuf_texture_formats; + struct wlr_drm_format_set dmabuf_render_formats; +}; + struct wlr_egl_context { EGLDisplay display; EGLContext context; diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 062222372..8cb48e02f 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -26,46 +26,7 @@ #include #include -struct wlr_egl { - EGLDisplay display; - EGLContext context; - EGLDeviceEXT device; // may be EGL_NO_DEVICE_EXT - struct gbm_device *gbm_device; - - struct { - // Display extensions - bool KHR_image_base; - bool EXT_image_dma_buf_import; - bool EXT_image_dma_buf_import_modifiers; - bool IMG_context_priority; - - // Device extensions - bool EXT_device_drm; - bool EXT_device_drm_render_node; - - // Client extensions - bool EXT_device_query; - bool KHR_platform_gbm; - bool EXT_platform_device; - } exts; - - struct { - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; - PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; - PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; - PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT; - PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT; - PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR; - PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT; - PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; - PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; - } procs; - - bool has_modifiers; - struct wlr_drm_format_set dmabuf_texture_formats; - struct wlr_drm_format_set dmabuf_render_formats; -}; +struct wlr_egl; struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, EGLContext context); From 4b3e08c8acf0b83654c203bf7e055fc995f2540f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 17:43:51 +0200 Subject: [PATCH 131/298] render/egl: make wlr_egl_{make,unset,is}_current private These are trivial wrappers around eglMakeCurrent and eglGetCurrentContext. Compositors which need to call these functions will also call other EGL or GL functions anyways. Let's reduce our API surface a bit by making them private. --- include/render/egl.h | 12 ++++++++++++ include/wlr/render/egl.h | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/render/egl.h b/include/render/egl.h index 547254c88..f77e11476 100644 --- a/include/render/egl.h +++ b/include/render/egl.h @@ -101,4 +101,16 @@ void wlr_egl_save_context(struct wlr_egl_context *context); */ bool wlr_egl_restore_context(struct wlr_egl_context *context); +/** + * Make the EGL context current. + * + * Callers are expected to clear the current context when they are done by + * calling wlr_egl_unset_current(). + */ +bool wlr_egl_make_current(struct wlr_egl *egl); + +bool wlr_egl_unset_current(struct wlr_egl *egl); + +bool wlr_egl_is_current(struct wlr_egl *egl); + #endif diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 8cb48e02f..7374e86d3 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -47,16 +47,4 @@ EGLDisplay wlr_egl_get_display(struct wlr_egl *egl); */ EGLContext wlr_egl_get_context(struct wlr_egl *egl); -/** - * Make the EGL context current. - * - * Callers are expected to clear the current context when they are done by - * calling wlr_egl_unset_current(). - */ -bool wlr_egl_make_current(struct wlr_egl *egl); - -bool wlr_egl_unset_current(struct wlr_egl *egl); - -bool wlr_egl_is_current(struct wlr_egl *egl); - #endif From 1cb6b2cf673a5b580d7ad79ce2b37c14b14b0268 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 25 May 2022 17:48:00 +0200 Subject: [PATCH 132/298] render/egl: document wlr_egl_create_with_context --- include/wlr/render/egl.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 7374e86d3..9bf1b8019 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -28,6 +28,12 @@ struct wlr_egl; +/** + * Create a struct wlr_egl with an existing EGL display and context. + * + * This is typically used by compositors which want to customize EGL + * initialization. + */ struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, EGLContext context); From 2e69eb10303f3074d6cafef30e7e1ce49cb7a1ac Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 26 May 2022 09:38:48 +0200 Subject: [PATCH 133/298] backend/drm: fix crash in init_drm_surface Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3434 --- backend/drm/renderer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 601553138..9e1de3d0a 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -61,7 +61,8 @@ static void finish_drm_surface(struct wlr_drm_surface *surf) { bool init_drm_surface(struct wlr_drm_surface *surf, struct wlr_drm_renderer *renderer, int width, int height, const struct wlr_drm_format *drm_format) { - if (surf->swapchain->width == width && surf->swapchain->height == height) { + if (surf->swapchain != NULL && surf->swapchain->width == width && + surf->swapchain->height == height) { return true; } From be86145322e6157994b348711b7bedd209b565ea Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 23 May 2022 10:32:26 +0200 Subject: [PATCH 134/298] output: turn make/model/serial into char * This allows the make/model/serial to be NULL when unset, and allows them to be longer than the hardcoded array length. This is a breaking change: compositors need to handle the new NULL case, and we stop setting make/model to useless "headless" or "wayland" strings. --- backend/drm/util.c | 29 ++++++++++++++++++++--------- backend/headless/output.c | 2 -- backend/wayland/output.c | 2 -- backend/x11/output.c | 19 +++++++++++++------ include/wlr/types/wlr_output.h | 4 +--- types/output/output.c | 13 ++++++++++++- types/wlr_output_management_v1.c | 6 +++--- 7 files changed, 49 insertions(+), 26 deletions(-) diff --git a/backend/drm/util.c b/backend/drm/util.c index 33446fd75..8588fa86e 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -1,9 +1,11 @@ +#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include +#include #include #include #include "backend/drm/drm.h" @@ -64,34 +66,40 @@ static const char *get_manufacturer(struct udev_hwdb *hwdb, uint16_t code) { void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) { struct wlr_output *output = &conn->output; + free(output->make); + free(output->model); + free(output->serial); + output->make = NULL; + output->model = NULL; + output->serial = NULL; + if (!data || len < 128) { - snprintf(output->make, sizeof(output->make), "Unknown"); - snprintf(output->model, sizeof(output->model), "Unknown"); return; } uint16_t id = (data[8] << 8) | data[9]; - snprintf(output->make, sizeof(output->make), "%s", - get_manufacturer(conn->backend->hwdb, id)); + output->make = strdup(get_manufacturer(conn->backend->hwdb, id)); uint16_t model = data[10] | (data[11] << 8); - snprintf(output->model, sizeof(output->model), "0x%04X", model); + char model_str[32]; + snprintf(model_str, sizeof(model_str), "0x%04" PRIX16, model); uint32_t serial = data[12] | (data[13] << 8) | (data[14] << 8) | (data[15] << 8); - snprintf(output->serial, sizeof(output->serial), "0x%08X", serial); + char serial_str[32]; + snprintf(serial_str, sizeof(serial_str), "0x%08" PRIX32, serial); for (size_t i = 72; i <= 108; i += 18) { uint16_t flag = (data[i] << 8) | data[i + 1]; if (flag == 0 && data[i + 3] == 0xFC) { - sprintf(output->model, "%.13s", &data[i + 5]); + snprintf(model_str, sizeof(model_str), "%.13s", &data[i + 5]); // Monitor names are terminated by newline if they're too short - char *nl = strchr(output->model, '\n'); + char *nl = strchr(model_str, '\n'); if (nl) { *nl = '\0'; } } else if (flag == 0 && data[i + 3] == 0xFF) { - sprintf(output->serial, "%.13s", &data[i + 5]); + snprintf(serial_str, sizeof(serial_str), "%.13s", &data[i + 5]); // Monitor serial numbers are terminated by newline if they're too // short @@ -101,6 +109,9 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) } } } + + output->model = strdup(model_str); + output->serial = strdup(serial_str); } const char *conn_get_name(uint32_t type_id) { diff --git a/backend/headless/output.c b/backend/headless/output.c index 10de845f3..824a265e0 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -115,8 +115,6 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend, struct wlr_output *wlr_output = &output->wlr_output; output_set_custom_mode(output, width, height, 0); - strncpy(wlr_output->make, "headless", sizeof(wlr_output->make)); - strncpy(wlr_output->model, "headless", sizeof(wlr_output->model)); char name[64]; snprintf(name, sizeof(name), "HEADLESS-%zu", ++backend->last_output_num); diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 65084b7a2..87b8ca1f6 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -520,8 +520,6 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { struct wlr_output *wlr_output = &output->wlr_output; wlr_output_update_custom_mode(wlr_output, 1280, 720, 0); - strncpy(wlr_output->make, "wayland", sizeof(wlr_output->make)); - strncpy(wlr_output->model, "wayland", sizeof(wlr_output->model)); char name[64]; snprintf(name, sizeof(name), "WL-%zu", ++backend->last_output_num); diff --git a/backend/x11/output.c b/backend/x11/output.c index 86e1dfd8e..383103748 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -33,12 +33,19 @@ static void parse_xcb_setup(struct wlr_output *output, xcb_connection_t *xcb) { const xcb_setup_t *xcb_setup = xcb_get_setup(xcb); - snprintf(output->make, sizeof(output->make), "%.*s", - xcb_setup_vendor_length(xcb_setup), - xcb_setup_vendor(xcb_setup)); - snprintf(output->model, sizeof(output->model), "%"PRIu16".%"PRIu16, - xcb_setup->protocol_major_version, - xcb_setup->protocol_minor_version); + output->make = calloc(1, xcb_setup_vendor_length(xcb_setup) + 1); + if (output->make == NULL) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return; + } + memcpy(output->make, xcb_setup_vendor(xcb_setup), + xcb_setup_vendor_length(xcb_setup)); + + char model[64]; + snprintf(model, sizeof(model), "%"PRIu16".%"PRIu16, + xcb_setup->protocol_major_version, + xcb_setup->protocol_minor_version); + output->model = strdup(output->model); } static struct wlr_x11_output *get_x11_output_from_output( diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 48b6e6f9c..13b6797fe 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -122,9 +122,7 @@ struct wlr_output { char *name; char *description; // may be NULL - char make[56]; - char model[16]; - char serial[16]; + char *make, *model, *serial; // may be NULL int32_t phys_width, phys_height; // mm // Note: some backends may have zero modes diff --git a/types/output/output.c b/types/output/output.c index 68a74b6b3..4f7259150 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -17,9 +17,20 @@ static void send_geometry(struct wl_resource *resource) { struct wlr_output *output = wlr_output_from_resource(resource); + + const char *make = output->make; + if (make == NULL) { + make = "Unknown"; + } + + const char *model = output->model; + if (model == NULL) { + model = "Unknown"; + } + wl_output_send_geometry(resource, 0, 0, output->phys_width, output->phys_height, output->subpixel, - output->make, output->model, output->transform); + make, model, output->transform); } static void send_current_mode(struct wl_resource *resource) { diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index 7acfe9d95..2c3ae0275 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -767,13 +767,13 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager, output->phys_width, output->phys_height); } - if (version >= ZWLR_OUTPUT_HEAD_V1_MAKE_SINCE_VERSION && output->make[0] != '\0') { + if (version >= ZWLR_OUTPUT_HEAD_V1_MAKE_SINCE_VERSION && output->make != NULL) { zwlr_output_head_v1_send_make(head_resource, output->make); } - if (version >= ZWLR_OUTPUT_HEAD_V1_MODEL_SINCE_VERSION && output->model[0] != '\0') { + if (version >= ZWLR_OUTPUT_HEAD_V1_MODEL_SINCE_VERSION && output->model != NULL) { zwlr_output_head_v1_send_model(head_resource, output->model); } - if (version >= ZWLR_OUTPUT_HEAD_V1_SERIAL_NUMBER_SINCE_VERSION && output->serial[0] != '\0') { + if (version >= ZWLR_OUTPUT_HEAD_V1_SERIAL_NUMBER_SINCE_VERSION && output->serial != NULL) { zwlr_output_head_v1_send_serial_number(head_resource, output->serial); } From 4d7f1aeb734cd2c9d75a59a0793941d5bb012749 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 26 May 2022 10:28:21 +0200 Subject: [PATCH 135/298] linux-dmabuf-v1: fix MOD_INVALID handling in feedback tranches [1] has changed wlr_drm_format to remove the assumption that MOD_INVALID is always implicitly enabled. MOD_INVALID is now part of the modifier list just like any other modifier. The patch adding support for linux-dmabuf-v1 feedback has been written a lot of time before [1], and hasn't been updated accordingly when merged. This results in MOD_INVALID being advertised twice [2] and other index bugs. Fix these issues by removing special-casing for MOD_INVALID. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3231 [2]: https://github.com/swaywm/sway/issues/7028 --- types/wlr_linux_dmabuf_v1.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index 69aa64b78..a124d5212 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -475,16 +475,12 @@ static ssize_t get_drm_format_set_index(const struct wlr_drm_format_set *set, format_found = true; break; } - idx += 1 + fmt->len; + idx += fmt->len; } if (!format_found) { return -1; } - if (modifier == DRM_FORMAT_MOD_INVALID) { - return idx; - } - for (size_t i = 0; i < fmt->len; i++) { if (fmt->modifiers[i] == modifier) { return idx; @@ -506,7 +502,7 @@ static struct wlr_linux_dmabuf_feedback_v1_compiled *feedback_compile( size_t table_len = 0; for (size_t i = 0; i < fallback_tranche->formats->len; i++) { const struct wlr_drm_format *fmt = fallback_tranche->formats->formats[i]; - table_len += 1 + fmt->len; + table_len += fmt->len; } assert(table_len > 0); @@ -533,12 +529,6 @@ static struct wlr_linux_dmabuf_feedback_v1_compiled *feedback_compile( for (size_t i = 0; i < fallback_tranche->formats->len; i++) { const struct wlr_drm_format *fmt = fallback_tranche->formats->formats[i]; - table[n] = (struct wlr_linux_dmabuf_feedback_v1_table_entry){ - .format = fmt->format, - .modifier = DRM_FORMAT_MOD_INVALID, - }; - n++; - for (size_t k = 0; k < fmt->len; k++) { table[n] = (struct wlr_linux_dmabuf_feedback_v1_table_entry){ .format = fmt->format, @@ -584,20 +574,6 @@ static struct wlr_linux_dmabuf_feedback_v1_compiled *feedback_compile( uint16_t *indices = compiled_tranche->indices.data; for (size_t j = 0; j < tranche->formats->len; j++) { const struct wlr_drm_format *fmt = tranche->formats->formats[j]; - - ssize_t index = get_drm_format_set_index( - fallback_tranche->formats, fmt->format, - DRM_FORMAT_MOD_INVALID); - if (index < 0) { - wlr_log(WLR_ERROR, "Format 0x%" PRIX32 " and modifier " - "INVALID are in tranche #%zu but are missing " - "from the fallback tranche", - fmt->format, i); - goto error_compiled; - } - indices[n] = index; - n++; - for (size_t k = 0; k < fmt->len; k++) { ssize_t index = get_drm_format_set_index( fallback_tranche->formats, fmt->format, fmt->modifiers[k]); From d0d480b91acc049db3effaf98d0e43f5de908446 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 26 May 2022 17:55:09 +0200 Subject: [PATCH 136/298] backend/drm: fix crash with null serial backend/drm: use serial_str instead --- backend/drm/util.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/drm/util.c b/backend/drm/util.c index 8588fa86e..eb4190926 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -103,7 +103,8 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) // Monitor serial numbers are terminated by newline if they're too // short - char *nl = strchr(output->serial, '\n'); + char* nl = strchr(serial_str, '\n'); + if (nl) { *nl = '\0'; } From 4f5d6e474635ee75d57650e4f1ae0926011c1263 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 26 May 2022 17:48:37 +0200 Subject: [PATCH 137/298] backend/x11: fix output model strdup call References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3434#note_1401193 Fixes: be86145322e6 ("output: turn make/model/serial into char *") --- backend/x11/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/x11/output.c b/backend/x11/output.c index 383103748..ba34fef77 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -45,7 +45,7 @@ static void parse_xcb_setup(struct wlr_output *output, snprintf(model, sizeof(model), "%"PRIu16".%"PRIu16, xcb_setup->protocol_major_version, xcb_setup->protocol_minor_version); - output->model = strdup(output->model); + output->model = strdup(model); } static struct wlr_x11_output *get_x11_output_from_output( From 4a968576e44240b447330c848d6cd624d2a27c62 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 5 Mar 2022 19:32:35 +0300 Subject: [PATCH 138/298] xdg-popup: add proper configure flow --- include/types/wlr_xdg_shell.h | 4 ++++ include/wlr/types/wlr_xdg_shell.h | 14 ++++++++++--- types/xdg_shell/wlr_xdg_popup.c | 34 ++++++++++++++++++++++++++----- types/xdg_shell/wlr_xdg_surface.c | 11 +++++----- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/include/types/wlr_xdg_shell.h b/include/types/wlr_xdg_shell.h index cfed6ee1d..37ef2a95f 100644 --- a/include/types/wlr_xdg_shell.h +++ b/include/types/wlr_xdg_shell.h @@ -26,6 +26,10 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, void unmap_xdg_popup(struct wlr_xdg_popup *popup); void destroy_xdg_popup(struct wlr_xdg_popup *popup); void handle_xdg_popup_committed(struct wlr_xdg_popup *popup); +struct wlr_xdg_popup_configure *send_xdg_popup_configure( + struct wlr_xdg_popup *popup); +void handle_xdg_popup_ack_configure(struct wlr_xdg_popup *popup, + struct wlr_xdg_popup_configure *configure); void create_xdg_toplevel(struct wlr_xdg_surface *surface, uint32_t id); diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 51ba05845..19378c16e 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -70,6 +70,11 @@ struct wlr_xdg_positioner { struct wlr_xdg_positioner_rules rules; }; +struct wlr_xdg_popup_configure { + struct wlr_box geometry; + struct wlr_xdg_positioner_rules rules; +}; + struct wlr_xdg_popup { struct wlr_xdg_surface *base; struct wl_list link; @@ -79,12 +84,12 @@ struct wlr_xdg_popup { struct wlr_surface *parent; struct wlr_seat *seat; + struct wlr_xdg_popup_configure scheduled; + // Position of the popup relative to the upper left corner of the window // geometry of the parent surface struct wlr_box geometry; - struct wlr_xdg_positioner_rules positioner_rules; - struct wl_list grab_link; // wlr_xdg_popup_grab.popups }; @@ -173,7 +178,10 @@ struct wlr_xdg_surface_configure { struct wl_list link; // wlr_xdg_surface.configure_list uint32_t serial; - struct wlr_xdg_toplevel_configure *toplevel_configure; + union { + struct wlr_xdg_toplevel_configure *toplevel_configure; + struct wlr_xdg_popup_configure *popup_configure; + }; }; struct wlr_xdg_surface_state { diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index 973a339be..fda0d6aa4 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -4,6 +4,30 @@ #include "types/wlr_xdg_shell.h" #include "util/signal.h" +void handle_xdg_popup_ack_configure( + struct wlr_xdg_popup *popup, + struct wlr_xdg_popup_configure *configure) { + popup->geometry = configure->geometry; +} + +struct wlr_xdg_popup_configure *send_xdg_popup_configure( + struct wlr_xdg_popup *popup) { + struct wlr_xdg_popup_configure *configure = + calloc(1, sizeof(*configure)); + if (configure == NULL) { + wl_resource_post_no_memory(popup->resource); + return NULL; + } + *configure = popup->scheduled; + + struct wlr_box *geometry = &configure->geometry; + xdg_popup_send_configure(popup->resource, + geometry->x, geometry->y, + geometry->width, geometry->height); + + return configure; +} + static void xdg_popup_grab_end(struct wlr_xdg_popup_grab *popup_grab) { struct wlr_xdg_popup *popup, *tmp; wl_list_for_each_safe(popup, tmp, &popup_grab->popups, grab_link) { @@ -348,10 +372,9 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, surface->role = WLR_XDG_SURFACE_ROLE_POPUP; - memcpy(&surface->popup->positioner_rules, - &positioner->rules, sizeof(positioner->rules)); wlr_xdg_positioner_rules_get_geometry( - &positioner->rules, &surface->popup->geometry); + &positioner->rules, &surface->popup->scheduled.geometry); + surface->popup->scheduled.rules = positioner->rules; if (parent) { surface->popup->parent = parent->surface; @@ -443,6 +466,7 @@ void wlr_xdg_popup_unconstrain_from_box(struct wlr_xdg_popup *popup, .width = toplevel_space_box->width, .height = toplevel_space_box->height, }; - wlr_xdg_positioner_rules_unconstrain_box(&popup->positioner_rules, - &popup_constraint, &popup->geometry); + wlr_xdg_positioner_rules_unconstrain_box(&popup->scheduled.rules, + &popup_constraint, &popup->scheduled.geometry); + wlr_xdg_surface_schedule_configure(popup->base); } diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 73ed66c92..80144fb62 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -107,9 +107,11 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client, break; case WLR_XDG_SURFACE_ROLE_TOPLEVEL: handle_xdg_toplevel_ack_configure(surface->toplevel, - configure->toplevel_configure); + configure->toplevel_configure); break; case WLR_XDG_SURFACE_ROLE_POPUP: + handle_xdg_popup_ack_configure(surface->popup, + configure->popup_configure); break; } @@ -145,11 +147,8 @@ static void surface_send_configure(void *user_data) { send_xdg_toplevel_configure(surface->toplevel); break; case WLR_XDG_SURFACE_ROLE_POPUP: - xdg_popup_send_configure(surface->popup->resource, - surface->popup->geometry.x, - surface->popup->geometry.y, - surface->popup->geometry.width, - surface->popup->geometry.height); + configure->popup_configure = + send_xdg_popup_configure(surface->popup); break; } From 6f1fce9cb450e22b6312369392d8835667825171 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 13 Apr 2022 20:22:14 +0300 Subject: [PATCH 139/298] xdg-popup: use current/pending state pattern --- include/wlr/types/wlr_xdg_shell.h | 10 +++++++--- types/scene/xdg_shell.c | 2 +- types/wlr_layer_shell_v1.c | 32 +++++++++++++++---------------- types/xdg_shell/wlr_xdg_popup.c | 9 ++++++--- types/xdg_shell/wlr_xdg_surface.c | 4 ++-- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 19378c16e..bfb475fbb 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -70,6 +70,12 @@ struct wlr_xdg_positioner { struct wlr_xdg_positioner_rules rules; }; +struct wlr_xdg_popup_state { + // Position of the popup relative to the upper left corner of + // the window geometry of the parent surface + struct wlr_box geometry; +}; + struct wlr_xdg_popup_configure { struct wlr_box geometry; struct wlr_xdg_positioner_rules rules; @@ -86,9 +92,7 @@ struct wlr_xdg_popup { struct wlr_xdg_popup_configure scheduled; - // Position of the popup relative to the upper left corner of the window - // geometry of the parent surface - struct wlr_box geometry; + struct wlr_xdg_popup_state current, pending; struct wl_list grab_link; // wlr_xdg_popup_grab.popups }; diff --git a/types/scene/xdg_shell.c b/types/scene/xdg_shell.c index 9b3ad71c3..909719d1a 100644 --- a/types/scene/xdg_shell.c +++ b/types/scene/xdg_shell.c @@ -60,7 +60,7 @@ static void scene_xdg_surface_update_position( if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { struct wlr_xdg_popup *popup = xdg_surface->popup; wlr_scene_node_set_position(&scene_xdg_surface->tree->node, - popup->geometry.x, popup->geometry.y); + popup->current.geometry.x, popup->current.geometry.y); } } diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index 107dac631..038ea1d87 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -552,16 +552,15 @@ void wlr_layer_surface_v1_for_each_surface(struct wlr_layer_surface_v1 *surface, void wlr_layer_surface_v1_for_each_popup_surface(struct wlr_layer_surface_v1 *surface, wlr_surface_iterator_func_t iterator, void *user_data){ - struct wlr_xdg_popup *popup_state; - wl_list_for_each(popup_state, &surface->popups, link) { - struct wlr_xdg_surface *popup = popup_state->base; - if (!popup->configured || !popup->mapped) { + struct wlr_xdg_popup *popup; + wl_list_for_each(popup, &surface->popups, link) { + if (!popup->base->configured || !popup->base->mapped) { continue; } double popup_sx, popup_sy; - popup_sx = popup->popup->geometry.x - popup->current.geometry.x; - popup_sy = popup->popup->geometry.y - popup->current.geometry.y; + popup_sx = popup->current.geometry.x - popup->base->current.geometry.x; + popup_sy = popup->current.geometry.y - popup->base->current.geometry.y; struct layer_surface_iterator_data data = { .user_iterator = iterator, @@ -569,7 +568,8 @@ void wlr_layer_surface_v1_for_each_popup_surface(struct wlr_layer_surface_v1 *su .x = popup_sx, .y = popup_sy, }; - wlr_xdg_surface_for_each_surface(popup, layer_surface_iterator, &data); + wlr_xdg_surface_for_each_surface(popup->base, + layer_surface_iterator, &data); } } @@ -587,20 +587,18 @@ struct wlr_surface *wlr_layer_surface_v1_surface_at( struct wlr_surface *wlr_layer_surface_v1_popup_surface_at( struct wlr_layer_surface_v1 *surface, double sx, double sy, double *sub_x, double *sub_y) { - struct wlr_xdg_popup *popup_state; - wl_list_for_each(popup_state, &surface->popups, link) { - struct wlr_xdg_surface *popup = popup_state->base; - if (!popup->mapped) { + struct wlr_xdg_popup *popup; + wl_list_for_each(popup, &surface->popups, link) { + if (!popup->base->mapped) { continue; } - double popup_sx = popup_state->geometry.x - popup->current.geometry.x; - double popup_sy = popup_state->geometry.y - popup->current.geometry.y; + double popup_sx, popup_sy; + popup_sx = popup->current.geometry.x - popup->base->current.geometry.x; + popup_sy = popup->current.geometry.y - popup->base->current.geometry.y; - struct wlr_surface *sub = wlr_xdg_surface_surface_at(popup, - sx - popup_sx, - sy - popup_sy, - sub_x, sub_y); + struct wlr_surface *sub = wlr_xdg_surface_surface_at( + popup->base, sx - popup_sx, sy - popup_sy, sub_x, sub_y); if (sub != NULL) { return sub; } diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index fda0d6aa4..26b5f0ef4 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -7,7 +7,7 @@ void handle_xdg_popup_ack_configure( struct wlr_xdg_popup *popup, struct wlr_xdg_popup_configure *configure) { - popup->geometry = configure->geometry; + popup->pending.geometry = configure->geometry; } struct wlr_xdg_popup_configure *send_xdg_popup_configure( @@ -238,7 +238,10 @@ void handle_xdg_popup_committed(struct wlr_xdg_popup *popup) { if (!popup->committed) { wlr_xdg_surface_schedule_configure(popup->base); popup->committed = true; + return; } + + popup->current = popup->pending; } static const struct xdg_popup_interface xdg_popup_implementation; @@ -440,8 +443,8 @@ void wlr_xdg_popup_get_toplevel_coords(struct wlr_xdg_popup *popup, wlr_xdg_surface_from_wlr_surface(parent); if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - popup_sx += xdg_surface->popup->geometry.x; - popup_sy += xdg_surface->popup->geometry.y; + popup_sx += xdg_surface->popup->current.geometry.x; + popup_sy += xdg_surface->popup->current.geometry.y; parent = xdg_surface->popup->parent; } else { popup_sx += xdg_surface->current.geometry.x; diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 80144fb62..9ea8fa33b 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -464,9 +464,9 @@ void wlr_xdg_popup_get_position(struct wlr_xdg_popup *popup, wlr_xdg_surface_from_wlr_surface(popup->parent); struct wlr_box parent_geo; wlr_xdg_surface_get_geometry(parent, &parent_geo); - *popup_sx = parent_geo.x + popup->geometry.x - + *popup_sx = parent_geo.x + popup->current.geometry.x - popup->base->current.geometry.x; - *popup_sy = parent_geo.y + popup->geometry.y - + *popup_sy = parent_geo.y + popup->current.geometry.y - popup->base->current.geometry.y; } From 8a0835c59c5569d6e0d24b5d246cce069262ad3c Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 12 Apr 2022 11:45:21 +0300 Subject: [PATCH 140/298] xdg-positioner: add v3 parameters --- include/wlr/types/wlr_xdg_shell.h | 9 +++++++- types/xdg_shell/wlr_xdg_popup.c | 1 + types/xdg_shell/wlr_xdg_positioner.c | 31 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index bfb475fbb..687883e9b 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -56,9 +56,14 @@ struct wlr_xdg_positioner_rules { enum xdg_positioner_gravity gravity; enum xdg_positioner_constraint_adjustment constraint_adjustment; + bool reactive; + + bool has_parent_configure_serial; + uint32_t parent_configure_serial; + struct { int32_t width, height; - } size; + } size, parent_size; struct { int32_t x, y; @@ -74,6 +79,8 @@ struct wlr_xdg_popup_state { // Position of the popup relative to the upper left corner of // the window geometry of the parent surface struct wlr_box geometry; + + bool reactive; }; struct wlr_xdg_popup_configure { diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index 26b5f0ef4..eb405d964 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -8,6 +8,7 @@ void handle_xdg_popup_ack_configure( struct wlr_xdg_popup *popup, struct wlr_xdg_popup_configure *configure) { popup->pending.geometry = configure->geometry; + popup->pending.reactive = configure->rules.reactive; } struct wlr_xdg_popup_configure *send_xdg_popup_configure( diff --git a/types/xdg_shell/wlr_xdg_positioner.c b/types/xdg_shell/wlr_xdg_positioner.c index eff81ea33..6a991bbac 100644 --- a/types/xdg_shell/wlr_xdg_positioner.c +++ b/types/xdg_shell/wlr_xdg_positioner.c @@ -95,6 +95,34 @@ static void xdg_positioner_handle_set_offset(struct wl_client *client, positioner->rules.offset.y = y; } +static void xdg_positioner_handle_set_reactive( + struct wl_client *client, struct wl_resource *resource) { + struct wlr_xdg_positioner *positioner = + wlr_xdg_positioner_from_resource(resource); + + positioner->rules.reactive = true; +} + +static void xdg_positioner_handle_set_parent_configure( + struct wl_client *client, struct wl_resource *resource, + uint32_t serial) { + struct wlr_xdg_positioner *positioner = + wlr_xdg_positioner_from_resource(resource); + + positioner->rules.has_parent_configure_serial = true; + positioner->rules.parent_configure_serial = serial; +} + +static void xdg_positioner_handle_set_parent_size(struct wl_client *client, + struct wl_resource *resource, + int32_t parent_width, int32_t parent_height) { + struct wlr_xdg_positioner *positioner = + wlr_xdg_positioner_from_resource(resource); + + positioner->rules.parent_size.width = parent_width; + positioner->rules.parent_size.height = parent_height; +} + static void xdg_positioner_handle_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); @@ -110,6 +138,9 @@ static const struct xdg_positioner_interface .set_constraint_adjustment = xdg_positioner_handle_set_constraint_adjustment, .set_offset = xdg_positioner_handle_set_offset, + .set_reactive = xdg_positioner_handle_set_reactive, + .set_parent_size = xdg_positioner_handle_set_parent_size, + .set_parent_configure = xdg_positioner_handle_set_parent_configure, }; static void xdg_positioner_handle_resource_destroy( From 1761c3bbe22134644f79d07d62acaa8e288049da Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 13 Apr 2022 20:40:23 +0300 Subject: [PATCH 141/298] xdg-popup: add reposition support --- include/wlr/types/wlr_xdg_shell.h | 7 +++++++ types/xdg_shell/wlr_xdg_popup.c | 33 ++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 687883e9b..04463d2ca 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -86,6 +86,9 @@ struct wlr_xdg_popup_state { struct wlr_xdg_popup_configure { struct wlr_box geometry; struct wlr_xdg_positioner_rules rules; + + bool has_reposition_token; + uint32_t reposition_token; }; struct wlr_xdg_popup { @@ -101,6 +104,10 @@ struct wlr_xdg_popup { struct wlr_xdg_popup_state current, pending; + struct { + struct wl_signal reposition; + } events; + struct wl_list grab_link; // wlr_xdg_popup_grab.popups }; diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index eb405d964..5f8cd4540 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -21,6 +21,12 @@ struct wlr_xdg_popup_configure *send_xdg_popup_configure( } *configure = popup->scheduled; + if (popup->scheduled.has_reposition_token) { + popup->scheduled.has_reposition_token = false; + xdg_popup_send_repositioned(popup->resource, + popup->scheduled.reposition_token); + } + struct wlr_box *geometry = &configure->geometry; xdg_popup_send_configure(popup->resource, geometry->x, geometry->y, @@ -295,6 +301,28 @@ static void xdg_popup_handle_grab(struct wl_client *client, &popup_grab->touch_grab); } +static void xdg_popup_handle_reposition( + struct wl_client *client, struct wl_resource *resource, + struct wl_resource *positioner_resource, uint32_t token) { + struct wlr_xdg_popup *popup = + wlr_xdg_popup_from_resource(resource); + if (!popup) { + return; + } + + struct wlr_xdg_positioner *positioner = + wlr_xdg_positioner_from_resource(positioner_resource); + wlr_xdg_positioner_rules_get_geometry( + &positioner->rules, &popup->scheduled.geometry); + popup->scheduled.rules = positioner->rules; + popup->scheduled.has_reposition_token = true; + popup->scheduled.reposition_token = token; + + wlr_xdg_surface_schedule_configure(popup->base); + + wlr_signal_emit_safe(&popup->events.reposition, NULL); +} + static void xdg_popup_handle_destroy(struct wl_client *client, struct wl_resource *resource) { struct wlr_xdg_popup *popup = @@ -313,6 +341,7 @@ static void xdg_popup_handle_destroy(struct wl_client *client, static const struct xdg_popup_interface xdg_popup_implementation = { .destroy = xdg_popup_handle_destroy, .grab = xdg_popup_handle_grab, + .reposition = xdg_popup_handle_reposition, }; static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) { @@ -380,6 +409,8 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, &positioner->rules, &surface->popup->scheduled.geometry); surface->popup->scheduled.rules = positioner->rules; + wl_signal_init(&surface->popup->events.reposition); + if (parent) { surface->popup->parent = parent->surface; wl_list_insert(&parent->popups, &surface->popup->link); @@ -407,7 +438,7 @@ void unmap_xdg_popup(struct wlr_xdg_popup *popup) { if (grab->seat->touch_state.grab == &grab->touch_grab) { wlr_seat_touch_end_grab(grab->seat); } - + destroy_xdg_popup_grab(grab); } From c1ec71903c51bb152d63cd96c5aae3fffa3639ec Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 12 Apr 2022 14:50:40 +0300 Subject: [PATCH 142/298] xdg-shell: bump version to 3 --- types/xdg_shell/wlr_xdg_shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 0d40b553d..7e6bf5f81 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -3,7 +3,7 @@ #include "types/wlr_xdg_shell.h" #include "util/signal.h" -#define WM_BASE_VERSION 2 +#define WM_BASE_VERSION 3 static const struct xdg_wm_base_interface xdg_shell_impl; From 75d31509db8c28e8379fe9570118ef8c82284581 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 23 May 2022 21:19:02 +0300 Subject: [PATCH 143/298] tinywl: use xdg-shell v3 --- tinywl/tinywl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index bf3fb4339..d8e171e15 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -860,14 +860,14 @@ int main(int argc, char *argv[]) { server.scene = wlr_scene_create(); wlr_scene_attach_output_layout(server.scene, server.output_layout); - /* Set up xdg-shell version 2. The xdg-shell is a Wayland protocol which is + /* Set up xdg-shell version 3. The xdg-shell is a Wayland protocol which is * used for application windows. For more detail on shells, refer to my * article: * * https://drewdevault.com/2018/07/29/Wayland-shells.html */ wl_list_init(&server.views); - server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 2); + server.xdg_shell = wlr_xdg_shell_create(server.wl_display, 3); server.new_xdg_surface.notify = server_new_xdg_surface; wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface); From 0ea15199386bc748c3b1eb87b1087535743eda12 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 20:15:00 +0200 Subject: [PATCH 144/298] docs/env_vars: fix case of WLR_SCENE_DEBUG_DAMAGE values The values are lowercase, not uppercase. --- docs/env_vars.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/env_vars.md b/docs/env_vars.md index 22626c6b0..6a0a94421 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -48,8 +48,8 @@ wlroots reads these environment variables ## scenes * *WLR_SCENE_DEBUG_DAMAGE*: specifies debug options for screen damage related -tasks for compositors that use scenes. (available options: NONE, RERENDER, -HIGHLIGHT) + tasks for compositors that use scenes (available options: none, rerender, + highlight) # Generic From 93ee4c7684050807e959bb3b6d57826a72fba8c2 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 28 May 2022 12:23:51 +0200 Subject: [PATCH 145/298] gitignore: remove unnecessary entries, add subprojects/ The previous entries aren't used because the build files are self-contained in the Meson build directory. Add subprojects/ because it's common for developers to override Meson dependencies via subproject symlinks. --- .gitignore | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index f635e54fe..1d1908c83 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,3 @@ -.clang_complete -*.o -*.a -bin/ -test/ -build/ -build-*/ -wayland-*-protocol.* -wlr-example.ini +/build/ +/build-*/ +/subprojects/ From 25dd3cc0cd89d3220f603e2fcb530ec80c29ff5f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 19:16:50 +0200 Subject: [PATCH 146/298] output: pass wlr_output_state to backend Groundwork for the following commits. The goal is to allow users to specify their own wlr_output_state instead of wlr_output.pending. --- backend/drm/drm.c | 25 +++++++++--------- backend/headless/output.c | 25 +++++++++--------- backend/wayland/output.c | 35 ++++++++++++------------ backend/x11/output.c | 41 ++++++++++++++++------------- include/wlr/interfaces/wlr_output.h | 8 +++--- types/output/output.c | 4 +-- types/output/render.c | 6 ++--- 7 files changed, 75 insertions(+), 69 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index af7e7836f..2caa0ef01 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -459,24 +459,24 @@ static bool drm_connector_set_pending_fb(struct wlr_drm_connector *conn, static bool drm_connector_alloc_crtc(struct wlr_drm_connector *conn); -static bool drm_connector_test(struct wlr_output *output) { +static bool drm_connector_test(struct wlr_output *output, + const struct wlr_output_state *state) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); if (!conn->backend->session->active) { return false; } - uint32_t unsupported = output->pending.committed & ~SUPPORTED_OUTPUT_STATE; + uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE; if (unsupported != 0) { wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32, unsupported); return false; } - if ((output->pending.committed & WLR_OUTPUT_STATE_ENABLED) && - output->pending.enabled) { + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) { if (output->current_mode == NULL && - !(output->pending.committed & WLR_OUTPUT_STATE_MODE)) { + !(state->committed & WLR_OUTPUT_STATE_MODE)) { wlr_drm_conn_log(conn, WLR_DEBUG, "Can't enable an output without a mode"); return false; @@ -484,12 +484,12 @@ static bool drm_connector_test(struct wlr_output *output) { } struct wlr_drm_connector_state pending = {0}; - drm_connector_state_init(&pending, conn, &output->pending); + drm_connector_state_init(&pending, conn, state); if (pending.active) { - if ((output->pending.committed & + if ((state->committed & (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE)) && - !(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { + !(state->committed & WLR_OUTPUT_STATE_BUFFER)) { wlr_drm_conn_log(conn, WLR_DEBUG, "Can't enable an output without a buffer"); return false; @@ -514,7 +514,7 @@ static bool drm_connector_test(struct wlr_output *output) { return true; } - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (!drm_connector_set_pending_fb(conn, pending.base)) { return false; } @@ -597,14 +597,15 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn, return true; } -static bool drm_connector_commit(struct wlr_output *output) { +static bool drm_connector_commit(struct wlr_output *output, + const struct wlr_output_state *state) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); - if (!drm_connector_test(output)) { + if (!drm_connector_test(output, state)) { return false; } - return drm_connector_commit_state(conn, &output->pending); + return drm_connector_commit_state(conn, state); } size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, diff --git a/backend/headless/output.c b/backend/headless/output.c index 824a265e0..2ce15a16c 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -29,40 +29,41 @@ static bool output_set_custom_mode(struct wlr_headless_output *output, return true; } -static bool output_test(struct wlr_output *wlr_output) { - uint32_t unsupported = - wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE; +static bool output_test(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { + uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE; if (unsupported != 0) { wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32, unsupported); return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { - assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + if (state->committed & WLR_OUTPUT_STATE_MODE) { + assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); } return true; } -static bool output_commit(struct wlr_output *wlr_output) { +static bool output_commit(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { struct wlr_headless_output *output = headless_output_from_output(wlr_output); - if (!output_test(wlr_output)) { + if (!output_test(wlr_output, state)) { return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { + if (state->committed & WLR_OUTPUT_STATE_MODE) { if (!output_set_custom_mode(output, - wlr_output->pending.custom_mode.width, - wlr_output->pending.custom_mode.height, - wlr_output->pending.custom_mode.refresh)) { + state->custom_mode.width, + state->custom_mode.height, + state->custom_mode.refresh)) { return false; } } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { struct wlr_output_event_present present_event = { .commit_seq = wlr_output->commit_seq + 1, .presented = true, diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 87b8ca1f6..baa25bc37 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -240,48 +240,49 @@ static struct wlr_wl_buffer *get_or_create_wl_buffer(struct wlr_wl_backend *wl, return create_wl_buffer(wl, wlr_buffer); } -static bool output_test(struct wlr_output *wlr_output) { +static bool output_test(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); - uint32_t unsupported = - wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE; + uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE; if (unsupported != 0) { wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32, unsupported); return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { - assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + if (state->committed & WLR_OUTPUT_STATE_MODE) { + assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); } - if ((wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) && - !test_buffer(output->backend, wlr_output->pending.buffer)) { + if ((state->committed & WLR_OUTPUT_STATE_BUFFER) && + !test_buffer(output->backend, state->buffer)) { return false; } return true; } -static bool output_commit(struct wlr_output *wlr_output) { +static bool output_commit(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); - if (!output_test(wlr_output)) { + if (!output_test(wlr_output, state)) { return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { + if (state->committed & WLR_OUTPUT_STATE_MODE) { if (!output_set_custom_mode(wlr_output, - wlr_output->pending.custom_mode.width, - wlr_output->pending.custom_mode.height, - wlr_output->pending.custom_mode.refresh)) { + state->custom_mode.width, + state->custom_mode.height, + state->custom_mode.refresh)) { return false; } } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { struct wp_presentation_feedback *wp_feedback = NULL; if (output->backend->presentation != NULL) { wp_feedback = wp_presentation_feedback(output->backend->presentation, @@ -289,8 +290,8 @@ static bool output_commit(struct wlr_output *wlr_output) { } pixman_region32_t *damage = NULL; - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) { - damage = &wlr_output->pending.damage; + if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { + damage = (pixman_region32_t *) &state->damage; } if (output->frame_callback != NULL) { @@ -301,7 +302,7 @@ static bool output_commit(struct wlr_output *wlr_output) { output->frame_callback = wl_surface_frame(output->surface); wl_callback_add_listener(output->frame_callback, &frame_listener, output); - struct wlr_buffer *wlr_buffer = wlr_output->pending.buffer; + struct wlr_buffer *wlr_buffer = state->buffer; struct wlr_wl_buffer *buffer = get_or_create_wl_buffer(output->backend, wlr_buffer); if (buffer == NULL) { diff --git a/backend/x11/output.c b/backend/x11/output.c index ba34fef77..3a599023d 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -104,17 +104,17 @@ static void output_destroy(struct wlr_output *wlr_output) { free(output); } -static bool output_test(struct wlr_output *wlr_output) { - uint32_t unsupported = - wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE; +static bool output_test(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { + uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE; if (unsupported != 0) { wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32, unsupported); return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { - assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + if (state->committed & WLR_OUTPUT_STATE_MODE) { + assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); } return true; @@ -257,10 +257,11 @@ static struct wlr_x11_buffer *get_or_create_x11_buffer( return create_x11_buffer(output, wlr_buffer); } -static bool output_commit_buffer(struct wlr_x11_output *output) { +static bool output_commit_buffer(struct wlr_x11_output *output, + const struct wlr_output_state *state) { struct wlr_x11_backend *x11 = output->x11; - struct wlr_buffer *buffer = output->wlr_output.pending.buffer; + struct wlr_buffer *buffer = state->buffer; struct wlr_x11_buffer *x11_buffer = get_or_create_x11_buffer(output, buffer); if (!x11_buffer) { @@ -268,8 +269,9 @@ static bool output_commit_buffer(struct wlr_x11_output *output) { } xcb_xfixes_region_t region = XCB_NONE; - if (output->wlr_output.pending.committed & WLR_OUTPUT_STATE_DAMAGE) { - pixman_region32_union(&output->exposed, &output->exposed, &output->wlr_output.pending.damage); + if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { + pixman_region32_union(&output->exposed, &output->exposed, + (pixman_region32_t *) &state->damage); int rects_len = 0; pixman_box32_t *rects = pixman_region32_rectangles(&output->exposed, &rects_len); @@ -315,26 +317,27 @@ error: return false; } -static bool output_commit(struct wlr_output *wlr_output) { +static bool output_commit(struct wlr_output *wlr_output, + const struct wlr_output_state *state) { struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); struct wlr_x11_backend *x11 = output->x11; - if (!output_test(wlr_output)) { + if (!output_test(wlr_output, state)) { return false; } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { + if (state->committed & WLR_OUTPUT_STATE_MODE) { if (!output_set_custom_mode(wlr_output, - wlr_output->pending.custom_mode.width, - wlr_output->pending.custom_mode.height, - wlr_output->pending.custom_mode.refresh)) { + state->custom_mode.width, + state->custom_mode.height, + state->custom_mode.refresh)) { return false; } } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED && + if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED && x11->atoms.variable_refresh != XCB_ATOM_NONE) { - if (wlr_output->pending.adaptive_sync_enabled) { + if (state->adaptive_sync_enabled) { uint32_t enabled = 1; xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win, x11->atoms.variable_refresh, XCB_ATOM_CARDINAL, 32, 1, @@ -347,8 +350,8 @@ static bool output_commit(struct wlr_output *wlr_output) { } } - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { - if (!output_commit_buffer(output)) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { + if (!output_commit_buffer(output, state)) { return false; } } diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 4de02c0bd..7a1252db8 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -54,18 +54,18 @@ struct wlr_output_impl { */ void (*destroy)(struct wlr_output *output); /** - * Check that the pending output state is a valid configuration. + * Check that the supplied output state is a valid configuration. * * If this function returns true, commit can only fail due to a runtime * error. */ - bool (*test)(struct wlr_output *output); + bool (*test)(struct wlr_output *output, const struct wlr_output_state *state); /** - * Commit the pending output state. + * Commit the supplied output state. * * If a buffer has been attached, a frame event is scheduled. */ - bool (*commit)(struct wlr_output *output); + bool (*commit)(struct wlr_output *output, const struct wlr_output_state *state); /** * Get the maximum number of gamma LUT elements for each channel. * diff --git a/types/output/output.c b/types/output/output.c index 4f7259150..d5cc0c64e 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -665,7 +665,7 @@ bool wlr_output_test(struct wlr_output *output) { return true; } - success = output->impl->test(output); + success = output->impl->test(output, &output->pending); if (!had_buffer) { output_clear_back_buffer(output); @@ -709,7 +709,7 @@ bool wlr_output_commit(struct wlr_output *output) { output_clear_back_buffer(output); } - if (!output->impl->commit(output)) { + if (!output->impl->commit(output, &output->pending)) { wlr_buffer_unlock(back_buffer); output_state_clear(&output->pending); return false; diff --git a/types/output/render.c b/types/output/render.c index 985b93a98..5427b4391 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -185,7 +185,7 @@ bool output_ensure_buffer(struct wlr_output *output) { // If the backend doesn't necessarily need a new buffer on modeset, don't // bother allocating one. - if (!output->impl->test || output->impl->test(output)) { + if (!output->impl->test || output->impl->test(output, &output->pending)) { return true; } @@ -194,7 +194,7 @@ bool output_ensure_buffer(struct wlr_output *output) { if (!output_attach_empty_buffer(output)) { goto error; } - if (!output->impl->test || output->impl->test(output)) { + if (!output->impl->test || output->impl->test(output, &output->pending)) { return true; } @@ -215,7 +215,7 @@ bool output_ensure_buffer(struct wlr_output *output) { if (!output_attach_empty_buffer(output)) { goto error; } - if (!output->impl->test(output)) { + if (!output->impl->test(output, &output->pending)) { goto error; } return true; From 927661d246b23a5a9133547209bc155ed501de2f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 19:29:02 +0200 Subject: [PATCH 147/298] output: pass wlr_output_state to output_pending_resolution --- include/types/wlr_output.h | 4 ++-- types/output/output.c | 22 ++++++++++++---------- types/output/render.c | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h index 1159d00a1..a9018da0e 100644 --- a/include/types/wlr_output.h +++ b/include/types/wlr_output.h @@ -4,8 +4,8 @@ #include #include -void output_pending_resolution(struct wlr_output *output, int *width, - int *height); +void output_pending_resolution(struct wlr_output *output, + const struct wlr_output_state *state, int *width, int *height); struct wlr_drm_format *output_pick_format(struct wlr_output *output, const struct wlr_drm_format_set *display_formats, uint32_t format); diff --git a/types/output/output.c b/types/output/output.c index d5cc0c64e..39d2d12bb 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -535,17 +535,17 @@ static void output_state_clear(struct wlr_output_state *state) { state->committed = 0; } -void output_pending_resolution(struct wlr_output *output, int *width, - int *height) { - if (output->pending.committed & WLR_OUTPUT_STATE_MODE) { - switch (output->pending.mode_type) { +void output_pending_resolution(struct wlr_output *output, + const struct wlr_output_state *state, int *width, int *height) { + if (state->committed & WLR_OUTPUT_STATE_MODE) { + switch (state->mode_type) { case WLR_OUTPUT_STATE_MODE_FIXED: - *width = output->pending.mode->width; - *height = output->pending.mode->height; + *width = state->mode->width; + *height = state->mode->height; return; case WLR_OUTPUT_STATE_MODE_CUSTOM: - *width = output->pending.custom_mode.width; - *height = output->pending.custom_mode.height; + *width = state->custom_mode.width; + *height = state->custom_mode.height; return; } abort(); @@ -583,7 +583,8 @@ static bool output_basic_test(struct wlr_output *output) { // If the size doesn't match, reject buffer (scaling is not // supported) int pending_width, pending_height; - output_pending_resolution(output, &pending_width, &pending_height); + output_pending_resolution(output, &output->pending, + &pending_width, &pending_height); if (output->pending.buffer->width != pending_width || output->pending.buffer->height != pending_height) { wlr_log(WLR_DEBUG, "Direct scan-out buffer size mismatch"); @@ -616,7 +617,8 @@ static bool output_basic_test(struct wlr_output *output) { if (enabled && (output->pending.committed & (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE))) { int pending_width, pending_height; - output_pending_resolution(output, &pending_width, &pending_height); + output_pending_resolution(output, &output->pending, + &pending_width, &pending_height); if (pending_width == 0 || pending_height == 0) { wlr_log(WLR_DEBUG, "Tried to enable an output with a zero mode"); return false; diff --git a/types/output/render.c b/types/output/render.c index 5427b4391..e162044ac 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -46,7 +46,7 @@ bool wlr_output_init_render(struct wlr_output *output, static bool output_create_swapchain(struct wlr_output *output, bool allow_modifiers) { int width, height; - output_pending_resolution(output, &width, &height); + output_pending_resolution(output, &output->pending, &width, &height); struct wlr_allocator *allocator = output->allocator; assert(allocator != NULL); @@ -154,7 +154,7 @@ static bool output_attach_empty_buffer(struct wlr_output *output) { } int width, height; - output_pending_resolution(output, &width, &height); + output_pending_resolution(output, &output->pending, &width, &height); struct wlr_renderer *renderer = output->renderer; wlr_renderer_begin(renderer, width, height); From 9e25d3074d6091141d184c95492d47dd8a6c904e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 19:43:56 +0200 Subject: [PATCH 148/298] output: pass wlr_output_state to rendering functions No functional change. --- include/types/wlr_output.h | 5 +++- types/output/output.c | 15 ++++++---- types/output/render.c | 59 +++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h index a9018da0e..9223407a2 100644 --- a/include/types/wlr_output.h +++ b/include/types/wlr_output.h @@ -6,10 +6,13 @@ void output_pending_resolution(struct wlr_output *output, const struct wlr_output_state *state, int *width, int *height); +void output_state_attach_buffer(struct wlr_output_state *state, + struct wlr_buffer *buffer); struct wlr_drm_format *output_pick_format(struct wlr_output *output, const struct wlr_drm_format_set *display_formats, uint32_t format); void output_clear_back_buffer(struct wlr_output *output); -bool output_ensure_buffer(struct wlr_output *output); +bool output_ensure_buffer(struct wlr_output *output, + struct wlr_output_state *state); #endif diff --git a/types/output/output.c b/types/output/output.c index 39d2d12bb..6d79532f0 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -660,7 +660,7 @@ bool wlr_output_test(struct wlr_output *output) { if (!output_basic_test(output)) { return false; } - if (!output_ensure_buffer(output)) { + if (!output_ensure_buffer(output, &output->pending)) { return false; } if (!output->impl->test) { @@ -681,7 +681,7 @@ bool wlr_output_commit(struct wlr_output *output) { return false; } - if (!output_ensure_buffer(output)) { + if (!output_ensure_buffer(output, &output->pending)) { return false; } @@ -804,11 +804,16 @@ void wlr_output_rollback(struct wlr_output *output) { output_state_clear(&output->pending); } +void output_state_attach_buffer(struct wlr_output_state *state, + struct wlr_buffer *buffer) { + output_state_clear_buffer(state); + state->committed |= WLR_OUTPUT_STATE_BUFFER; + state->buffer = wlr_buffer_lock(buffer); +} + void wlr_output_attach_buffer(struct wlr_output *output, struct wlr_buffer *buffer) { - output_state_clear_buffer(&output->pending); - output->pending.committed |= WLR_OUTPUT_STATE_BUFFER; - output->pending.buffer = wlr_buffer_lock(buffer); + output_state_attach_buffer(&output->pending, buffer); } void wlr_output_send_frame(struct wlr_output *output) { diff --git a/types/output/render.c b/types/output/render.c index e162044ac..ab586d645 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -44,9 +44,9 @@ bool wlr_output_init_render(struct wlr_output *output, * If set to false, the swapchain's format is guaranteed to not use modifiers. */ static bool output_create_swapchain(struct wlr_output *output, - bool allow_modifiers) { + const struct wlr_output_state *state, bool allow_modifiers) { int width, height; - output_pending_resolution(output, &output->pending, &width, &height); + output_pending_resolution(output, state, &width, &height); struct wlr_allocator *allocator = output->allocator; assert(allocator != NULL); @@ -99,10 +99,10 @@ static bool output_create_swapchain(struct wlr_output *output, } static bool output_attach_back_buffer(struct wlr_output *output, - int *buffer_age) { + struct wlr_output_state *state, int *buffer_age) { assert(output->back_buffer == NULL); - if (!output_create_swapchain(output, true)) { + if (!output_create_swapchain(output, state, true)) { return false; } @@ -138,23 +138,29 @@ void output_clear_back_buffer(struct wlr_output *output) { output->back_buffer = NULL; } -bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) { - if (!output_attach_back_buffer(output, buffer_age)) { +static bool output_attach_render(struct wlr_output *output, + struct wlr_output_state *state, int *buffer_age) { + if (!output_attach_back_buffer(output, state, buffer_age)) { return false; } - wlr_output_attach_buffer(output, output->back_buffer); + output_state_attach_buffer(state, output->back_buffer); return true; } -static bool output_attach_empty_buffer(struct wlr_output *output) { - assert(!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)); +bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) { + return output_attach_render(output, &output->pending, buffer_age); +} - if (!wlr_output_attach_render(output, NULL)) { +static bool output_attach_empty_buffer(struct wlr_output *output, + struct wlr_output_state *state) { + assert(!(state->committed & WLR_OUTPUT_STATE_BUFFER)); + + if (!output_attach_render(output, state, NULL)) { return false; } int width, height; - output_pending_resolution(output, &output->pending, &width, &height); + output_pending_resolution(output, state, &width, &height); struct wlr_renderer *renderer = output->renderer; wlr_renderer_begin(renderer, width, height); @@ -164,42 +170,41 @@ static bool output_attach_empty_buffer(struct wlr_output *output) { return true; } -bool output_ensure_buffer(struct wlr_output *output) { +bool output_ensure_buffer(struct wlr_output *output, + struct wlr_output_state *state) { // If we're lighting up an output or changing its mode, make sure to // provide a new buffer bool needs_new_buffer = false; - if ((output->pending.committed & WLR_OUTPUT_STATE_ENABLED) && - output->pending.enabled) { + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) { needs_new_buffer = true; } - if (output->pending.committed & WLR_OUTPUT_STATE_MODE) { + if (state->committed & WLR_OUTPUT_STATE_MODE) { needs_new_buffer = true; } - if (output->pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { + if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { needs_new_buffer = true; } - if (!needs_new_buffer || - (output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) { + if (!needs_new_buffer || (state->committed & WLR_OUTPUT_STATE_BUFFER)) { return true; } // If the backend doesn't necessarily need a new buffer on modeset, don't // bother allocating one. - if (!output->impl->test || output->impl->test(output, &output->pending)) { + if (!output->impl->test || output->impl->test(output, state)) { return true; } wlr_log(WLR_DEBUG, "Attaching empty buffer to output for modeset"); - if (!output_attach_empty_buffer(output)) { + if (!output_attach_empty_buffer(output, state)) { goto error; } - if (!output->impl->test || output->impl->test(output, &output->pending)) { + if (!output->impl->test || output->impl->test(output, state)) { return true; } output_clear_back_buffer(output); - output->pending.committed &= ~WLR_OUTPUT_STATE_BUFFER; + state->committed &= ~WLR_OUTPUT_STATE_BUFFER; if (output->swapchain->format->len == 0) { return false; @@ -209,20 +214,20 @@ bool output_ensure_buffer(struct wlr_output *output) { // modifiers to see if that makes a difference. wlr_log(WLR_DEBUG, "Output modeset test failed, retrying without modifiers"); - if (!output_create_swapchain(output, false)) { + if (!output_create_swapchain(output, state, false)) { return false; } - if (!output_attach_empty_buffer(output)) { + if (!output_attach_empty_buffer(output, state)) { goto error; } - if (!output->impl->test(output, &output->pending)) { + if (!output->impl->test(output, state)) { goto error; } return true; error: output_clear_back_buffer(output); - output->pending.committed &= ~WLR_OUTPUT_STATE_BUFFER; + state->committed &= ~WLR_OUTPUT_STATE_BUFFER; return false; } @@ -291,7 +296,7 @@ uint32_t wlr_output_preferred_read_format(struct wlr_output *output) { return DRM_FORMAT_INVALID; } - if (!output_attach_back_buffer(output, NULL)) { + if (!output_attach_back_buffer(output, &output->pending, NULL)) { return false; } From c4253fef9c1197a4f1228022ca528f38b23b5519 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 19:51:46 +0200 Subject: [PATCH 149/298] output: add wlr_output_test_state Same as wlr_output_test, but takes a wlr_output_state argument. --- include/wlr/types/wlr_output.h | 2 ++ types/output/output.c | 56 +++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 13b6797fe..363df2bc9 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -425,6 +425,8 @@ bool wlr_output_commit(struct wlr_output *output); * Discard the pending output state. */ void wlr_output_rollback(struct wlr_output *output); +bool wlr_output_test_state(struct wlr_output *output, + const struct wlr_output_state *state); /** * Manually schedules a `frame` event. If a `frame` event is already pending, * it is a no-op. diff --git a/types/output/output.c b/types/output/output.c index 6d79532f0..4bd4917af 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -555,8 +555,9 @@ void output_pending_resolution(struct wlr_output *output, } } -static bool output_basic_test(struct wlr_output *output) { - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { +static bool output_basic_test(struct wlr_output *output, + const struct wlr_output_state *state) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (output->frame_pending) { wlr_log(WLR_DEBUG, "Tried to commit a buffer while a frame is pending"); return false; @@ -583,24 +584,24 @@ static bool output_basic_test(struct wlr_output *output) { // If the size doesn't match, reject buffer (scaling is not // supported) int pending_width, pending_height; - output_pending_resolution(output, &output->pending, + output_pending_resolution(output, state, &pending_width, &pending_height); - if (output->pending.buffer->width != pending_width || - output->pending.buffer->height != pending_height) { + if (state->buffer->width != pending_width || + state->buffer->height != pending_height) { wlr_log(WLR_DEBUG, "Direct scan-out buffer size mismatch"); return false; } } } - if (output->pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { + if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { struct wlr_allocator *allocator = output->allocator; assert(allocator != NULL); const struct wlr_drm_format_set *display_formats = wlr_output_get_primary_formats(output, allocator->buffer_caps); struct wlr_drm_format *format = output_pick_format(output, display_formats, - output->pending.render_format); + state->render_format); if (format == NULL) { wlr_log(WLR_ERROR, "Failed to pick primary buffer format for output"); return false; @@ -610,14 +611,14 @@ static bool output_basic_test(struct wlr_output *output) { } bool enabled = output->enabled; - if (output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { - enabled = output->pending.enabled; + if (state->committed & WLR_OUTPUT_STATE_ENABLED) { + enabled = state->enabled; } - if (enabled && (output->pending.committed & (WLR_OUTPUT_STATE_ENABLED | + if (enabled && (state->committed & (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE))) { int pending_width, pending_height; - output_pending_resolution(output, &output->pending, + output_pending_resolution(output, state, &pending_width, &pending_height); if (pending_width == 0 || pending_height == 0) { wlr_log(WLR_DEBUG, "Tried to enable an output with a zero mode"); @@ -625,27 +626,27 @@ static bool output_basic_test(struct wlr_output *output) { } } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_BUFFER) { wlr_log(WLR_DEBUG, "Tried to commit a buffer on a disabled output"); return false; } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_MODE) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_MODE) { wlr_log(WLR_DEBUG, "Tried to modeset a disabled output"); return false; } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { wlr_log(WLR_DEBUG, "Tried to enable adaptive sync on a disabled output"); return false; } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { wlr_log(WLR_DEBUG, "Tried to set format for a disabled output"); return false; } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_GAMMA_LUT) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_GAMMA_LUT) { wlr_log(WLR_DEBUG, "Tried to set the gamma lut on a disabled output"); return false; } - if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) { + if (!enabled && state->committed & WLR_OUTPUT_STATE_SUBPIXEL) { wlr_log(WLR_DEBUG, "Tried to set the subpixel layout on a disabled output"); return false; } @@ -653,30 +654,35 @@ static bool output_basic_test(struct wlr_output *output) { return true; } -bool wlr_output_test(struct wlr_output *output) { - bool had_buffer = output->pending.committed & WLR_OUTPUT_STATE_BUFFER; - bool success; +bool wlr_output_test_state(struct wlr_output *output, + const struct wlr_output_state *state) { + bool had_buffer = state->committed & WLR_OUTPUT_STATE_BUFFER; - if (!output_basic_test(output)) { + // Duplicate the satte because we might mutate it in output_ensure_buffer + struct wlr_output_state pending = *state; + if (!output_basic_test(output, &pending)) { return false; } - if (!output_ensure_buffer(output, &output->pending)) { + if (!output_ensure_buffer(output, &pending)) { return false; } if (!output->impl->test) { return true; } - success = output->impl->test(output, &output->pending); - + bool success = output->impl->test(output, &pending); if (!had_buffer) { output_clear_back_buffer(output); } return success; } +bool wlr_output_test(struct wlr_output *output) { + return wlr_output_test_state(output, &output->pending); +} + bool wlr_output_commit(struct wlr_output *output) { - if (!output_basic_test(output)) { + if (!output_basic_test(output, &output->pending)) { wlr_log(WLR_ERROR, "Basic output test failed for %s", output->name); return false; } From b21c26a1c9b5f035eb69ede201980c82c256dabc Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 20:41:22 +0200 Subject: [PATCH 150/298] output: add wlr_output_event_precommit.state --- include/wlr/types/wlr_output.h | 1 + types/output/output.c | 1 + types/wlr_output_damage.c | 4 +++- types/wlr_screencopy_v1.c | 13 ++++++++----- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 363df2bc9..052751569 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -205,6 +205,7 @@ struct wlr_output_event_damage { struct wlr_output_event_precommit { struct wlr_output *output; struct timespec *when; + const struct wlr_output_state *state; }; struct wlr_output_event_commit { diff --git a/types/output/output.c b/types/output/output.c index 4bd4917af..a587edc13 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -703,6 +703,7 @@ bool wlr_output_commit(struct wlr_output *output) { struct wlr_output_event_precommit pre_event = { .output = output, .when = &now, + .state = &output->pending, }; wlr_signal_emit_safe(&output->events.precommit, &pre_event); diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index f9aabc312..0dfc30ca0 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -47,9 +47,11 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { static void output_handle_precommit(struct wl_listener *listener, void *data) { struct wlr_output_damage *output_damage = wl_container_of(listener, output_damage, output_precommit); + const struct wlr_output_event_precommit *event = data; + const struct wlr_output_state *state = event->state; struct wlr_output *output = output_damage->output; - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (state->committed & WLR_OUTPUT_STATE_BUFFER) { // TODO: find a better way to access this info without a precommit // handler output_damage->pending_attach_render = output->back_buffer != NULL; diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index c656a916b..0b48fe3f4 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -40,16 +40,18 @@ static struct screencopy_damage *screencopy_damage_find( return NULL; } -static void screencopy_damage_accumulate(struct screencopy_damage *damage) { +static void screencopy_damage_accumulate(struct screencopy_damage *damage, + const struct wlr_output_state *state) { struct pixman_region32 *region = &damage->damage; struct wlr_output *output = damage->output; - if (output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) { + if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { // If the compositor submitted damage, copy it over - pixman_region32_union(region, region, &output->pending.damage); + pixman_region32_union(region, region, + (pixman_region32_t *) &state->damage); pixman_region32_intersect_rect(region, region, 0, 0, output->width, output->height); - } else if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + } else if (state->committed & WLR_OUTPUT_STATE_BUFFER) { // If the compositor did not submit damage but did submit a buffer // damage everything pixman_region32_union_rect(region, region, 0, 0, @@ -61,7 +63,8 @@ static void screencopy_damage_handle_output_precommit( struct wl_listener *listener, void *data) { struct screencopy_damage *damage = wl_container_of(listener, damage, output_precommit); - screencopy_damage_accumulate(damage); + const struct wlr_output_event_precommit *event = data; + screencopy_damage_accumulate(damage, event->state); } static void screencopy_damage_destroy(struct screencopy_damage *damage) { From 501ac5398d6f9a85dfdeeb9bf60a342bcff35adc Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 11:35:33 +0200 Subject: [PATCH 151/298] output: add output_state_{init,finish} --- types/output/output.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/types/output/output.c b/types/output/output.c index a587edc13..cdfb48ff5 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -382,6 +382,21 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { wlr_output_destroy_global(output); } +static void output_state_init(struct wlr_output_state *state) { + memset(state, 0, sizeof(*state)); + pixman_region32_init(&state->damage); +} + +static void output_state_finish(struct wlr_output_state *state) { + wlr_buffer_unlock(state->buffer); + // struct wlr_buffer is ref'counted, so the pointer may remain valid after + // wlr_buffer_unlock(). Reset the field to NULL to ensure nobody mistakenly + // reads it after output_state_finish(). + state->buffer = NULL; + pixman_region32_fini(&state->damage); + free(state->gamma_lut); +} + void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, const struct wlr_output_impl *impl, struct wl_display *display) { assert(impl->commit); @@ -411,7 +426,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.mode); wl_signal_init(&output->events.description); wl_signal_init(&output->events.destroy); - pixman_region32_init(&output->pending.damage); + output_state_init(&output->pending); const char *no_hardware_cursors = getenv("WLR_NO_HARDWARE_CURSORS"); if (no_hardware_cursors != NULL && strcmp(no_hardware_cursors, "1") == 0) { @@ -461,7 +476,7 @@ void wlr_output_destroy(struct wlr_output *output) { free(output->name); free(output->description); - pixman_region32_fini(&output->pending.damage); + output_state_finish(&output->pending); if (output->impl && output->impl->destroy) { output->impl->destroy(output); From d483dd2f4caeeab97de97c4e8215f084945de63c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 24 May 2022 20:42:29 +0200 Subject: [PATCH 152/298] output: add wlr_output_commit_state Same as wlr_output_commit, but takes a wlr_output_state. --- include/wlr/types/wlr_output.h | 2 ++ types/output/output.c | 65 ++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 052751569..68f85ebb2 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -428,6 +428,8 @@ bool wlr_output_commit(struct wlr_output *output); void wlr_output_rollback(struct wlr_output *output); bool wlr_output_test_state(struct wlr_output *output, const struct wlr_output_state *state); +bool wlr_output_commit_state(struct wlr_output *output, + const struct wlr_output_state *state); /** * Manually schedules a `frame` event. If a `frame` event is already pending, * it is a no-op. diff --git a/types/output/output.c b/types/output/output.c index cdfb48ff5..6bcb2b870 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -397,6 +397,12 @@ static void output_state_finish(struct wlr_output_state *state) { free(state->gamma_lut); } +static void output_state_move(struct wlr_output_state *dst, + struct wlr_output_state *src) { + *dst = *src; + output_state_init(src); +} + void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, const struct wlr_output_impl *impl, struct wl_display *display) { assert(impl->commit); @@ -673,7 +679,7 @@ bool wlr_output_test_state(struct wlr_output *output, const struct wlr_output_state *state) { bool had_buffer = state->committed & WLR_OUTPUT_STATE_BUFFER; - // Duplicate the satte because we might mutate it in output_ensure_buffer + // Duplicate the state because we might mutate it in output_ensure_buffer struct wlr_output_state pending = *state; if (!output_basic_test(output, &pending)) { return false; @@ -696,17 +702,20 @@ bool wlr_output_test(struct wlr_output *output) { return wlr_output_test_state(output, &output->pending); } -bool wlr_output_commit(struct wlr_output *output) { - if (!output_basic_test(output, &output->pending)) { +bool wlr_output_commit_state(struct wlr_output *output, + const struct wlr_output_state *state) { + if (!output_basic_test(output, state)) { wlr_log(WLR_ERROR, "Basic output test failed for %s", output->name); return false; } - if (!output_ensure_buffer(output, &output->pending)) { + // Duplicate the state because we might mutate it in output_ensure_buffer + struct wlr_output_state pending = *state; + if (!output_ensure_buffer(output, &pending)) { return false; } - if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) && + if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) && output->idle_frame != NULL) { wl_event_source_remove(output->idle_frame); output->idle_frame = NULL; @@ -718,7 +727,7 @@ bool wlr_output_commit(struct wlr_output *output) { struct wlr_output_event_precommit pre_event = { .output = output, .when = &now, - .state = &output->pending, + .state = &pending, }; wlr_signal_emit_safe(&output->events.precommit, &pre_event); @@ -727,19 +736,18 @@ bool wlr_output_commit(struct wlr_output *output) { // implicit rendering synchronization point. The backend needs it to avoid // displaying a buffer when asynchronous GPU work isn't finished. struct wlr_buffer *back_buffer = NULL; - if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) && + if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) && output->back_buffer != NULL) { back_buffer = wlr_buffer_lock(output->back_buffer); output_clear_back_buffer(output); } - if (!output->impl->commit(output, &output->pending)) { + if (!output->impl->commit(output, &pending)) { wlr_buffer_unlock(back_buffer); - output_state_clear(&output->pending); return false; } - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (pending.committed & WLR_OUTPUT_STATE_BUFFER) { struct wlr_output_cursor *cursor; wl_list_for_each(cursor, &output->cursors, link) { if (!cursor->enabled || !cursor->visible || cursor->surface == NULL) { @@ -749,27 +757,27 @@ bool wlr_output_commit(struct wlr_output *output) { } } - if (output->pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { - output->render_format = output->pending.render_format; + if (pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { + output->render_format = pending.render_format; } - if (output->pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) { - output->subpixel = output->pending.subpixel; + if (pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) { + output->subpixel = pending.subpixel; } output->commit_seq++; - bool scale_updated = output->pending.committed & WLR_OUTPUT_STATE_SCALE; + bool scale_updated = pending.committed & WLR_OUTPUT_STATE_SCALE; if (scale_updated) { - output->scale = output->pending.scale; + output->scale = pending.scale; } - if (output->pending.committed & WLR_OUTPUT_STATE_TRANSFORM) { - output->transform = output->pending.transform; + if (pending.committed & WLR_OUTPUT_STATE_TRANSFORM) { + output->transform = pending.transform; output_update_matrix(output); } - bool geometry_updated = output->pending.committed & + bool geometry_updated = pending.committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SUBPIXEL); if (geometry_updated || scale_updated) { @@ -786,15 +794,14 @@ bool wlr_output_commit(struct wlr_output *output) { } // Destroy the swapchains when an output is disabled - if ((output->pending.committed & WLR_OUTPUT_STATE_ENABLED) && - !output->pending.enabled) { + if ((pending.committed & WLR_OUTPUT_STATE_ENABLED) && !pending.enabled) { wlr_swapchain_destroy(output->swapchain); output->swapchain = NULL; wlr_swapchain_destroy(output->cursor_swapchain); output->cursor_swapchain = NULL; } - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { + if (pending.committed & WLR_OUTPUT_STATE_BUFFER) { output->frame_pending = true; output->needs_frame = false; } @@ -803,12 +810,9 @@ bool wlr_output_commit(struct wlr_output *output) { wlr_swapchain_set_buffer_submitted(output->swapchain, back_buffer); } - uint32_t committed = output->pending.committed; - output_state_clear(&output->pending); - struct wlr_output_event_commit event = { .output = output, - .committed = committed, + .committed = pending.committed, .when = &now, .buffer = back_buffer, }; @@ -821,6 +825,15 @@ bool wlr_output_commit(struct wlr_output *output) { return true; } +bool wlr_output_commit(struct wlr_output *output) { + // Make sure the pending state is cleared before the output is committed + struct wlr_output_state state = {0}; + output_state_move(&state, &output->pending); + bool ok = wlr_output_commit_state(output, &state); + output_state_finish(&state); + return ok; +} + void wlr_output_rollback(struct wlr_output *output) { output_clear_back_buffer(output); output_state_clear(&output->pending); From bb2946f7377b9e71c15457e93f6f9a34712b77de Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 29 May 2022 14:09:06 +0200 Subject: [PATCH 153/298] build: make GBM optional Now that the DRM backend no longer depends on GBM, we can make it optional. The GLES2 renderer still depends on it because of our EGL device selection. This is useful for compositors with their own renderers, and for compositors using the Vulkan renderer. --- README.md | 2 +- examples/meson.build | 1 + include/wlr/config.h.in | 3 ++- meson.build | 3 +-- meson_options.txt | 2 ++ render/allocator/allocator.c | 9 ++++++++- render/allocator/meson.build | 22 +++++++++++++++++++--- render/gles2/renderer.c | 1 - render/meson.build | 5 +++-- 9 files changed, 37 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 418aab94b..7fbd691a0 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Install dependencies: * EGL and GLESv2 (optional, for the GLES2 renderer) * Vulkan loader, headers and glslang (optional, for the Vulkan renderer) * libdrm -* GBM +* GBM (optional, for the GBM allocator) * libinput (optional, for the libinput backend) * xkbcommon * udev diff --git a/examples/meson.build b/examples/meson.build index 26d103bbb..51e7d3117 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -5,6 +5,7 @@ wayland_client = dependency('wayland-client') libpng = dependency('libpng', required: false, disabler: true) egl = dependency('egl', required: false, disabler: true) glesv2 = dependency('glesv2', required: false, disabler: true) +gbm = dependency('gbm', required: false, disabler: true) # These versions correspond to ffmpeg 4.0 libavutil = dependency('libavutil', version: '>=56.14.100', required: false, disabler: true) libavcodec = dependency('libavcodec', version: '>=58.18.100', required: false, disabler: true) diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in index 71868a349..0b612271c 100644 --- a/include/wlr/config.h.in +++ b/include/wlr/config.h.in @@ -6,9 +6,10 @@ #mesondefine WLR_HAS_X11_BACKEND #mesondefine WLR_HAS_GLES2_RENDERER - #mesondefine WLR_HAS_VULKAN_RENDERER +#mesondefine WLR_HAS_GBM_ALLOCATOR + #mesondefine WLR_HAS_XWAYLAND #endif diff --git a/meson.build b/meson.build index 5d45073de..971be7e63 100644 --- a/meson.build +++ b/meson.build @@ -92,6 +92,7 @@ features = { 'xwayland': false, 'gles2-renderer': false, 'vulkan-renderer': false, + 'gbm-allocator': false, } internal_features = { 'xcb-errors': false, @@ -125,7 +126,6 @@ drm = dependency('libdrm', 'valgrind=false', ], ) -gbm = dependency('gbm', version: '>=17.1.0') xkbcommon = dependency('xkbcommon') udev = dependency('libudev') pixman = dependency('pixman-1') @@ -136,7 +136,6 @@ wlr_files = [] wlr_deps = [ wayland_server, drm, - gbm, xkbcommon, udev, pixman, diff --git a/meson_options.txt b/meson_options.txt index 550acbe6f..1a439a4d8 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -4,3 +4,5 @@ option('examples', type: 'boolean', value: true, description: 'Build example app option('icon_directory', description: 'Location used to look for cursors (default: ${datadir}/icons)', type: 'string', value: '') option('renderers', type: 'array', choices: ['auto', 'gles2', 'vulkan'], value: ['auto'], description: 'Select built-in renderers') option('backends', type: 'array', choices: ['auto', 'drm', 'libinput', 'x11'], value: ['auto'], description: 'Select built-in backends') +option('allocators', type: 'array', choices: ['auto', 'gbm'], value: ['auto'], + description: 'Select built-in allocators') diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 83e836aee..6b96e0239 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -11,10 +12,13 @@ #include "backend/backend.h" #include "render/allocator/allocator.h" #include "render/allocator/drm_dumb.h" -#include "render/allocator/gbm.h" #include "render/allocator/shm.h" #include "render/wlr_renderer.h" +#if WLR_HAS_GBM_ALLOCATOR +#include "render/allocator/gbm.h" +#endif + void wlr_allocator_init(struct wlr_allocator *alloc, const struct wlr_allocator_interface *impl, uint32_t buffer_caps) { assert(impl && impl->destroy && impl->create_buffer); @@ -94,6 +98,8 @@ struct wlr_allocator *allocator_autocreate_with_drm_fd( uint32_t renderer_caps = renderer_get_render_buffer_caps(renderer); struct wlr_allocator *alloc = NULL; + +#if WLR_HAS_GBM_ALLOCATOR uint32_t gbm_caps = WLR_BUFFER_CAP_DMABUF; if ((backend_caps & gbm_caps) && (renderer_caps & gbm_caps) && drm_fd >= 0) { @@ -108,6 +114,7 @@ struct wlr_allocator *allocator_autocreate_with_drm_fd( close(gbm_fd); wlr_log(WLR_DEBUG, "Failed to create gbm allocator"); } +#endif uint32_t shm_caps = WLR_BUFFER_CAP_SHM | WLR_BUFFER_CAP_DATA_PTR; if ((backend_caps & shm_caps) && (renderer_caps & shm_caps)) { diff --git a/render/allocator/meson.build b/render/allocator/meson.build index db17ccb2c..f8e452df9 100644 --- a/render/allocator/meson.build +++ b/render/allocator/meson.build @@ -1,9 +1,25 @@ +allocators = get_option('allocators') +if 'auto' in allocators and get_option('auto_features').enabled() + allocators = ['gbm'] +elif 'auto' in renderers and get_option('auto_features').disabled() + allocators = [] +endif + wlr_files += files( 'allocator.c', - 'gbm.c', 'shm.c', 'drm_dumb.c', ) -has = cc.has_function('gbm_bo_get_fd_for_plane', dependencies: [gbm]) -add_project_arguments('-DHAS_GBM_BO_GET_FD_FOR_PLANE=@0@'.format(has.to_int()), language: 'c') +gbm = disabler() +if 'gbm' in allocators or 'auto' in allocators + gbm = dependency('gbm', version: '>=17.1.0', required: 'gbm' in allocators) +endif +if gbm.found() + wlr_files += files('gbm.c') + wlr_deps += gbm + features += { 'gbm-allocator': true } + + has = cc.has_function('gbm_bo_get_fd_for_plane', dependencies: [gbm]) + add_project_arguments('-DHAS_GBM_BO_GET_FD_FOR_PLANE=@0@'.format(has.to_int()), language: 'c') +endif diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 5ffd6f85f..e7bfe0e00 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/render/meson.build b/render/meson.build index a1289edee..2bdcced8f 100644 --- a/render/meson.build +++ b/render/meson.build @@ -16,8 +16,9 @@ wlr_files += files( if 'gles2' in renderers or 'auto' in renderers egl = dependency('egl', required: 'gles2' in renderers) - if egl.found() - wlr_deps += egl + gbm = dependency('gbm', required: 'gles2' in renderers) + if egl.found() and gbm.found() + wlr_deps += [egl, gbm] wlr_files += files('egl.c') endif subdir('gles2') From 988fe5bda9c11c4b2a25e998bd0329c70cc487a0 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Fri, 27 May 2022 20:47:34 +0200 Subject: [PATCH 154/298] relative_pointer: handle inert pointer objects Since 5e0ef70cc085 ("seat: Create inert objects for missing capabilities") wlroots can create inert seat objects when the capability is currently missing for the client but it had the capablity before. The client hoever will happily handover the wl_pointer resource to the relative_pointer implementation, creating a NULL pointer dereference when trying to access the seat_client which is set to NULL for inert objects. Since the protocol does not contain an error for such requests, we hand out an relative_pointer handle with the seat set to NULL. We also need to check whether there is an associated seat in send_relative_motion and need to tweak the destroy notifier in case no seat is available. This way we can hand out a valid relative_pointer resource and don't crash the compositor when trying to access an inert seat pointer resource in relative_pointer. Relevant WAYLAND_DEBUG=1 when testing a client and switching VT every second: [2619872.442] wl_seat@30.capabilities(3) [2619872.460] -> wl_seat@30.get_pointer(new id wl_pointer@36) [2619872.484] wl_data_device@25.selection(nil) [2619872.504] zwp_primary_selection_device_v1@26.selection(nil) [2619874.995] wl_seat@12.capabilities(3) [2619875.035] -> wl_compositor@5.create_surface(new id wl_surface@37) [2619875.088] -> wl_seat@12.get_pointer(new id wl_pointer@29) [2619875.105] -> zwp_relative_pointer_manager_v1@8.get_relative_pointer(new id zwp_relative_pointer_v1@27, wl_pointer@29) [2619875.127] -> wl_compositor@5.create_surface(new id wl_surface@35) [2619875.139] -> wl_seat@12.get_pointer(new id wl_pointer@43) [2619981.180] wl_seat@12.capabilities(2) [2619981.214] -> zwp_relative_pointer_v1@27.destroy() [2619981.226] -> wl_pointer@29.release() [2619981.236] -> wl_surface@37.destroy() [2619981.247] -> wl_pointer@43.release() [2619981.254] -> wl_surface@35.destroy() [2619981.262] wl_seat@12.capabilities(0) [2619981.285] -> wl_keyboard@33.release() [2619987.316] wl_seat@30.capabilities(2) [2619987.336] -> wl_pointer@36.release() [2619987.363] wl_seat@30.capabilities(0) [2619987.371] -> wl_keyboard@34.release() [2621932.880] wl_display@1.delete_id(41) [2621932.903] wl_display@1.delete_id(40) [2621932.910] wl_display@1.delete_id(27) [2621932.917] wl_display@1.delete_id(29) [2621932.924] wl_display@1.delete_id(37) [2621932.930] wl_display@1.delete_id(43) [2621932.944] wl_display@1.delete_id(35) [2621932.950] wl_display@1.delete_id(33) [2621932.959] wl_seat@12.capabilities(2) [2621932.976] -> wl_seat@12.get_keyboard(new id wl_keyboard@33) [2621936.875] wl_seat@12.capabilities(3) [2621936.893] -> wl_compositor@5.create_surface(new id wl_surface@35) [2621936.931] -> wl_seat@12.get_pointer(new id wl_pointer@43) [2621936.945] -> zwp_relative_pointer_manager_v1@8.get_relative_pointer(new id zwp_relative_pointer_v1@37, wl_pointer@43) [2621936.965] -> wl_compositor@5.create_surface(new id wl_surface@29) [2621936.987] -> wl_seat@12.get_pointer(new id wl_pointer@27) [2621942.796] wl_data_device@25.selection(nil) [2621942.817] zwp_primary_selection_device_v1@26.selection(nil) [2621942.823] wl_seat@30.capabilities(2) --- types/wlr_relative_pointer_v1.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index 8613f2b91..0c3d3829f 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -117,9 +117,17 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl } relative_pointer->resource = relative_pointer_resource; - relative_pointer->seat = seat_client->seat; relative_pointer->pointer_resource = pointer; + if (seat_client) { + relative_pointer->seat = seat_client->seat; + wl_signal_add(&relative_pointer->seat->events.destroy, + &relative_pointer->seat_destroy); + relative_pointer->seat_destroy.notify = relative_pointer_handle_seat_destroy; + } else { + wl_list_init(&relative_pointer->seat_destroy.link); + } + wl_signal_init(&relative_pointer->events.destroy); wl_resource_set_implementation(relative_pointer_resource, &relative_pointer_v1_impl, @@ -131,10 +139,6 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl wl_list_insert(&manager->relative_pointers, &relative_pointer->link); - wl_signal_add(&relative_pointer->seat->events.destroy, - &relative_pointer->seat_destroy); - relative_pointer->seat_destroy.notify = relative_pointer_handle_seat_destroy; - wl_resource_add_destroy_listener(relative_pointer->pointer_resource, &relative_pointer->pointer_destroy); relative_pointer->pointer_destroy.notify = relative_pointer_handle_pointer_destroy; @@ -230,7 +234,7 @@ void wlr_relative_pointer_manager_v1_send_relative_motion( wl_list_for_each(pointer, &manager->relative_pointers, link) { struct wlr_seat_client *seat_client = wlr_seat_client_from_pointer_resource(pointer->pointer_resource); - if (seat != pointer->seat || focused != seat_client) { + if (!pointer->seat || seat != pointer->seat || focused != seat_client) { continue; } From 98c5f58a388926c3db5d5b4b9275645bccd54271 Mon Sep 17 00:00:00 2001 From: Consolatis <40171-Consolatis@users.noreply.gitlab.freedesktop.org> Date: Mon, 30 May 2022 17:31:47 +0200 Subject: [PATCH 155/298] wlr_scene: Fix scaling with default source_box Default to texture instead of destination_box geometry. --- types/scene/wlr_scene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 676fe1270..86eb2bf00 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -801,8 +801,8 @@ static void render_texture(struct wlr_output *output, struct wlr_fbox default_src_box = {0}; if (wlr_fbox_empty(src_box)) { - default_src_box.width = dst_box->width; - default_src_box.height = dst_box->height; + default_src_box.width = texture->width; + default_src_box.height = texture->height; src_box = &default_src_box; } From 17fbf60bd1878ae81f4cfdbe67bed62dea621a63 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 30 May 2022 16:17:25 +0200 Subject: [PATCH 156/298] relative-pointer-v1: remove unnecessary comments We don't do this in other implementations, so it feels out of place. --- types/wlr_relative_pointer_v1.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index 0c3d3829f..ddd399746 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -14,29 +14,18 @@ static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager_v1_impl; static const struct zwp_relative_pointer_v1_interface relative_pointer_v1_impl; - -/** - * helper functions - */ - struct wlr_relative_pointer_v1 *wlr_relative_pointer_v1_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwp_relative_pointer_v1_interface, &relative_pointer_v1_impl)); return wl_resource_get_user_data(resource); } - static struct wlr_relative_pointer_manager_v1 *relative_pointer_manager_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwp_relative_pointer_manager_v1_interface, &relative_pointer_manager_v1_impl)); return wl_resource_get_user_data(resource); } - -/** - * relative_pointer handler functions - */ - static void relative_pointer_destroy(struct wlr_relative_pointer_v1 *relative_pointer) { wlr_signal_emit_safe(&relative_pointer->events.destroy, relative_pointer); @@ -57,7 +46,6 @@ static void relative_pointer_v1_handle_resource_destroy(struct wl_resource *reso relative_pointer_destroy(relative_pointer); } - static void relative_pointer_v1_handle_destroy(struct wl_client *client, struct wl_resource *resource) { struct wlr_relative_pointer_v1 *relative_pointer = @@ -84,10 +72,6 @@ static void relative_pointer_handle_pointer_destroy(struct wl_listener *listener relative_pointer_destroy(relative_pointer); } -/** - * relative_pointer_manager handler functions - */ - static void relative_pointer_manager_v1_handle_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); @@ -150,7 +134,6 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl relative_pointer, client); } - static void relative_pointer_manager_v1_bind(struct wl_client *wl_client, void *data, uint32_t version, uint32_t id) { struct wlr_relative_pointer_manager_v1 *manager = data; @@ -175,26 +158,15 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { free(manager); } - -/** - * Implementations - */ - static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager_v1_impl = { .destroy = relative_pointer_manager_v1_handle_destroy, .get_relative_pointer = relative_pointer_manager_v1_handle_get_relative_pointer, }; - static const struct zwp_relative_pointer_v1_interface relative_pointer_v1_impl = { .destroy = relative_pointer_v1_handle_destroy, }; - -/** - * Public functions - */ - struct wlr_relative_pointer_manager_v1 *wlr_relative_pointer_manager_v1_create(struct wl_display *display) { struct wlr_relative_pointer_manager_v1 *manager = calloc(1, sizeof(struct wlr_relative_pointer_manager_v1)); From 1feb8edd2177de50579f65f5a28bf8766cce3fbd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 30 May 2022 16:42:12 +0200 Subject: [PATCH 157/298] relative-pointer-v1: remove unnecessary log messages Logging when a client creates or destroys an object is a bit too chatty. --- types/wlr_relative_pointer_v1.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index ddd399746..0a230b60a 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -48,11 +48,6 @@ static void relative_pointer_v1_handle_resource_destroy(struct wl_resource *reso static void relative_pointer_v1_handle_destroy(struct wl_client *client, struct wl_resource *resource) { - struct wlr_relative_pointer_v1 *relative_pointer = - wlr_relative_pointer_v1_from_resource(resource); - wlr_log(WLR_DEBUG, "relative_pointer_v1 %p released by client %p", - relative_pointer, client); - wl_resource_destroy(resource); } @@ -75,9 +70,6 @@ static void relative_pointer_handle_pointer_destroy(struct wl_listener *listener static void relative_pointer_manager_v1_handle_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); - - wlr_log(WLR_DEBUG, "relative_pointer_v1 manager unbound from client %p", - client); } static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_client *client, @@ -129,9 +121,6 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl wlr_signal_emit_safe(&manager->events.new_relative_pointer, relative_pointer); - - wlr_log(WLR_DEBUG, "relative_pointer_v1 %p created for client %p", - relative_pointer, client); } static void relative_pointer_manager_v1_bind(struct wl_client *wl_client, void *data, From 43020963d400c8aec0bd24896aab30825fee33e5 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 30 May 2022 16:54:53 +0200 Subject: [PATCH 158/298] relative-pointer-v1: don't allocate when inert When the wl_pointer the zwp_relative_pointer_v1 is created with is inert, don't allocate any struct, just leave the resource's data pointer NULL. --- types/wlr_relative_pointer_v1.c | 45 ++++++++++++++++----------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index 0a230b60a..50871b51e 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -74,9 +74,25 @@ static void relative_pointer_manager_v1_handle_destroy(struct wl_client *client, static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *pointer) { + struct wlr_relative_pointer_manager_v1 *manager = + relative_pointer_manager_from_resource(resource); struct wlr_seat_client *seat_client = wlr_seat_client_from_pointer_resource(pointer); + struct wl_resource *relative_pointer_resource = wl_resource_create(client, + &zwp_relative_pointer_v1_interface, wl_resource_get_version(resource), id); + if (relative_pointer_resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(relative_pointer_resource, &relative_pointer_v1_impl, + NULL, relative_pointer_v1_handle_resource_destroy); + + if (seat_client == NULL) { + // Leave the resource inert + return; + } + struct wlr_relative_pointer_v1 *relative_pointer = calloc(1, sizeof(struct wlr_relative_pointer_v1)); if (relative_pointer == NULL) { @@ -84,36 +100,19 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl return; } - struct wl_resource *relative_pointer_resource = wl_resource_create(client, - &zwp_relative_pointer_v1_interface, wl_resource_get_version(resource), id); - if (relative_pointer_resource == NULL) { - free(relative_pointer); - wl_client_post_no_memory(client); - return; - } - relative_pointer->resource = relative_pointer_resource; relative_pointer->pointer_resource = pointer; - if (seat_client) { - relative_pointer->seat = seat_client->seat; - wl_signal_add(&relative_pointer->seat->events.destroy, - &relative_pointer->seat_destroy); - relative_pointer->seat_destroy.notify = relative_pointer_handle_seat_destroy; - } else { - wl_list_init(&relative_pointer->seat_destroy.link); - } + relative_pointer->seat = seat_client->seat; + wl_signal_add(&relative_pointer->seat->events.destroy, + &relative_pointer->seat_destroy); + relative_pointer->seat_destroy.notify = relative_pointer_handle_seat_destroy; wl_signal_init(&relative_pointer->events.destroy); - wl_resource_set_implementation(relative_pointer_resource, &relative_pointer_v1_impl, - relative_pointer, relative_pointer_v1_handle_resource_destroy); + wl_resource_set_user_data(relative_pointer_resource, relative_pointer); - struct wlr_relative_pointer_manager_v1 *manager = - relative_pointer_manager_from_resource(resource); - - wl_list_insert(&manager->relative_pointers, - &relative_pointer->link); + wl_list_insert(&manager->relative_pointers, &relative_pointer->link); wl_resource_add_destroy_listener(relative_pointer->pointer_resource, &relative_pointer->pointer_destroy); From 2563b79dc2c200899316d5659b0dd00ca26460b8 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 14:54:43 +0200 Subject: [PATCH 159/298] backend/drm: improve atomic commit flag logging We weren't logging all of the flags, which made debugging more difficult. --- backend/drm/atomic.c | 45 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 534879143..cacb8e87a 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -1,4 +1,6 @@ +#define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -6,6 +8,41 @@ #include "backend/drm/iface.h" #include "backend/drm/util.h" +static char *atomic_commit_flags_str(uint32_t flags) { + const char *const l[] = { + (flags & DRM_MODE_PAGE_FLIP_EVENT) ? "PAGE_FLIP_EVENT" : NULL, + (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? "PAGE_FLIP_ASYNC" : NULL, + (flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "ATOMIC_TEST_ONLY" : NULL, + (flags & DRM_MODE_ATOMIC_NONBLOCK) ? "ATOMIC_NONBLOCK" : NULL, + (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) ? "ATOMIC_ALLOW_MODESET" : NULL, + }; + + char *buf = NULL; + size_t size = 0; + FILE *f = open_memstream(&buf, &size); + if (f == NULL) { + return NULL; + } + + for (size_t i = 0; i < sizeof(l) / sizeof(l[0]); i++) { + if (l[i] == NULL) { + continue; + } + if (ftell(f) > 0) { + fprintf(f, " | "); + } + fprintf(f, "%s", l[i]); + } + + if (ftell(f) == 0) { + fprintf(f, "none"); + } + + fclose(f); + + return buf; +} + struct atomic { drmModeAtomicReq *req; bool failed; @@ -33,9 +70,11 @@ static bool atomic_commit(struct atomic *atom, if (ret != 0) { wlr_drm_conn_log_errno(conn, (flags & DRM_MODE_ATOMIC_TEST_ONLY) ? WLR_DEBUG : WLR_ERROR, - "Atomic %s failed (%s)", - (flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "test" : "commit", - (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) ? "modeset" : "pageflip"); + "Atomic commit failed"); + char *flags_str = atomic_commit_flags_str(flags); + wlr_log(WLR_DEBUG, "(Atomic commit flags: %s)", + flags_str ? flags_str : ""); + free(flags_str); return false; } From 9eb71146ae56c509ee33c7e8a662549592aad870 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 30 May 2022 19:26:08 -0400 Subject: [PATCH 160/298] wlr_scene: Refactor wlr_scene (the root element) to encase a wlr_scene_tree Co-authored-by: Isaac Freund --- examples/scene-graph.c | 4 +- include/wlr/types/wlr_scene.h | 13 +++--- tinywl/tinywl.c | 4 +- types/scene/output_layout.c | 2 +- types/scene/wlr_scene.c | 87 ++++++++++++++++++----------------- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 98f98cfd4..ac8ea5c34 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -122,12 +122,12 @@ static void server_handle_new_surface(struct wl_listener *listener, wl_signal_add(&wlr_surface->events.destroy, &surface->destroy); /* Border dimensions will be set in surface.commit handler */ - surface->border = wlr_scene_rect_create(&server->scene->node, + surface->border = wlr_scene_rect_create(&server->scene->tree.node, 0, 0, (float[4]){ 0.5f, 0.5f, 0.5f, 1 }); wlr_scene_node_set_position(&surface->border->node, pos, pos); surface->scene_surface = - wlr_scene_surface_create(&server->scene->node, wlr_surface); + wlr_scene_surface_create(&server->scene->tree.node, wlr_surface); wlr_scene_node_set_position(&surface->scene_surface->buffer->node, pos + border_width, pos + border_width); diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 0e3857d5b..9af0f25cb 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -41,7 +41,6 @@ typedef void (*wlr_scene_buffer_iterator_func_t)( struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data); enum wlr_scene_node_type { - WLR_SCENE_NODE_ROOT, WLR_SCENE_NODE_TREE, WLR_SCENE_NODE_RECT, WLR_SCENE_NODE_BUFFER, @@ -77,9 +76,14 @@ enum wlr_scene_debug_damage_option { WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT }; +/** A sub-tree in the scene-graph. */ +struct wlr_scene_tree { + struct wlr_scene_node node; +}; + /** The root scene-graph node. */ struct wlr_scene { - struct wlr_scene_node node; + struct wlr_scene_tree tree; struct wl_list outputs; // wlr_scene_output.link @@ -94,11 +98,6 @@ struct wlr_scene { struct wl_list damage_highlight_regions; }; -/** A sub-tree in the scene-graph. */ -struct wlr_scene_tree { - struct wlr_scene_node node; -}; - /** A scene-graph node displaying a single surface. */ struct wlr_scene_surface { struct wlr_scene_buffer *buffer; diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index d8e171e15..49d33b421 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -340,7 +340,7 @@ static struct tinywl_view *desktop_view_at( * we only care about surface nodes as we are specifically looking for a * surface in the surface tree of a tinywl_view. */ struct wlr_scene_node *node = wlr_scene_node_at( - &server->scene->node, lx, ly, sx, sy); + &server->scene->tree.node, lx, ly, sx, sy); if (node == NULL || node->type != WLR_SCENE_NODE_BUFFER) { return NULL; } @@ -760,7 +760,7 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { view->server = server; view->xdg_toplevel = xdg_surface->toplevel; view->scene_node = wlr_scene_xdg_surface_create( - &view->server->scene->node, view->xdg_toplevel->base); + &view->server->scene->tree.node, view->xdg_toplevel->base); view->scene_node->data = view; xdg_surface->data = view->scene_node; diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c index b80759ff1..e2327eb99 100644 --- a/types/scene/output_layout.c +++ b/types/scene/output_layout.c @@ -99,7 +99,7 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, wl_signal_add(&output_layout->events.add, &sol->layout_add); sol->scene_destroy.notify = scene_output_layout_handle_scene_destroy; - wl_signal_add(&scene->node.events.destroy, &sol->scene_destroy); + wl_signal_add(&scene->tree.node.events.destroy, &sol->scene_destroy); return true; } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 86eb2bf00..410fbe3b8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -17,11 +17,6 @@ #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 -static struct wlr_scene *scene_root_from_node(struct wlr_scene_node *node) { - assert(node->type == WLR_SCENE_NODE_ROOT); - return (struct wlr_scene *)node; -} - static struct wlr_scene_rect *scene_rect_from_node( struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_RECT); @@ -38,7 +33,7 @@ struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { while (node->parent != NULL) { node = node->parent; } - return scene_root_from_node(node); + return (struct wlr_scene *)node; } static void scene_node_state_init(struct wlr_scene_node_state *state) { @@ -54,8 +49,6 @@ static void scene_node_state_finish(struct wlr_scene_node_state *state) { static void scene_node_init(struct wlr_scene_node *node, enum wlr_scene_node_type type, struct wlr_scene_node *parent) { - assert(type == WLR_SCENE_NODE_ROOT || parent != NULL); - memset(node, 0, sizeof(*node)); node->type = type; node->parent = parent; @@ -96,26 +89,12 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_signal_emit_safe(&node->events.destroy, NULL); struct wlr_scene *scene = scene_node_get_root(node); - struct wlr_scene_output *scene_output; - switch (node->type) { - case WLR_SCENE_NODE_ROOT:; - struct wlr_scene_output *scene_output_tmp; - wl_list_for_each_safe(scene_output, scene_output_tmp, &scene->outputs, link) { - wlr_scene_output_destroy(scene_output); - } - - struct highlight_region *damage, *tmp_damage; - wl_list_for_each_safe(damage, tmp_damage, &scene->damage_highlight_regions, link) { - highlight_region_destroy(damage); - } - - wl_list_remove(&scene->presentation_destroy.link); - break; - case WLR_SCENE_NODE_BUFFER:; + if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); uint64_t active = scene_buffer->active_outputs; if (active) { + struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { if (active & (1ull << scene_output->index)) { wlr_signal_emit_safe(&scene_buffer->events.output_leave, @@ -126,10 +105,23 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_texture_destroy(scene_buffer->texture); wlr_buffer_unlock(scene_buffer->buffer); - break; - case WLR_SCENE_NODE_TREE: - case WLR_SCENE_NODE_RECT: - break; + } else if (node->type == WLR_SCENE_NODE_TREE) { + if (node == &scene->tree.node) { + assert(!node->parent); + struct wlr_scene_output *scene_output, *scene_output_tmp; + wl_list_for_each_safe(scene_output, scene_output_tmp, &scene->outputs, link) { + wlr_scene_output_destroy(scene_output); + } + + struct highlight_region *damage, *tmp_damage; + wl_list_for_each_safe(damage, tmp_damage, &scene->damage_highlight_regions, link) { + highlight_region_destroy(damage); + } + + wl_list_remove(&scene->presentation_destroy.link); + } else { + assert(node->parent); + } } struct wlr_scene_node *child, *child_tmp; @@ -143,12 +135,20 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { free(node); } +static void scene_tree_init(struct wlr_scene_tree *tree, + struct wlr_scene_node *parent) { + memset(tree, 0, sizeof(*tree)); + scene_node_init(&tree->node, WLR_SCENE_NODE_TREE, parent); +} + struct wlr_scene *wlr_scene_create(void) { struct wlr_scene *scene = calloc(1, sizeof(struct wlr_scene)); if (scene == NULL) { return NULL; } - scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL); + + scene_tree_init(&scene->tree, NULL); + wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); wl_list_init(&scene->damage_highlight_regions); @@ -173,12 +173,14 @@ struct wlr_scene *wlr_scene_create(void) { } struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent) { + assert(parent); + struct wlr_scene_tree *tree = calloc(1, sizeof(struct wlr_scene_tree)); if (tree == NULL) { return NULL; } - scene_node_init(&tree->node, WLR_SCENE_NODE_TREE, parent); + scene_tree_init(tree, parent); return tree; } @@ -256,6 +258,7 @@ struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, if (scene_rect == NULL) { return NULL; } + assert(parent); scene_node_init(&scene_rect->node, WLR_SCENE_NODE_RECT, parent); scene_rect->width = width; @@ -293,6 +296,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, if (scene_buffer == NULL) { return NULL; } + assert(parent); scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent); if (buffer) { @@ -473,7 +477,6 @@ static void scene_node_get_size(struct wlr_scene_node *node, *height = 0; switch (node->type) { - case WLR_SCENE_NODE_ROOT: case WLR_SCENE_NODE_TREE: return; case WLR_SCENE_NODE_RECT:; @@ -630,7 +633,7 @@ void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) { void wlr_scene_node_reparent(struct wlr_scene_node *node, struct wlr_scene_node *new_parent) { - assert(node->type != WLR_SCENE_NODE_ROOT && new_parent != NULL); + assert(new_parent != NULL); if (node->parent == new_parent) { return; @@ -716,7 +719,6 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, bool intersects = false; switch (node->type) { - case WLR_SCENE_NODE_ROOT: case WLR_SCENE_NODE_TREE: break; case WLR_SCENE_NODE_RECT:; @@ -845,7 +847,6 @@ static void render_node_iterator(struct wlr_scene_node *node, float matrix[9]; enum wl_output_transform transform; switch (node->type) { - case WLR_SCENE_NODE_ROOT: case WLR_SCENE_NODE_TREE: /* Root or tree node has nothing to render itself */ break; @@ -933,14 +934,14 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data) if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { - scene_node_update_outputs(&scene_output->scene->node); + scene_node_update_outputs(&scene_output->scene->tree.node); } } static void scene_output_handle_mode(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wl_container_of(listener, scene_output, output_mode); - scene_node_update_outputs(&scene_output->scene->node); + scene_node_update_outputs(&scene_output->scene->tree.node); } struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, @@ -984,7 +985,7 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, wl_signal_add(&output->events.mode, &scene_output->output_mode); wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene->node); + scene_node_update_outputs(&scene->tree.node); return scene_output; } @@ -1012,7 +1013,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { return; } - scene_node_remove_output(&scene_output->scene->node, scene_output); + scene_node_remove_output(&scene_output->scene->tree.node, scene_output); wlr_addon_finish(&scene_output->addon); wl_list_remove(&scene_output->link); @@ -1044,7 +1045,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output->y = ly; wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene_output->scene->node); + scene_node_update_outputs(&scene_output->scene->tree.node); } struct check_scanout_data { @@ -1094,7 +1095,7 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { struct check_scanout_data check_scanout_data = { .viewport_box = viewport_box, }; - scene_node_for_each_node(&scene_output->scene->node, 0, 0, + scene_node_for_each_node(&scene_output->scene->tree.node, 0, 0, check_scanout_iterator, &check_scanout_data); if (check_scanout_data.n != 1 || check_scanout_data.node == NULL) { return false; @@ -1222,7 +1223,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { .scene_output = scene_output, .damage = &damage, }; - scene_node_for_each_node(&scene_output->scene->node, + scene_node_for_each_node(&scene_output->scene->tree.node, -scene_output->x, -scene_output->y, render_node_iterator, &data); wlr_renderer_scissor(renderer, NULL); @@ -1302,7 +1303,7 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, struct timespec *now) { - scene_node_send_frame_done(&scene_output->scene->node, + scene_node_send_frame_done(&scene_output->scene->tree.node, scene_output, now); } @@ -1340,6 +1341,6 @@ void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, struct wlr_box box = { .x = scene_output->x, .y = scene_output->y }; wlr_output_effective_resolution(scene_output->output, &box.width, &box.height); - scene_output_for_each_scene_buffer(&box, &scene_output->scene->node, 0, 0, + scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0, iterator, user_data); } From ccd0f85c2a36308e35b153c7f9653abac7659af3 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 30 May 2022 19:23:27 -0400 Subject: [PATCH 161/298] wlr_scene: Only allow parenting on a wlr_scene_tree --- examples/scene-graph.c | 4 +-- include/wlr/types/wlr_scene.h | 24 ++++++++-------- tinywl/tinywl.c | 27 +++++++++--------- types/scene/layer_shell_v1.c | 27 +++++++++--------- types/scene/subsurface_tree.c | 14 ++++----- types/scene/surface.c | 2 +- types/scene/wlr_scene.c | 54 +++++++++++++++++++++++------------ types/scene/xdg_shell.c | 16 +++++------ 8 files changed, 93 insertions(+), 75 deletions(-) diff --git a/examples/scene-graph.c b/examples/scene-graph.c index ac8ea5c34..ba5d2d756 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -122,12 +122,12 @@ static void server_handle_new_surface(struct wl_listener *listener, wl_signal_add(&wlr_surface->events.destroy, &surface->destroy); /* Border dimensions will be set in surface.commit handler */ - surface->border = wlr_scene_rect_create(&server->scene->tree.node, + surface->border = wlr_scene_rect_create(&server->scene->tree, 0, 0, (float[4]){ 0.5f, 0.5f, 0.5f, 1 }); wlr_scene_node_set_position(&surface->border->node, pos, pos); surface->scene_surface = - wlr_scene_surface_create(&server->scene->tree.node, wlr_surface); + wlr_scene_surface_create(&server->scene->tree, wlr_surface); wlr_scene_node_set_position(&surface->scene_surface->buffer->node, pos + border_width, pos + border_width); diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 9af0f25cb..aed617f9f 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -58,7 +58,7 @@ struct wlr_scene_node_state { /** A node is an object in the scene. */ struct wlr_scene_node { enum wlr_scene_node_type type; - struct wlr_scene_node *parent; + struct wlr_scene_tree *parent; struct wlr_scene_node_state state; struct { @@ -178,7 +178,7 @@ struct wlr_scene_output { /** A layer shell scene helper */ struct wlr_scene_layer_surface_v1 { - struct wlr_scene_node *node; + struct wlr_scene_tree *tree; struct wlr_layer_surface_v1 *layer_surface; // private state @@ -226,7 +226,7 @@ void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node); * Move the node to another location in the tree. */ void wlr_scene_node_reparent(struct wlr_scene_node *node, - struct wlr_scene_node *new_parent); + struct wlr_scene_tree *new_parent); /** * Get the node's layout-local coordinates. * @@ -265,7 +265,7 @@ void wlr_scene_set_presentation(struct wlr_scene *scene, /** * Add a node displaying nothing but its children. */ -struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent); +struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent); /** * Add a node displaying a single surface to the scene-graph. @@ -276,7 +276,7 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent); * automatically based on the position of the surface and outputs in * the scene. */ -struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, +struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent, struct wlr_surface *surface); struct wlr_scene_buffer *wlr_scene_buffer_from_node(struct wlr_scene_node *node); @@ -291,7 +291,7 @@ struct wlr_scene_surface *wlr_scene_surface_from_buffer( /** * Add a node displaying a solid-colored rectangle to the scene-graph. */ -struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, +struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, int width, int height, const float color[static 4]); /** @@ -309,7 +309,7 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta * * If the buffer is NULL, this node will not be displayed. */ -struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, +struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, struct wlr_buffer *buffer); /** @@ -415,8 +415,8 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, * Add a node displaying a surface and all of its sub-surfaces to the * scene-graph. */ -struct wlr_scene_node *wlr_scene_subsurface_tree_create( - struct wlr_scene_node *parent, struct wlr_surface *surface); +struct wlr_scene_tree *wlr_scene_subsurface_tree_create( + struct wlr_scene_tree *parent, struct wlr_surface *surface); /** * Add a node displaying an xdg_surface and all of its sub-surfaces to the @@ -425,8 +425,8 @@ struct wlr_scene_node *wlr_scene_subsurface_tree_create( * The origin of the returned scene-graph node will match the top-left corner * of the xdg_surface window geometry. */ -struct wlr_scene_node *wlr_scene_xdg_surface_create( - struct wlr_scene_node *parent, struct wlr_xdg_surface *xdg_surface); +struct wlr_scene_tree *wlr_scene_xdg_surface_create( + struct wlr_scene_tree *parent, struct wlr_xdg_surface *xdg_surface); /** * Add a node displaying a layer_surface_v1 and all of its sub-surfaces to the @@ -436,7 +436,7 @@ struct wlr_scene_node *wlr_scene_xdg_surface_create( * of the layer surface. */ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( - struct wlr_scene_node *parent, struct wlr_layer_surface_v1 *layer_surface); + struct wlr_scene_tree *parent, struct wlr_layer_surface_v1 *layer_surface); /** * Configure a layer_surface_v1, position its scene node in accordance to its diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 49d33b421..f96fe7919 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -80,7 +80,7 @@ struct tinywl_view { struct wl_list link; struct tinywl_server *server; struct wlr_xdg_toplevel *xdg_toplevel; - struct wlr_scene_node *scene_node; + struct wlr_scene_tree *scene_tree; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; @@ -126,7 +126,7 @@ static void focus_view(struct tinywl_view *view, struct wlr_surface *surface) { } struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat); /* Move the view to the front */ - wlr_scene_node_raise_to_top(view->scene_node); + wlr_scene_node_raise_to_top(&view->scene_tree->node); wl_list_remove(&view->link); wl_list_insert(&server->views, &view->link); /* Activate the new surface */ @@ -354,10 +354,11 @@ static struct tinywl_view *desktop_view_at( *surface = scene_surface->surface; /* Find the node corresponding to the tinywl_view at the root of this * surface tree, it is the only one for which we set the data field. */ - while (node != NULL && node->data == NULL) { - node = node->parent; + struct wlr_scene_tree *tree = node->parent; + while (tree != NULL && tree->node.data == NULL) { + tree = tree->node.parent; } - return node->data; + return tree->node.data; } static void process_cursor_move(struct tinywl_server *server, uint32_t time) { @@ -365,7 +366,7 @@ static void process_cursor_move(struct tinywl_server *server, uint32_t time) { struct tinywl_view *view = server->grabbed_view; view->x = server->cursor->x - server->grab_x; view->y = server->cursor->y - server->grab_y; - wlr_scene_node_set_position(view->scene_node, view->x, view->y); + wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y); } static void process_cursor_resize(struct tinywl_server *server, uint32_t time) { @@ -414,7 +415,7 @@ static void process_cursor_resize(struct tinywl_server *server, uint32_t time) { wlr_xdg_surface_get_geometry(view->xdg_toplevel->base, &geo_box); view->x = new_left - geo_box.x; view->y = new_top - geo_box.y; - wlr_scene_node_set_position(view->scene_node, view->x, view->y); + wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y); int new_width = new_right - new_left; int new_height = new_bottom - new_top; @@ -747,9 +748,9 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { struct wlr_xdg_surface *parent = wlr_xdg_surface_from_wlr_surface( xdg_surface->popup->parent); - struct wlr_scene_node *parent_node = parent->data; + struct wlr_scene_tree *parent_tree = parent->data; xdg_surface->data = wlr_scene_xdg_surface_create( - parent_node, xdg_surface); + parent_tree, xdg_surface); return; } assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); @@ -759,10 +760,10 @@ static void server_new_xdg_surface(struct wl_listener *listener, void *data) { calloc(1, sizeof(struct tinywl_view)); view->server = server; view->xdg_toplevel = xdg_surface->toplevel; - view->scene_node = wlr_scene_xdg_surface_create( - &view->server->scene->tree.node, view->xdg_toplevel->base); - view->scene_node->data = view; - xdg_surface->data = view->scene_node; + view->scene_tree = wlr_scene_xdg_surface_create( + &view->server->scene->tree, view->xdg_toplevel->base); + view->scene_tree->node.data = view; + xdg_surface->data = view->scene_tree; /* Listen to the various events it can emit */ view->map.notify = xdg_toplevel_map; diff --git a/types/scene/layer_shell_v1.c b/types/scene/layer_shell_v1.c index 1c2b6e4ff..eb0bc76e3 100644 --- a/types/scene/layer_shell_v1.c +++ b/types/scene/layer_shell_v1.c @@ -18,21 +18,21 @@ static void scene_layer_surface_handle_layer_surface_destroy( struct wl_listener *listener, void *data) { struct wlr_scene_layer_surface_v1 *scene_layer_surface = wl_container_of(listener, scene_layer_surface, layer_surface_destroy); - wlr_scene_node_destroy(scene_layer_surface->node); + wlr_scene_node_destroy(&scene_layer_surface->tree->node); } static void scene_layer_surface_handle_layer_surface_map( struct wl_listener *listener, void *data) { struct wlr_scene_layer_surface_v1 *scene_layer_surface = wl_container_of(listener, scene_layer_surface, layer_surface_map); - wlr_scene_node_set_enabled(scene_layer_surface->node, true); + wlr_scene_node_set_enabled(&scene_layer_surface->tree->node, true); } static void scene_layer_surface_handle_layer_surface_unmap( struct wl_listener *listener, void *data) { struct wlr_scene_layer_surface_v1 *scene_layer_surface = wl_container_of(listener, scene_layer_surface, layer_surface_unmap); - wlr_scene_node_set_enabled(scene_layer_surface->node, false); + wlr_scene_node_set_enabled(&scene_layer_surface->tree->node, false); } static void layer_surface_exclusive_zone( @@ -122,7 +122,7 @@ void wlr_scene_layer_surface_v1_configure( box.y = bounds.y + bounds.height/2 - box.height/2; } - wlr_scene_node_set_position(scene_layer_surface->node, box.x, box.y); + wlr_scene_node_set_position(&scene_layer_surface->tree->node, box.x, box.y); wlr_layer_surface_v1_configure(layer_surface, box.width, box.height); if (state->exclusive_zone > 0) { @@ -131,7 +131,7 @@ void wlr_scene_layer_surface_v1_configure( } struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( - struct wlr_scene_node *parent, + struct wlr_scene_tree *parent, struct wlr_layer_surface_v1 *layer_surface) { struct wlr_scene_layer_surface_v1 *scene_layer_surface = calloc(1, sizeof(*scene_layer_surface)); @@ -141,24 +141,23 @@ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( scene_layer_surface->layer_surface = layer_surface; - struct wlr_scene_tree *tree = wlr_scene_tree_create(parent); - if (tree == NULL) { + scene_layer_surface->tree = wlr_scene_tree_create(parent); + if (scene_layer_surface->tree == NULL) { free(scene_layer_surface); return NULL; } - scene_layer_surface->node = &tree->node; - struct wlr_scene_node *surface_node = wlr_scene_subsurface_tree_create( - scene_layer_surface->node, layer_surface->surface); - if (surface_node == NULL) { - wlr_scene_node_destroy(scene_layer_surface->node); + struct wlr_scene_tree *surface_tree = wlr_scene_subsurface_tree_create( + scene_layer_surface->tree, layer_surface->surface); + if (surface_tree == NULL) { + wlr_scene_node_destroy(&scene_layer_surface->tree->node); free(scene_layer_surface); return NULL; } scene_layer_surface->tree_destroy.notify = scene_layer_surface_handle_tree_destroy; - wl_signal_add(&scene_layer_surface->node->events.destroy, + wl_signal_add(&scene_layer_surface->tree->node.events.destroy, &scene_layer_surface->tree_destroy); scene_layer_surface->layer_surface_destroy.notify = @@ -176,7 +175,7 @@ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( wl_signal_add(&layer_surface->events.unmap, &scene_layer_surface->layer_surface_unmap); - wlr_scene_node_set_enabled(scene_layer_surface->node, + wlr_scene_node_set_enabled(&scene_layer_surface->tree->node, layer_surface->mapped); return scene_layer_surface; diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 1cb2977c6..35420abe4 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -148,13 +148,13 @@ static const struct wlr_addon_interface subsurface_tree_addon_impl = { }; static struct wlr_scene_subsurface_tree *scene_surface_tree_create( - struct wlr_scene_node *parent, struct wlr_surface *surface); + struct wlr_scene_tree *parent, struct wlr_surface *surface); static bool subsurface_tree_create_subsurface( struct wlr_scene_subsurface_tree *parent, struct wlr_subsurface *subsurface) { struct wlr_scene_subsurface_tree *child = scene_surface_tree_create( - &parent->tree->node, subsurface->surface); + parent->tree, subsurface->surface); if (child == NULL) { return false; } @@ -188,7 +188,7 @@ static void subsurface_tree_handle_surface_new_subsurface( } static struct wlr_scene_subsurface_tree *scene_surface_tree_create( - struct wlr_scene_node *parent, struct wlr_surface *surface) { + struct wlr_scene_tree *parent, struct wlr_surface *surface) { struct wlr_scene_subsurface_tree *subsurface_tree = calloc(1, sizeof(*subsurface_tree)); if (subsurface_tree == NULL) { @@ -201,7 +201,7 @@ static struct wlr_scene_subsurface_tree *scene_surface_tree_create( } subsurface_tree->scene_surface = - wlr_scene_surface_create(&subsurface_tree->tree->node, surface); + wlr_scene_surface_create(subsurface_tree->tree, surface); if (subsurface_tree->scene_surface == NULL) { goto error_scene_surface; } @@ -248,12 +248,12 @@ error_surface_tree: return NULL; } -struct wlr_scene_node *wlr_scene_subsurface_tree_create( - struct wlr_scene_node *parent, struct wlr_surface *surface) { +struct wlr_scene_tree *wlr_scene_subsurface_tree_create( + struct wlr_scene_tree *parent, struct wlr_surface *surface) { struct wlr_scene_subsurface_tree *subsurface_tree = scene_surface_tree_create(parent, surface); if (subsurface_tree == NULL) { return NULL; } - return &subsurface_tree->tree->node; + return subsurface_tree->tree; } diff --git a/types/scene/surface.c b/types/scene/surface.c index e6a8b6b6c..d3a0b035f 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -135,7 +135,7 @@ struct wlr_scene_surface *wlr_scene_surface_from_buffer( return surface; } -struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent, +struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent, struct wlr_surface *wlr_surface) { struct wlr_scene_surface *surface = calloc(1, sizeof(*surface)); if (surface == NULL) { diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 410fbe3b8..e60ff5d48 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -17,6 +17,11 @@ #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 +static struct wlr_scene_tree *scene_tree_from_node(struct wlr_scene_node *node) { + assert(node->type == WLR_SCENE_NODE_TREE); + return (struct wlr_scene_tree *)node; +} + static struct wlr_scene_rect *scene_rect_from_node( struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_RECT); @@ -30,10 +35,17 @@ struct wlr_scene_buffer *wlr_scene_buffer_from_node( } struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { - while (node->parent != NULL) { - node = node->parent; + struct wlr_scene_tree *tree; + if (node->type == WLR_SCENE_NODE_TREE) { + tree = scene_tree_from_node(node); + } else { + tree = node->parent; } - return (struct wlr_scene *)node; + + while (tree->node.parent != NULL) { + tree = tree->node.parent; + } + return (struct wlr_scene *)tree; } static void scene_node_state_init(struct wlr_scene_node_state *state) { @@ -48,7 +60,7 @@ static void scene_node_state_finish(struct wlr_scene_node_state *state) { } static void scene_node_init(struct wlr_scene_node *node, - enum wlr_scene_node_type type, struct wlr_scene_node *parent) { + enum wlr_scene_node_type type, struct wlr_scene_tree *parent) { memset(node, 0, sizeof(*node)); node->type = type; node->parent = parent; @@ -56,7 +68,7 @@ static void scene_node_init(struct wlr_scene_node *node, wl_signal_init(&node->events.destroy); if (parent != NULL) { - wl_list_insert(parent->state.children.prev, &node->state.link); + wl_list_insert(parent->node.state.children.prev, &node->state.link); } wlr_addon_set_init(&node->addons); @@ -136,7 +148,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } static void scene_tree_init(struct wlr_scene_tree *tree, - struct wlr_scene_node *parent) { + struct wlr_scene_tree *parent) { memset(tree, 0, sizeof(*tree)); scene_node_init(&tree->node, WLR_SCENE_NODE_TREE, parent); } @@ -172,7 +184,7 @@ struct wlr_scene *wlr_scene_create(void) { return scene; } -struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_node *parent) { +struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) { assert(parent); struct wlr_scene_tree *tree = calloc(1, sizeof(struct wlr_scene_tree)); @@ -251,7 +263,7 @@ static void scene_node_update_outputs(struct wlr_scene_node *node) { _scene_node_update_outputs(node, lx, ly, scene); } -struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_node *parent, +struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, int width, int height, const float color[static 4]) { struct wlr_scene_rect *scene_rect = calloc(1, sizeof(struct wlr_scene_rect)); @@ -290,7 +302,7 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta scene_node_damage_whole(&rect->node); } -struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent, +struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, struct wlr_buffer *buffer) { struct wlr_scene_buffer *scene_buffer = calloc(1, sizeof(*scene_buffer)); if (scene_buffer == NULL) { @@ -615,7 +627,7 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { struct wlr_scene_node *current_top = wl_container_of( - node->parent->state.children.prev, current_top, state.link); + node->parent->node.state.children.prev, current_top, state.link); if (node == current_top) { return; } @@ -624,7 +636,7 @@ void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) { struct wlr_scene_node *current_bottom = wl_container_of( - node->parent->state.children.next, current_bottom, state.link); + node->parent->node.state.children.next, current_bottom, state.link); if (node == current_bottom) { return; } @@ -632,7 +644,7 @@ void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) { } void wlr_scene_node_reparent(struct wlr_scene_node *node, - struct wlr_scene_node *new_parent) { + struct wlr_scene_tree *new_parent) { assert(new_parent != NULL); if (node->parent == new_parent) { @@ -640,16 +652,16 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, } /* Ensure that a node cannot become its own ancestor */ - for (struct wlr_scene_node *ancestor = new_parent; ancestor != NULL; - ancestor = ancestor->parent) { - assert(ancestor != node); + for (struct wlr_scene_tree *ancestor = new_parent; ancestor != NULL; + ancestor = ancestor->node.parent) { + assert(&ancestor->node != node); } scene_node_damage_whole(node); wl_list_remove(&node->state.link); node->parent = new_parent; - wl_list_insert(new_parent->state.children.prev, &node->state.link); + wl_list_insert(new_parent->node.state.children.prev, &node->state.link); scene_node_damage_whole(node); @@ -658,13 +670,19 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx_ptr, int *ly_ptr) { + assert(node); + int lx = 0, ly = 0; bool enabled = true; - while (node != NULL) { + while (true) { lx += node->state.x; ly += node->state.y; enabled = enabled && node->state.enabled; - node = node->parent; + if (node->parent == NULL) { + break; + } + + node = &node->parent->node; } *lx_ptr = lx; diff --git a/types/scene/xdg_shell.c b/types/scene/xdg_shell.c index 909719d1a..16883488f 100644 --- a/types/scene/xdg_shell.c +++ b/types/scene/xdg_shell.c @@ -5,7 +5,7 @@ struct wlr_scene_xdg_surface { struct wlr_scene_tree *tree; struct wlr_xdg_surface *xdg_surface; - struct wlr_scene_node *surface_node; + struct wlr_scene_tree *surface_tree; struct wl_listener tree_destroy; struct wl_listener xdg_surface_destroy; @@ -54,7 +54,7 @@ static void scene_xdg_surface_update_position( struct wlr_box geo = {0}; wlr_xdg_surface_get_geometry(xdg_surface, &geo); - wlr_scene_node_set_position(scene_xdg_surface->surface_node, + wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->node, -geo.x, -geo.y); if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { @@ -71,8 +71,8 @@ static void scene_xdg_surface_handle_xdg_surface_commit(struct wl_listener *list scene_xdg_surface_update_position(scene_xdg_surface); } -struct wlr_scene_node *wlr_scene_xdg_surface_create( - struct wlr_scene_node *parent, struct wlr_xdg_surface *xdg_surface) { +struct wlr_scene_tree *wlr_scene_xdg_surface_create( + struct wlr_scene_tree *parent, struct wlr_xdg_surface *xdg_surface) { struct wlr_scene_xdg_surface *scene_xdg_surface = calloc(1, sizeof(*scene_xdg_surface)); if (scene_xdg_surface == NULL) { @@ -87,9 +87,9 @@ struct wlr_scene_node *wlr_scene_xdg_surface_create( return NULL; } - scene_xdg_surface->surface_node = wlr_scene_subsurface_tree_create( - &scene_xdg_surface->tree->node, xdg_surface->surface); - if (scene_xdg_surface->surface_node == NULL) { + scene_xdg_surface->surface_tree = wlr_scene_subsurface_tree_create( + scene_xdg_surface->tree, xdg_surface->surface); + if (scene_xdg_surface->surface_tree == NULL) { wlr_scene_node_destroy(&scene_xdg_surface->tree->node); free(scene_xdg_surface); return NULL; @@ -120,5 +120,5 @@ struct wlr_scene_node *wlr_scene_xdg_surface_create( wlr_scene_node_set_enabled(&scene_xdg_surface->tree->node, xdg_surface->mapped); scene_xdg_surface_update_position(scene_xdg_surface); - return &scene_xdg_surface->tree->node; + return scene_xdg_surface->tree; } From cb2dbc327e4d695c2a60a386e116a7dc20b29107 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 6 Apr 2022 08:17:21 -0400 Subject: [PATCH 162/298] wlr_scene: Inline wlr_scene_node_state This seems like nothing interesting was done with this. Let's simplify and allow us some flexibility in the future. --- include/wlr/types/wlr_scene.h | 17 +++--- types/scene/wlr_scene.c | 110 ++++++++++++++++------------------ 2 files changed, 58 insertions(+), 69 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index aed617f9f..9b20cbd9c 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -46,20 +46,17 @@ enum wlr_scene_node_type { WLR_SCENE_NODE_BUFFER, }; -struct wlr_scene_node_state { - struct wl_list link; // wlr_scene_node_state.children - - struct wl_list children; // wlr_scene_node_state.link - - bool enabled; - int x, y; // relative to parent -}; - /** A node is an object in the scene. */ struct wlr_scene_node { enum wlr_scene_node_type type; struct wlr_scene_tree *parent; - struct wlr_scene_node_state state; + + struct wl_list link; // wlr_scene_node.children + + struct wl_list children; // wlr_scene_node.link + + bool enabled; + int x, y; // relative to parent struct { struct wl_signal destroy; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index e60ff5d48..8d05d0f1b 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -48,27 +48,20 @@ struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) { return (struct wlr_scene *)tree; } -static void scene_node_state_init(struct wlr_scene_node_state *state) { - memset(state, 0, sizeof(*state)); - wl_list_init(&state->children); - wl_list_init(&state->link); - state->enabled = true; -} - -static void scene_node_state_finish(struct wlr_scene_node_state *state) { - wl_list_remove(&state->link); -} - static void scene_node_init(struct wlr_scene_node *node, enum wlr_scene_node_type type, struct wlr_scene_tree *parent) { memset(node, 0, sizeof(*node)); node->type = type; node->parent = parent; - scene_node_state_init(&node->state); + node->enabled = true; + + wl_list_init(&node->children); + wl_list_init(&node->link); + wl_signal_init(&node->events.destroy); if (parent != NULL) { - wl_list_insert(parent->node.state.children.prev, &node->state.link); + wl_list_insert(parent->node.children.prev, &node->link); } wlr_addon_set_init(&node->addons); @@ -137,13 +130,12 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } struct wlr_scene_node *child, *child_tmp; - wl_list_for_each_safe(child, child_tmp, - &node->state.children, state.link) { + wl_list_for_each_safe(child, child_tmp, &node->children, link) { wlr_scene_node_destroy(child); } wlr_addon_set_finish(&node->addons); - scene_node_state_finish(&node->state); + wl_list_remove(&node->link); free(node); } @@ -250,9 +242,9 @@ static void _scene_node_update_outputs( } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { - _scene_node_update_outputs(child, lx + child->state.x, - ly + child->state.y, scene); + wl_list_for_each(child, &node->children, link) { + _scene_node_update_outputs(child, lx + child->x, + ly + child->y, scene); } } @@ -527,14 +519,14 @@ static void scale_box(struct wlr_box *box, float scale) { static void _scene_node_damage_whole(struct wlr_scene_node *node, struct wlr_scene *scene, int lx, int ly) { - if (!node->state.enabled) { + if (!node->enabled) { return; } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { _scene_node_damage_whole(child, scene, - lx + child->state.x, ly + child->state.y); + lx + child->x, ly + child->y); } int width, height; @@ -570,24 +562,24 @@ static void scene_node_damage_whole(struct wlr_scene_node *node) { } void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) { - if (node->state.enabled == enabled) { + if (node->enabled == enabled) { return; } // One of these damage_whole() calls will short-circuit and be a no-op scene_node_damage_whole(node); - node->state.enabled = enabled; + node->enabled = enabled; scene_node_damage_whole(node); } void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) { - if (node->state.x == x && node->state.y == y) { + if (node->x == x && node->y == y) { return; } scene_node_damage_whole(node); - node->state.x = x; - node->state.y = y; + node->x = x; + node->y = y; scene_node_damage_whole(node); scene_node_update_outputs(node); @@ -598,12 +590,12 @@ void wlr_scene_node_place_above(struct wlr_scene_node *node, assert(node != sibling); assert(node->parent == sibling->parent); - if (node->state.link.prev == &sibling->state.link) { + if (node->link.prev == &sibling->link) { return; } - wl_list_remove(&node->state.link); - wl_list_insert(&sibling->state.link, &node->state.link); + wl_list_remove(&node->link); + wl_list_insert(&sibling->link, &node->link); scene_node_damage_whole(node); scene_node_damage_whole(sibling); @@ -614,12 +606,12 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, assert(node != sibling); assert(node->parent == sibling->parent); - if (node->state.link.next == &sibling->state.link) { + if (node->link.next == &sibling->link) { return; } - wl_list_remove(&node->state.link); - wl_list_insert(sibling->state.link.prev, &node->state.link); + wl_list_remove(&node->link); + wl_list_insert(sibling->link.prev, &node->link); scene_node_damage_whole(node); scene_node_damage_whole(sibling); @@ -627,7 +619,7 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { struct wlr_scene_node *current_top = wl_container_of( - node->parent->node.state.children.prev, current_top, state.link); + node->parent->node.children.prev, current_top, link); if (node == current_top) { return; } @@ -636,7 +628,7 @@ void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) { struct wlr_scene_node *current_bottom = wl_container_of( - node->parent->node.state.children.next, current_bottom, state.link); + node->parent->node.children.next, current_bottom, link); if (node == current_bottom) { return; } @@ -659,9 +651,9 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, scene_node_damage_whole(node); - wl_list_remove(&node->state.link); + wl_list_remove(&node->link); node->parent = new_parent; - wl_list_insert(new_parent->node.state.children.prev, &node->state.link); + wl_list_insert(new_parent->node.children.prev, &node->link); scene_node_damage_whole(node); @@ -675,9 +667,9 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node, int lx = 0, ly = 0; bool enabled = true; while (true) { - lx += node->state.x; - ly += node->state.y; - enabled = enabled && node->state.enabled; + lx += node->x; + ly += node->y; + enabled = enabled && node->enabled; if (node->parent == NULL) { break; } @@ -693,12 +685,12 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node, static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { - if (!node->state.enabled) { + if (!node->enabled) { return; } - lx += node->state.x; - ly += node->state.y; + lx += node->x; + ly += node->y; if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); @@ -706,7 +698,7 @@ static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data); } } @@ -718,16 +710,16 @@ void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, double lx, double ly, double *nx, double *ny) { - if (!node->state.enabled) { + if (!node->enabled) { return NULL; } // TODO: optimize by storing a bounding box in each node? - lx -= node->state.x; - ly -= node->state.y; + lx -= node->x; + ly -= node->y; struct wlr_scene_node *child; - wl_list_for_each_reverse(child, &node->state.children, state.link) { + wl_list_for_each_reverse(child, &node->children, link) { struct wlr_scene_node *node = wlr_scene_node_at(child, lx, ly, nx, ny); if (node != NULL) { @@ -901,17 +893,17 @@ static void render_node_iterator(struct wlr_scene_node *node, static void scene_node_for_each_node(struct wlr_scene_node *node, int lx, int ly, wlr_scene_node_iterator_func_t user_iterator, void *user_data) { - if (!node->state.enabled) { + if (!node->enabled) { return; } - lx += node->state.x; - ly += node->state.y; + lx += node->x; + ly += node->y; user_iterator(node, lx, ly, user_data); struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { scene_node_for_each_node(child, lx, ly, user_iterator, user_data); } } @@ -1021,7 +1013,7 @@ static void scene_node_remove_output(struct wlr_scene_node *node, } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { scene_node_remove_output(child, output); } } @@ -1300,7 +1292,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { static void scene_node_send_frame_done(struct wlr_scene_node *node, struct wlr_scene_output *scene_output, struct timespec *now) { - if (!node->state.enabled) { + if (!node->enabled) { return; } @@ -1314,7 +1306,7 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { scene_node_send_frame_done(child, scene_output, now); } } @@ -1328,12 +1320,12 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output, static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, struct wlr_scene_node *node, int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) { - if (!node->state.enabled) { + if (!node->enabled) { return; } - lx += node->state.x; - ly += node->state.y; + lx += node->x; + ly += node->y; if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_box node_box = { .x = lx, .y = ly }; @@ -1348,7 +1340,7 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, } struct wlr_scene_node *child; - wl_list_for_each(child, &node->state.children, state.link) { + wl_list_for_each(child, &node->children, link) { scene_output_for_each_scene_buffer(output_box, child, lx, ly, user_iterator, user_data); } From 71f8a48d380701de1e3331d53d470bd76f5f643b Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 18 May 2022 18:16:44 -0400 Subject: [PATCH 163/298] wlr_scene: Move children list from wlr_scene_node to wlr_scene_tree --- include/wlr/types/wlr_scene.h | 6 +- types/scene/wlr_scene.c | 122 +++++++++++++++++++--------------- 2 files changed, 71 insertions(+), 57 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 9b20cbd9c..86976f61f 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -51,9 +51,7 @@ struct wlr_scene_node { enum wlr_scene_node_type type; struct wlr_scene_tree *parent; - struct wl_list link; // wlr_scene_node.children - - struct wl_list children; // wlr_scene_node.link + struct wl_list link; // wlr_scene_tree.children bool enabled; int x, y; // relative to parent @@ -76,6 +74,8 @@ enum wlr_scene_debug_damage_option { /** A sub-tree in the scene-graph. */ struct wlr_scene_tree { struct wlr_scene_node node; + + struct wl_list children; // wlr_scene_node.link }; /** The root scene-graph node. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 8d05d0f1b..678941343 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -55,13 +55,12 @@ static void scene_node_init(struct wlr_scene_node *node, node->parent = parent; node->enabled = true; - wl_list_init(&node->children); wl_list_init(&node->link); wl_signal_init(&node->events.destroy); if (parent != NULL) { - wl_list_insert(parent->node.children.prev, &node->link); + wl_list_insert(parent->children.prev, &node->link); } wlr_addon_set_init(&node->addons); @@ -111,7 +110,9 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_texture_destroy(scene_buffer->texture); wlr_buffer_unlock(scene_buffer->buffer); } else if (node->type == WLR_SCENE_NODE_TREE) { - if (node == &scene->tree.node) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + + if (scene_tree == &scene->tree) { assert(!node->parent); struct wlr_scene_output *scene_output, *scene_output_tmp; wl_list_for_each_safe(scene_output, scene_output_tmp, &scene->outputs, link) { @@ -127,11 +128,12 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { } else { assert(node->parent); } - } - struct wlr_scene_node *child, *child_tmp; - wl_list_for_each_safe(child, child_tmp, &node->children, link) { - wlr_scene_node_destroy(child); + struct wlr_scene_node *child, *child_tmp; + wl_list_for_each_safe(child, child_tmp, + &scene_tree->children, link) { + wlr_scene_node_destroy(child); + } } wlr_addon_set_finish(&node->addons); @@ -143,6 +145,7 @@ static void scene_tree_init(struct wlr_scene_tree *tree, struct wlr_scene_tree *parent) { memset(tree, 0, sizeof(*tree)); scene_node_init(&tree->node, WLR_SCENE_NODE_TREE, parent); + wl_list_init(&tree->children); } struct wlr_scene *wlr_scene_create(void) { @@ -239,12 +242,13 @@ static void _scene_node_update_outputs( struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); scene_buffer_update_outputs(scene_buffer, lx, ly, scene); - } - - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - _scene_node_update_outputs(child, lx + child->x, - ly + child->y, scene); + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + _scene_node_update_outputs(child, lx + child->x, + ly + child->y, scene); + } } } @@ -523,10 +527,13 @@ static void _scene_node_damage_whole(struct wlr_scene_node *node, return; } - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - _scene_node_damage_whole(child, scene, - lx + child->x, ly + child->y); + if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + _scene_node_damage_whole(child, scene, + lx + child->x, ly + child->y); + } } int width, height; @@ -619,7 +626,7 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { struct wlr_scene_node *current_top = wl_container_of( - node->parent->node.children.prev, current_top, link); + node->parent->children.prev, current_top, link); if (node == current_top) { return; } @@ -628,7 +635,7 @@ void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) { struct wlr_scene_node *current_bottom = wl_container_of( - node->parent->node.children.next, current_bottom, link); + node->parent->children.next, current_bottom, link); if (node == current_bottom) { return; } @@ -653,7 +660,7 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, wl_list_remove(&node->link); node->parent = new_parent; - wl_list_insert(new_parent->node.children.prev, &node->link); + wl_list_insert(new_parent->children.prev, &node->link); scene_node_damage_whole(node); @@ -695,11 +702,12 @@ static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node, if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); user_iterator(scene_buffer, lx, ly, user_data); - } - - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data); + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_for_each_scene_buffer(child, lx, ly, user_iterator, user_data); + } } } @@ -718,18 +726,18 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, lx -= node->x; ly -= node->y; - struct wlr_scene_node *child; - wl_list_for_each_reverse(child, &node->children, link) { - struct wlr_scene_node *node = - wlr_scene_node_at(child, lx, ly, nx, ny); - if (node != NULL) { - return node; - } - } - bool intersects = false; switch (node->type) { - case WLR_SCENE_NODE_TREE: + case WLR_SCENE_NODE_TREE:; + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each_reverse(child, &scene_tree->children, link) { + struct wlr_scene_node *node = + wlr_scene_node_at(child, lx, ly, nx, ny); + if (node != NULL) { + return node; + } + } break; case WLR_SCENE_NODE_RECT:; int width, height; @@ -902,9 +910,12 @@ static void scene_node_for_each_node(struct wlr_scene_node *node, user_iterator(node, lx, ly, user_data); - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - scene_node_for_each_node(child, lx, ly, user_iterator, user_data); + if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_for_each_node(child, lx, ly, user_iterator, user_data); + } } } @@ -1010,11 +1021,12 @@ static void scene_node_remove_output(struct wlr_scene_node *node, scene_buffer->active_outputs &= ~mask; wlr_signal_emit_safe(&scene_buffer->events.output_leave, output); } - } - - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - scene_node_remove_output(child, output); + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_remove_output(child, output); + } } } @@ -1303,11 +1315,12 @@ static void scene_node_send_frame_done(struct wlr_scene_node *node, if (scene_buffer->primary_output == scene_output) { wlr_scene_buffer_send_frame_done(scene_buffer, now); } - } - - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - scene_node_send_frame_done(child, scene_output, now); + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_send_frame_done(child, scene_output, now); + } } } @@ -1337,12 +1350,13 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, wlr_scene_buffer_from_node(node); user_iterator(scene_buffer, lx, ly, user_data); } - } - - struct wlr_scene_node *child; - wl_list_for_each(child, &node->children, link) { - scene_output_for_each_scene_buffer(output_box, child, lx, ly, - user_iterator, user_data); + } else if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_output_for_each_scene_buffer(output_box, child, lx, ly, + user_iterator, user_data); + } } } From e3e2a34cd82c7a45ee174df6e64c2261883ccc20 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 18:25:08 +0200 Subject: [PATCH 164/298] output: remove noop backend check in wlr_output_cursor_set_image The noop backend doesn't exist anymore. --- types/output/cursor.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/types/output/cursor.c b/types/output/cursor.c index f3055c5c4..c70b8e3da 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -377,9 +377,7 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, int32_t hotspot_x, int32_t hotspot_y) { struct wlr_renderer *renderer = cursor->output->renderer; if (!renderer) { - // if the backend has no renderer, we can't draw a cursor, but this is - // actually okay, for ex. with the noop backend - return true; + return false; } output_cursor_reset(cursor); From 459a642e83349cc96b722450c391a13758eeb1a6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 18:28:55 +0200 Subject: [PATCH 165/298] output: introduce wlr_output_cursor_set_buffer This will supersede wlr_output_cursor_set_image, and then later also supersede wlr_output_cursor_set_surface. --- include/wlr/types/wlr_output.h | 2 ++ types/output/cursor.c | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 68f85ebb2..a6523d3d2 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -498,6 +498,8 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, int32_t hotspot_x, int32_t hotspot_y); void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor, struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y); +bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, + struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y); bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, double x, double y); void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor); diff --git a/types/output/cursor.c b/types/output/cursor.c index c70b8e3da..0d82c3546 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -411,6 +411,50 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, return true; } +bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, + struct wlr_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y) { + struct wlr_renderer *renderer = cursor->output->renderer; + if (!renderer) { + return false; + } + + output_cursor_reset(cursor); + + if (buffer != NULL) { + cursor->width = buffer->width; + cursor->height = buffer->height; + } else { + cursor->width = 0; + cursor->height = 0; + } + + cursor->hotspot_x = hotspot_x; + cursor->hotspot_y = hotspot_y; + + output_cursor_update_visible(cursor); + + wlr_texture_destroy(cursor->texture); + cursor->texture = NULL; + + cursor->enabled = false; + if (buffer != NULL) { + cursor->texture = wlr_texture_from_buffer(renderer, buffer); + if (cursor->texture == NULL) { + return false; + } + cursor->enabled = true; + } + + if (output_cursor_attempt_hardware(cursor)) { + return true; + } + + wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", + cursor->output->name); + output_cursor_damage_whole(cursor); + return true; +} + static void output_cursor_commit(struct wlr_output_cursor *cursor, bool update_hotspot) { if (cursor->output->hardware_cursor != cursor) { From 1ab3e582acda1829e2ad84aa278550c5cfa174b1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 18:32:50 +0200 Subject: [PATCH 166/298] output: re-implement set_image with set_buffer Avoids having two code-paths doing the same thing. --- types/output/cursor.c | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/types/output/cursor.c b/types/output/cursor.c index 0d82c3546..2cbf67f54 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -8,6 +8,7 @@ #include #include "render/allocator/allocator.h" #include "render/swapchain.h" +#include "types/wlr_buffer.h" #include "types/wlr_output.h" #include "util/signal.h" @@ -375,40 +376,16 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { - struct wlr_renderer *renderer = cursor->output->renderer; - if (!renderer) { + struct wlr_readonly_data_buffer *buffer = + readonly_data_buffer_create(DRM_FORMAT_ARGB8888, stride, width, height, + pixels); + if (buffer == NULL) { return false; } - - output_cursor_reset(cursor); - - cursor->width = width; - cursor->height = height; - cursor->hotspot_x = hotspot_x; - cursor->hotspot_y = hotspot_y; - output_cursor_update_visible(cursor); - - wlr_texture_destroy(cursor->texture); - cursor->texture = NULL; - - cursor->enabled = false; - if (pixels != NULL) { - cursor->texture = wlr_texture_from_pixels(renderer, - DRM_FORMAT_ARGB8888, stride, width, height, pixels); - if (cursor->texture == NULL) { - return false; - } - cursor->enabled = true; - } - - if (output_cursor_attempt_hardware(cursor)) { - return true; - } - - wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", - cursor->output->name); - output_cursor_damage_whole(cursor); - return true; + bool ok = wlr_output_cursor_set_buffer(cursor, &buffer->base, + hotspot_x, hotspot_y); + wlr_buffer_drop(&buffer->base); + return ok; } bool wlr_output_cursor_set_buffer(struct wlr_output_cursor *cursor, From 638c5cda5116b4b7f6e1156e552945023688d83a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 18:42:51 +0200 Subject: [PATCH 167/298] output: drop wlr_output_cursor.events.destroy Compositors can just listen to wlr_output.events.destroy instead. --- include/wlr/types/wlr_output.h | 4 ---- types/output/cursor.c | 2 -- 2 files changed, 6 deletions(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index a6523d3d2..d3d44132b 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -40,10 +40,6 @@ struct wlr_output_cursor { struct wlr_surface *surface; struct wl_listener surface_commit; struct wl_listener surface_destroy; - - struct { - struct wl_signal destroy; - } events; }; enum wlr_output_adaptive_sync_status { diff --git a/types/output/cursor.c b/types/output/cursor.c index 2cbf67f54..bd6f757ef 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -566,7 +566,6 @@ struct wlr_output_cursor *wlr_output_cursor_create(struct wlr_output *output) { return NULL; } cursor->output = output; - wl_signal_init(&cursor->events.destroy); wl_list_init(&cursor->surface_commit.link); cursor->surface_commit.notify = output_cursor_handle_commit; wl_list_init(&cursor->surface_destroy.link); @@ -581,7 +580,6 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) { return; } output_cursor_reset(cursor); - wlr_signal_emit_safe(&cursor->events.destroy, cursor); if (cursor->output->hardware_cursor == cursor) { // If this cursor was the hardware cursor, disable it output_set_hardware_cursor(cursor->output, NULL, 0, 0); From ec328ca8cc82f5cac657141e31a81a590759150d Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 31 May 2022 20:34:50 +0300 Subject: [PATCH 168/298] scene/wlr_scene.h: fix indentation --- include/wlr/types/wlr_scene.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 86976f61f..38a2e4786 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -73,9 +73,9 @@ enum wlr_scene_debug_damage_option { /** A sub-tree in the scene-graph. */ struct wlr_scene_tree { - struct wlr_scene_node node; + struct wlr_scene_node node; - struct wl_list children; // wlr_scene_node.link + struct wl_list children; // wlr_scene_node.link }; /** The root scene-graph node. */ From d3bc17d5d1712cb445598d5fbfd40574661b2568 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 31 May 2022 21:39:53 +0300 Subject: [PATCH 169/298] scene: add wlr_scene_output.events.destroy --- include/wlr/types/wlr_scene.h | 4 ++++ types/scene/wlr_scene.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 38a2e4786..4b8ea517f 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -164,6 +164,10 @@ struct wlr_scene_output { int x, y; + struct { + struct wl_signal destroy; + } events; + // private state uint8_t index; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 678941343..8f9d0369e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -999,6 +999,8 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, assert(scene_output->index < 64); wl_list_insert(prev_output_link, &scene_output->link); + wl_signal_init(&scene_output->events.destroy); + scene_output->output_commit.notify = scene_output_handle_commit; wl_signal_add(&output->events.commit, &scene_output->output_commit); @@ -1035,6 +1037,8 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { return; } + wlr_signal_emit_safe(&scene_output->events.destroy, NULL); + scene_node_remove_output(&scene_output->scene->tree.node, scene_output); wlr_addon_finish(&scene_output->addon); From 0c2eed533eeb6a8d7dbe0a0378930b3a01be557d Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 31 May 2022 21:40:03 +0300 Subject: [PATCH 170/298] scene/output-layout: improve ownership logic This commit ensures that outputs that weren't created by the output layout helper aren't destroyed on the output layout change. Consider the following piece of logic: // struct wlr_output *o1, *o2; // struct wlr_scene *scene; // struct wlr_output_layout *layout; wlr_scene_attach_output_layout(scene, layout); wlr_output_layout_add_auto(layout, o1); struct wlr_scene_output *so2 = wlr_scene_output_create(scene, o2); wlr_output_layout_move(layout, o1, 100, 200); // so2 is invalid now --- include/wlr/types/wlr_scene.h | 6 +- types/scene/output_layout.c | 110 +++++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 4b8ea517f..49804d83a 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -406,8 +406,10 @@ struct wlr_scene_output *wlr_scene_get_scene_output(struct wlr_scene *scene, /** * Attach an output layout to a scene. * - * Outputs in the output layout are automatically added to the scene. Any - * change to the output layout is mirrored to the scene-graph outputs. + * Adding, removing, or repositioning an output in the output layout + * will respectively add, remove or reposition a corresponding + * scene-graph output. When the output layout is destroyed, scene-graph + * outputs which were created by this helper will be destroyed. */ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, struct wlr_output_layout *output_layout); diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c index e2327eb99..212231145 100644 --- a/types/scene/output_layout.c +++ b/types/scene/output_layout.c @@ -6,36 +6,58 @@ struct wlr_scene_output_layout { struct wlr_output_layout *layout; struct wlr_scene *scene; + struct wl_list outputs; // wlr_scene_output_layout_output.link + struct wl_listener layout_add; struct wl_listener layout_change; struct wl_listener layout_destroy; struct wl_listener scene_destroy; }; -static void scene_output_layout_destroy(struct wlr_scene_output_layout *sol) { - wl_list_remove(&sol->layout_destroy.link); - wl_list_remove(&sol->layout_add.link); - wl_list_remove(&sol->layout_change.link); - wl_list_remove(&sol->scene_destroy.link); - free(sol); +struct wlr_scene_output_layout_output { + struct wlr_output_layout_output *layout_output; + struct wlr_scene_output *scene_output; + + struct wl_list link; // wlr_scene_output_layout.outputs + + struct wl_listener layout_output_destroy; + struct wl_listener scene_output_destroy; +}; + +static void scene_output_layout_output_destroy( + struct wlr_scene_output_layout_output *solo) { + wlr_scene_output_destroy(solo->scene_output); + wl_list_remove(&solo->layout_output_destroy.link); + wl_list_remove(&solo->scene_output_destroy.link); + wl_list_remove(&solo->link); + free(solo); } -static void scene_output_layout_handle_layout_destroy( +static void scene_output_layout_output_handle_layout_output_destroy( struct wl_listener *listener, void *data) { - struct wlr_scene_output_layout *sol = - wl_container_of(listener, sol, layout_destroy); + struct wlr_scene_output_layout_output *solo = + wl_container_of(listener, solo, layout_output_destroy); + scene_output_layout_output_destroy(solo); +} - // Remove all outputs managed by the output layout - struct wlr_scene_output *scene_output, *tmp; - wl_list_for_each_safe(scene_output, tmp, &sol->scene->outputs, link) { - struct wlr_output_layout_output *lo = - wlr_output_layout_get(sol->layout, scene_output->output); - if (lo != NULL) { - wlr_scene_output_destroy(scene_output); - } +static void scene_output_layout_output_handle_scene_output_destroy( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout_output *solo = + wl_container_of(listener, solo, scene_output_destroy); + solo->scene_output = NULL; + scene_output_layout_output_destroy(solo); +} + +static void scene_output_layout_destroy(struct wlr_scene_output_layout *sol) { + struct wlr_scene_output_layout_output *solo, *tmp; + wl_list_for_each_safe(solo, tmp, &sol->outputs, link) { + scene_output_layout_output_destroy(solo); } - - scene_output_layout_destroy(sol); + wl_list_remove(&sol->layout_add.link); + wl_list_remove(&sol->layout_change.link); + wl_list_remove(&sol->layout_destroy.link); + wl_list_remove(&sol->scene_destroy.link); + free(sol); } static void scene_output_layout_handle_layout_change( @@ -43,17 +65,10 @@ static void scene_output_layout_handle_layout_change( struct wlr_scene_output_layout *sol = wl_container_of(listener, sol, layout_change); - struct wlr_scene_output *scene_output, *tmp; - wl_list_for_each_safe(scene_output, tmp, &sol->scene->outputs, link) { - struct wlr_output_layout_output *lo = - wlr_output_layout_get(sol->layout, scene_output->output); - if (lo == NULL) { - // Output has been removed from the layout - wlr_scene_output_destroy(scene_output); - continue; - } - - wlr_scene_output_set_position(scene_output, lo->x, lo->y); + struct wlr_scene_output_layout_output *solo; + wl_list_for_each(solo, &sol->outputs, link) { + wlr_scene_output_set_position(solo->scene_output, + solo->layout_output->x, solo->layout_output->y); } } @@ -63,13 +78,38 @@ static void scene_output_layout_handle_layout_add( wl_container_of(listener, sol, layout_add); struct wlr_output_layout_output *lo = data; - struct wlr_scene_output *scene_output = - wlr_scene_output_create(sol->scene, lo->output); - if (scene_output == NULL) { + struct wlr_scene_output_layout_output *solo = calloc(1, sizeof(*solo)); + if (solo == NULL) { return; } - wlr_scene_output_set_position(scene_output, lo->x, lo->y); + solo->scene_output = wlr_scene_output_create(sol->scene, lo->output); + if (solo->scene_output == NULL) { + free(solo); + return; + } + + solo->layout_output = lo; + + solo->layout_output_destroy.notify = + scene_output_layout_output_handle_layout_output_destroy; + wl_signal_add(&lo->events.destroy, &solo->layout_output_destroy); + + solo->scene_output_destroy.notify = + scene_output_layout_output_handle_scene_output_destroy; + wl_signal_add(&solo->scene_output->events.destroy, + &solo->scene_output_destroy); + + wl_list_insert(&sol->outputs, &solo->link); + + wlr_scene_output_set_position(solo->scene_output, lo->x, lo->y); +} + +static void scene_output_layout_handle_layout_destroy( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, layout_destroy); + scene_output_layout_destroy(sol); } static void scene_output_layout_handle_scene_destroy( @@ -89,6 +129,8 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, sol->scene = scene; sol->layout = output_layout; + wl_list_init(&sol->outputs); + sol->layout_destroy.notify = scene_output_layout_handle_layout_destroy; wl_signal_add(&output_layout->events.destroy, &sol->layout_destroy); From 1284f85da4ee9345af31d239a2e451c4066e710b Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 31 May 2022 21:44:10 +0300 Subject: [PATCH 171/298] scene/output-layout: add initial outputs --- types/scene/output_layout.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c index 212231145..900cabc30 100644 --- a/types/scene/output_layout.c +++ b/types/scene/output_layout.c @@ -72,12 +72,8 @@ static void scene_output_layout_handle_layout_change( } } -static void scene_output_layout_handle_layout_add( - struct wl_listener *listener, void *data) { - struct wlr_scene_output_layout *sol = - wl_container_of(listener, sol, layout_add); - struct wlr_output_layout_output *lo = data; - +static void scene_output_layout_add(struct wlr_scene_output_layout *sol, + struct wlr_output_layout_output *lo) { struct wlr_scene_output_layout_output *solo = calloc(1, sizeof(*solo)); if (solo == NULL) { return; @@ -105,6 +101,15 @@ static void scene_output_layout_handle_layout_add( wlr_scene_output_set_position(solo->scene_output, lo->x, lo->y); } +static void scene_output_layout_handle_layout_add( + struct wl_listener *listener, void *data) { + struct wlr_scene_output_layout *sol = + wl_container_of(listener, sol, layout_add); + struct wlr_output_layout_output *lo = data; + + scene_output_layout_add(sol, lo); +} + static void scene_output_layout_handle_layout_destroy( struct wl_listener *listener, void *data) { struct wlr_scene_output_layout *sol = @@ -143,5 +148,10 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene, sol->scene_destroy.notify = scene_output_layout_handle_scene_destroy; wl_signal_add(&scene->tree.node.events.destroy, &sol->scene_destroy); + struct wlr_output_layout_output *lo; + wl_list_for_each(lo, &output_layout->outputs, link) { + scene_output_layout_add(sol, lo); + } + return true; } From 18595000f3a21502fd60bf213122859cc348f9af Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 7 May 2022 10:28:05 +0200 Subject: [PATCH 172/298] compositor: send WL_SURFACE_ERROR_INVALID_SIZE for non-cursor surfaces See the discussion at [1]: there's no easy way to fix libwayland-cursor without a new API. Sending the error for other roles will prevent the same client bug from appearing elsewhere. [1]: https://gitlab.freedesktop.org/wayland/wayland/-/issues/194 --- types/wlr_compositor.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 1e86e9e78..8b84a6439 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -176,12 +176,21 @@ static void surface_finalize_pending(struct wlr_surface *surface) { if (!pending->viewport.has_src && (pending->buffer_width % pending->scale != 0 || pending->buffer_height % pending->scale != 0)) { - // TODO: send WL_SURFACE_ERROR_INVALID_SIZE error once this issue is - // resolved: + // TODO: send WL_SURFACE_ERROR_INVALID_SIZE error to cursor surfaces + // once this issue is resolved: // https://gitlab.freedesktop.org/wayland/wayland/-/issues/194 - wlr_log(WLR_DEBUG, "Client bug: submitted a buffer whose size (%dx%d) " - "is not divisible by scale (%d)", pending->buffer_width, - pending->buffer_height, pending->scale); + if (!surface->role + || strcmp(surface->role->name, "wl_pointer-cursor") == 0 + || strcmp(surface->role->name, "wp_tablet_tool-cursor") == 0) { + wlr_log(WLR_DEBUG, "Client bug: submitted a buffer whose size (%dx%d) " + "is not divisible by scale (%d)", pending->buffer_width, + pending->buffer_height, pending->scale); + } else { + wl_resource_post_error(surface->resource, + WL_SURFACE_ERROR_INVALID_SIZE, + "Buffer size (%dx%d) is not divisible by scale (%d)", + pending->buffer_width, pending->buffer_height, pending->scale); + } } if (pending->viewport.has_dst) { From e383c1f1db37c6d2de8f070603a89230f876bc80 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 6 May 2022 19:20:33 +0200 Subject: [PATCH 173/298] xdg-shell: add support for v4 This adds a configure_bounds event to let the client know of the preferred maximum window geometry size. --- include/wlr/types/wlr_xdg_shell.h | 15 +++++++++++++++ types/xdg_shell/wlr_xdg_shell.c | 2 +- types/xdg_shell/wlr_xdg_toplevel.c | 24 ++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 04463d2ca..f6b3b362b 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -137,10 +137,18 @@ struct wlr_xdg_toplevel_state { uint32_t min_width, min_height; }; +enum wlr_xdg_toplevel_configure_field { + WLR_XDG_TOPLEVEL_CONFIGURE_BOUNDS = 1 << 0, +}; + struct wlr_xdg_toplevel_configure { + uint32_t fields; // enum wlr_xdg_toplevel_configure_field bool maximized, fullscreen, resizing, activated; uint32_t tiled; // enum wlr_edges uint32_t width, height; + struct { + uint32_t width, height; + } bounds; }; struct wlr_xdg_toplevel_requested { @@ -376,6 +384,13 @@ uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_toplevel *toplevel, uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, uint32_t tiled_edges); +/** + * Configure the recommended bounds for the client's window geometry size. + * Returns the associated configure serial. + */ +uint32_t wlr_xdg_toplevel_set_bounds(struct wlr_xdg_toplevel *toplevel, + int32_t width, int32_t height); + /** * Request that this toplevel closes. */ diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 7e6bf5f81..9008de4ed 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -3,7 +3,7 @@ #include "types/wlr_xdg_shell.h" #include "util/signal.h" -#define WM_BASE_VERSION 3 +#define WM_BASE_VERSION 4 static const struct xdg_wm_base_interface xdg_shell_impl; diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 750efedac..a7ca8257c 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -31,6 +31,14 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( } *configure = toplevel->scheduled; + uint32_t version = wl_resource_get_version(toplevel->resource); + + if ((configure->fields & WLR_XDG_TOPLEVEL_CONFIGURE_BOUNDS) && + version >= XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) { + xdg_toplevel_send_configure_bounds(toplevel->resource, + configure->bounds.width, configure->bounds.height); + } + size_t nstates = 0; uint32_t states[32]; if (configure->maximized) { @@ -46,8 +54,7 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( states[nstates++] = XDG_TOPLEVEL_STATE_ACTIVATED; } if (configure->tiled) { - if (wl_resource_get_version(toplevel->resource) >= - XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) { + if (version >= XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) { const struct { enum wlr_edges edge; enum xdg_toplevel_state state; @@ -79,6 +86,8 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( xdg_toplevel_send_configure(toplevel->resource, width, height, &wl_states); + toplevel->scheduled.fields = 0; + return configure; } @@ -501,3 +510,14 @@ uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, toplevel->scheduled.tiled = tiled; return wlr_xdg_surface_schedule_configure(toplevel->base); } + +uint32_t wlr_xdg_toplevel_set_bounds(struct wlr_xdg_toplevel *toplevel, + int32_t width, int32_t height) { + assert(toplevel->base->client->shell->version >= + XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION); + assert(width >= 0 && height >= 0); + toplevel->scheduled.fields |= WLR_XDG_TOPLEVEL_CONFIGURE_BOUNDS; + toplevel->scheduled.bounds.width = width; + toplevel->scheduled.bounds.height = height; + return wlr_xdg_surface_schedule_configure(toplevel->base); +} From acc6d94db048118e7e910d7812431dfb27b2d769 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 27 May 2022 13:21:55 +0200 Subject: [PATCH 174/298] backend/drm: make commits without a buffer blocking The wlr_output API requires compositors to wait for wlr_output.frame before submitting a new buffer. However, compositors can perform a commit which doesn't involve a buffer anytime. If the commit is a modeset, we set DRM_MODE_ATOMIC_ALLOW_MODESET and block until the commit is done. If it isn't, we currently always perform a non-blocking commit. This is an issue because a previous page-flip might still be in flight kernel-side, returning EBUSY. Fix this by using blocking commits when a buffer isn't submitted by the compositor. Closes: https://github.com/swaywm/sway/issues/6962 References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2239 --- backend/drm/atomic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index cacb8e87a..1d4f9df43 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -264,7 +264,12 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, } if (modeset) { flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - } else if (!test_only) { + } else if (!test_only && (state->base->committed & WLR_OUTPUT_STATE_BUFFER)) { + // The wlr_output API requires non-modeset commits with a new buffer to + // wait for the frame event. However compositors often perform + // non-modesets commits without a new buffer without waiting for the + // frame event. In that case we need to make the KMS commit blocking, + // otherwise the kernel will error out with EBUSY. flags |= DRM_MODE_ATOMIC_NONBLOCK; } From 6936e163b514fd4f43a9319f53090527fc411156 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 1 Jun 2022 21:31:54 +0200 Subject: [PATCH 175/298] backend/drm: short-circuit no-op commits Some output commits (changing e.g. the output scale or transform) don't require any change in the KMS state. Instead of going through a KMS commit, return early. Blocking KMS commits can be expensive. --- backend/drm/drm.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 2caa0ef01..97e473b6d 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -31,13 +31,16 @@ #include "render/wlr_renderer.h" #include "util/signal.h" -static const uint32_t SUPPORTED_OUTPUT_STATE = - WLR_OUTPUT_STATE_BACKEND_OPTIONAL | +// Output state which needs a KMS commit to be applied +static const uint32_t COMMIT_OUTPUT_STATE = WLR_OUTPUT_STATE_BUFFER | WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_GAMMA_LUT; +static const uint32_t SUPPORTED_OUTPUT_STATE = + WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE; + bool check_drm_features(struct wlr_drm_backend *drm) { if (drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &drm->cursor_width)) { drm->cursor_width = 64; @@ -474,6 +477,11 @@ static bool drm_connector_test(struct wlr_output *output, return false; } + if ((state->committed & ~COMMIT_OUTPUT_STATE) == 0) { + // This commit doesn't change the KMS state + return true; + } + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) { if (output->current_mode == NULL && !(state->committed & WLR_OUTPUT_STATE_MODE)) { @@ -560,6 +568,11 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn, return false; } + if ((base->committed & ~COMMIT_OUTPUT_STATE) == 0) { + // This commit doesn't change the KMS state + return true; + } + struct wlr_drm_connector_state pending = {0}; drm_connector_state_init(&pending, conn, base); From 4772eec93dc683b376283222243e852e0332c8a8 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 2 Jun 2022 10:33:04 -0400 Subject: [PATCH 176/298] wlr_scene_buffer: Call output enter/leave after primary_output calculation --- types/scene/wlr_scene.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 8f9d0369e..791462ddf 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -205,6 +205,14 @@ static void scene_buffer_update_outputs( int largest_overlap = 0; scene_buffer->primary_output = NULL; + uint64_t active_outputs = 0; + + // let's update the outputs in two steps: + // - the primary outputs + // - the enter/leave signals + // This ensures that the enter/leave signals can rely on the primary output + // to have a reasonable value. Otherwise, they may get a value that's in + // the middle of a calculation. struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { struct wlr_box output_box = { @@ -216,7 +224,6 @@ static void scene_buffer_update_outputs( struct wlr_box intersection; bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box); - bool intersects_before = scene_buffer->active_outputs & (1ull << scene_output->index); if (intersects) { int overlap = intersection.width * intersection.height; @@ -224,13 +231,22 @@ static void scene_buffer_update_outputs( largest_overlap = overlap; scene_buffer->primary_output = scene_output; } + + active_outputs |= 1ull << scene_output->index; } + } + + uint64_t old_active = scene_buffer->active_outputs; + scene_buffer->active_outputs = active_outputs; + + wl_list_for_each(scene_output, &scene->outputs, link) { + uint64_t mask = 1ull << scene_output->index; + bool intersects = active_outputs & mask; + bool intersects_before = old_active & mask; if (intersects && !intersects_before) { - scene_buffer->active_outputs |= 1ull << scene_output->index; wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output); } else if (!intersects && intersects_before) { - scene_buffer->active_outputs &= ~(1ull << scene_output->index); wlr_signal_emit_safe(&scene_buffer->events.output_leave, scene_output); } } From cc5a02e75deccf1006b3f231556b9fbbcd64edf8 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 31 May 2022 15:22:45 -0400 Subject: [PATCH 177/298] wlr_scene_buffer: Update primary_output on output destroy --- types/scene/wlr_scene.c | 65 +++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 791462ddf..4cdf4be84 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -196,9 +196,9 @@ static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); // This function must be called whenever the coordinates/dimensions of a scene // buffer or scene output change. It is not necessary to call when a scene // buffer's node is enabled/disabled or obscured by other nodes. -static void scene_buffer_update_outputs( - struct wlr_scene_buffer *scene_buffer, - int lx, int ly, struct wlr_scene *scene) { +static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, + int lx, int ly, struct wlr_scene *scene, + struct wlr_scene_output *ignore) { struct wlr_box buffer_box = { .x = lx, .y = ly }; scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height); @@ -215,6 +215,10 @@ static void scene_buffer_update_outputs( // the middle of a calculation. struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { + if (scene_output == ignore) { + continue; + } + struct wlr_box output_box = { .x = scene_output->x, .y = scene_output->y, @@ -252,27 +256,29 @@ static void scene_buffer_update_outputs( } } -static void _scene_node_update_outputs( - struct wlr_scene_node *node, int lx, int ly, struct wlr_scene *scene) { +static void _scene_node_update_outputs(struct wlr_scene_node *node, + int lx, int ly, struct wlr_scene *scene, + struct wlr_scene_output *ignore) { if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - scene_buffer_update_outputs(scene_buffer, lx, ly, scene); + scene_buffer_update_outputs(scene_buffer, lx, ly, scene, ignore); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { _scene_node_update_outputs(child, lx + child->x, - ly + child->y, scene); + ly + child->y, scene, ignore); } } } -static void scene_node_update_outputs(struct wlr_scene_node *node) { +static void scene_node_update_outputs(struct wlr_scene_node *node, + struct wlr_scene_output *ignore) { struct wlr_scene *scene = scene_node_get_root(node); int lx, ly; wlr_scene_node_coords(node, &lx, &ly); - _scene_node_update_outputs(node, lx, ly, scene); + _scene_node_update_outputs(node, lx, ly, scene, ignore); } struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, @@ -334,7 +340,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, scene_node_damage_whole(&scene_buffer->node); - scene_node_update_outputs(&scene_buffer->node); + scene_node_update_outputs(&scene_buffer->node, NULL); return scene_buffer; } @@ -361,7 +367,7 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff scene_buffer->buffer = NULL; } - scene_node_update_outputs(&scene_buffer->node); + scene_node_update_outputs(&scene_buffer->node, NULL); if (!damage) { scene_node_damage_whole(&scene_buffer->node); @@ -457,7 +463,7 @@ void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, scene_buffer->dst_height = height; scene_node_damage_whole(&scene_buffer->node); - scene_node_update_outputs(&scene_buffer->node); + scene_node_update_outputs(&scene_buffer->node, NULL); } void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, @@ -470,7 +476,7 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, scene_buffer->transform = transform; scene_node_damage_whole(&scene_buffer->node); - scene_node_update_outputs(&scene_buffer->node); + scene_node_update_outputs(&scene_buffer->node, NULL); } void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, @@ -605,7 +611,7 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) { node->y = y; scene_node_damage_whole(node); - scene_node_update_outputs(node); + scene_node_update_outputs(node, NULL); } void wlr_scene_node_place_above(struct wlr_scene_node *node, @@ -680,7 +686,7 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, scene_node_damage_whole(node); - scene_node_update_outputs(node); + scene_node_update_outputs(node, NULL); } bool wlr_scene_node_coords(struct wlr_scene_node *node, @@ -971,14 +977,14 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data) if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { - scene_node_update_outputs(&scene_output->scene->tree.node); + scene_node_update_outputs(&scene_output->scene->tree.node, NULL); } } static void scene_output_handle_mode(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wl_container_of(listener, scene_output, output_mode); - scene_node_update_outputs(&scene_output->scene->tree.node); + scene_node_update_outputs(&scene_output->scene->tree.node, NULL); } struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, @@ -1024,30 +1030,11 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, wl_signal_add(&output->events.mode, &scene_output->output_mode); wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene->tree.node); + scene_node_update_outputs(&scene->tree.node, NULL); return scene_output; } -static void scene_node_remove_output(struct wlr_scene_node *node, - struct wlr_scene_output *output) { - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - uint64_t mask = 1ull << output->index; - if (scene_buffer->active_outputs & mask) { - scene_buffer->active_outputs &= ~mask; - wlr_signal_emit_safe(&scene_buffer->events.output_leave, output); - } - } else if (node->type == WLR_SCENE_NODE_TREE) { - struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); - struct wlr_scene_node *child; - wl_list_for_each(child, &scene_tree->children, link) { - scene_node_remove_output(child, output); - } - } -} - void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { if (scene_output == NULL) { return; @@ -1055,7 +1042,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wlr_signal_emit_safe(&scene_output->events.destroy, NULL); - scene_node_remove_output(&scene_output->scene->tree.node, scene_output); + scene_node_update_outputs(&scene_output->scene->tree.node, scene_output); wlr_addon_finish(&scene_output->addon); wl_list_remove(&scene_output->link); @@ -1087,7 +1074,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output->y = ly; wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene_output->scene->tree.node); + scene_node_update_outputs(&scene_output->scene->tree.node, NULL); } struct check_scanout_data { From 2b10ae62ad9c1a3de5d96dafbf0f86a9e897fc8e Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 2 Jun 2022 20:18:16 +0200 Subject: [PATCH 178/298] backend/drm: fix check for no-op commits Since 6936e163b, we short-circut no-op commits as an optimization. However, the logic in the check was slightly off. --- backend/drm/drm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 97e473b6d..3a4a683fb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -477,7 +477,7 @@ static bool drm_connector_test(struct wlr_output *output, return false; } - if ((state->committed & ~COMMIT_OUTPUT_STATE) == 0) { + if ((state->committed & COMMIT_OUTPUT_STATE) == 0) { // This commit doesn't change the KMS state return true; } @@ -568,7 +568,7 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn, return false; } - if ((base->committed & ~COMMIT_OUTPUT_STATE) == 0) { + if ((base->committed & COMMIT_OUTPUT_STATE) == 0) { // This commit doesn't change the KMS state return true; } From 366e8e3b9163d29bfcb75c97d482aa730d0dfc11 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 4 Jun 2022 23:02:42 +0200 Subject: [PATCH 179/298] examples/text-input: stop using strcpy/strcat These functions are too easy to misuse, they don't do bounds checking. --- examples/text-input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/text-input.c b/examples/text-input.c index 363632755..2f530d274 100644 --- a/examples/text-input.c +++ b/examples/text-input.c @@ -244,15 +244,15 @@ static void text_input_handle_done(void *data, buffer[strlen(buffer) - delete_before] = '\0'; } - char *commit_string = current.commit; + const char *commit_string = current.commit; if (!commit_string) { commit_string = ""; } - char *old_buffer = buffer; - buffer = calloc(strlen(buffer) + strlen(commit_string) + 1, sizeof(char)); // realloc may fail anyway - strcpy(buffer, old_buffer); - free(old_buffer); - strcat(buffer, commit_string); + size_t new_size = strlen(buffer) + strlen(commit_string) + 1; + char *new_buffer = calloc(new_size, sizeof(char)); // realloc may fail anyway + snprintf(new_buffer, new_size, "%s%s", buffer, commit_string); + free(buffer); + buffer = new_buffer; send_status_update(zwp_text_input_v3); show_status(); From c2952411d388c09fa4e90aca3c27e5d2e74bd413 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sat, 4 Jun 2022 23:03:39 +0200 Subject: [PATCH 180/298] examples/screencopy-dmabuf: stop using strncpy strncpy doesn't guarantee that the result is zero-terminated. --- examples/screencopy-dmabuf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/screencopy-dmabuf.c b/examples/screencopy-dmabuf.c index e7657e1a9..f16c29daf 100644 --- a/examples/screencopy-dmabuf.c +++ b/examples/screencopy-dmabuf.c @@ -76,7 +76,7 @@ static const struct format formats[] = { {DRM_FORMAT_ABGR8888, false}, }; -static bool find_render_node(char *node, size_t maxlen) { +static bool find_render_node(char *node, size_t node_size) { bool r = false; drmDevice *devices[64]; @@ -87,8 +87,7 @@ static bool find_render_node(char *node, size_t maxlen) { continue; } - strncpy(node, dev->nodes[DRM_NODE_RENDER], maxlen - 1); - node[maxlen - 1] = '\0'; + snprintf(node, node_size, "%s", dev->nodes[DRM_NODE_RENDER]); r = true; break; } From 808e660291309ad36581356cb7a3931657d228af Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 4 Jun 2022 18:18:02 -0400 Subject: [PATCH 181/298] wlr_output_commit_state: Make sure to clear the back buffer Fixes: #3445 --- types/output/output.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/output/output.c b/types/output/output.c index 6bcb2b870..c69b517ff 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -706,12 +706,14 @@ bool wlr_output_commit_state(struct wlr_output *output, const struct wlr_output_state *state) { if (!output_basic_test(output, state)) { wlr_log(WLR_ERROR, "Basic output test failed for %s", output->name); + output_clear_back_buffer(output); return false; } // Duplicate the state because we might mutate it in output_ensure_buffer struct wlr_output_state pending = *state; if (!output_ensure_buffer(output, &pending)) { + output_clear_back_buffer(output); return false; } From 99f63b03e7970093cf4b8028b21b26b656e14e6f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 5 Jun 2022 09:44:55 +0200 Subject: [PATCH 182/298] Remove remaining wl_signal_emit calls Replace them with wlr_signal_emit_safe, which correctly handles cases where a listener removes another listener. Reported-by: Isaac Freund --- render/allocator/allocator.c | 3 ++- types/tablet_v2/wlr_tablet_v2_pad.c | 15 ++++++++------- types/tablet_v2/wlr_tablet_v2_tool.c | 9 +++++---- types/wlr_buffer.c | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 6b96e0239..00dadd295 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -14,6 +14,7 @@ #include "render/allocator/drm_dumb.h" #include "render/allocator/shm.h" #include "render/wlr_renderer.h" +#include "util/signal.h" #if WLR_HAS_GBM_ALLOCATOR #include "render/allocator/gbm.h" @@ -158,7 +159,7 @@ void wlr_allocator_destroy(struct wlr_allocator *alloc) { if (alloc == NULL) { return; } - wl_signal_emit(&alloc->events.destroy, NULL); + wlr_signal_emit_safe(&alloc->events.destroy, NULL); alloc->impl->destroy(alloc); } diff --git a/types/tablet_v2/wlr_tablet_v2_pad.c b/types/tablet_v2/wlr_tablet_v2_pad.c index 58094f575..a468a1248 100644 --- a/types/tablet_v2/wlr_tablet_v2_pad.c +++ b/types/tablet_v2/wlr_tablet_v2_pad.c @@ -2,7 +2,6 @@ #define _POSIX_C_SOURCE 200809L #endif -#include "tablet-unstable-v2-protocol.h" #include #include #include @@ -12,6 +11,8 @@ #include #include #include +#include "util/signal.h" +#include "tablet-unstable-v2-protocol.h" static const struct wlr_tablet_pad_v2_grab_interface default_pad_grab_interface; @@ -49,9 +50,9 @@ static void handle_tablet_pad_ring_v2_set_feedback(struct wl_client *client, .serial = serial, .description = description, .index = aux->index - }; + }; - wl_signal_emit(&aux->pad->pad->events.ring_feedback, &evt); + wlr_signal_emit_safe(&aux->pad->pad->events.ring_feedback, &evt); } static void handle_tablet_pad_ring_v2_destroy(struct wl_client *client, @@ -87,9 +88,9 @@ static void handle_tablet_pad_strip_v2_set_feedback(struct wl_client *client, .serial = serial, .description = description, .index = aux->index - }; + }; - wl_signal_emit(&aux->pad->pad->events.strip_feedback, &evt); + wlr_signal_emit_safe(&aux->pad->pad->events.strip_feedback, &evt); } static void handle_tablet_pad_strip_v2_destroy(struct wl_client *client, @@ -114,9 +115,9 @@ static void handle_tablet_pad_v2_set_feedback( struct wl_client *client, .serial = serial, .index = button, .description = description, - }; + }; - wl_signal_emit(&pad->pad->events.button_feedback, &evt); + wlr_signal_emit_safe(&pad->pad->events.button_feedback, &evt); } static const struct zwp_tablet_pad_v2_interface tablet_pad_impl = { diff --git a/types/tablet_v2/wlr_tablet_v2_tool.c b/types/tablet_v2/wlr_tablet_v2_tool.c index 9e5b9658a..e47e91033 100644 --- a/types/tablet_v2/wlr_tablet_v2_tool.c +++ b/types/tablet_v2/wlr_tablet_v2_tool.c @@ -2,9 +2,6 @@ #define _POSIX_C_SOURCE 200809L #endif -#include "tablet-unstable-v2-protocol.h" -#include "util/array.h" -#include "util/time.h" #include #include #include @@ -13,6 +10,10 @@ #include #include #include +#include "util/array.h" +#include "util/signal.h" +#include "util/time.h" +#include "tablet-unstable-v2-protocol.h" static const struct wlr_tablet_tool_v2_grab_interface default_tool_grab_interface; @@ -46,7 +47,7 @@ static void handle_tablet_tool_v2_set_cursor(struct wl_client *client, .seat_client = tool->seat->seat_client, }; - wl_signal_emit(&tool->tool->events.set_cursor, &evt); + wlr_signal_emit_safe(&tool->tool->events.set_cursor, &evt); } static void handle_tablet_tool_v2_destroy(struct wl_client *client, diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index e50fad405..96e508b2d 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -64,7 +64,7 @@ void wlr_buffer_unlock(struct wlr_buffer *buffer) { buffer->n_locks--; if (buffer->n_locks == 0) { - wl_signal_emit(&buffer->events.release, NULL); + wlr_signal_emit_safe(&buffer->events.release, NULL); } buffer_consider_destroy(buffer); From bd7b42eb9f182b3eef62a59c9da0ed9f2660440a Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 6 Jun 2022 00:50:41 -0400 Subject: [PATCH 183/298] dmabuf: Don't leak file descriptors on error path --- render/dmabuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/dmabuf.c b/render/dmabuf.c index 3c4311590..433cb82e0 100644 --- a/render/dmabuf.c +++ b/render/dmabuf.c @@ -29,7 +29,7 @@ bool wlr_dmabuf_attributes_copy(struct wlr_dmabuf_attributes *dst, error: for (int j = 0; j < i; j++) { - close(dst->fd[i]); + close(dst->fd[j]); dst->fd[j] = -1; } dst->n_planes = 0; From 1b27d537d13c25c622bf50b8b1670e5a40b944d1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 3 Jun 2022 16:02:40 +0200 Subject: [PATCH 184/298] backend/drm: unconditionally set "content type" to graphics CTA-861-G says that "graphics" is used to indicate non-analog (ie, digital) content. With that bit set, the sink should turn off analog reconstruction and other related filtering. --- backend/drm/atomic.c | 4 ++++ backend/drm/properties.c | 1 + include/backend/drm/properties.h | 1 + 3 files changed, 6 insertions(+) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 1d4f9df43..82ead96e1 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -280,6 +280,10 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, atomic_add(&atom, conn->id, conn->props.link_status, DRM_MODE_LINK_STATUS_GOOD); } + if (active && conn->props.content_type != 0) { + atomic_add(&atom, conn->id, conn->props.content_type, + DRM_MODE_CONTENT_TYPE_GRAPHICS); + } atomic_add(&atom, crtc->id, crtc->props.mode_id, mode_id); atomic_add(&atom, crtc->id, crtc->props.active, active); if (active) { diff --git a/backend/drm/properties.c b/backend/drm/properties.c index f26965933..51fbc80a6 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -24,6 +24,7 @@ static const struct prop_info connector_info[] = { { "DPMS", INDEX(dpms) }, { "EDID", INDEX(edid) }, { "PATH", INDEX(path) }, + { "content type", INDEX(content_type) }, { "link-status", INDEX(link_status) }, { "non-desktop", INDEX(non_desktop) }, { "panel orientation", INDEX(panel_orientation) }, diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index 10c1ccd09..f6c6023ac 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -20,6 +20,7 @@ union wlr_drm_connector_props { uint32_t subconnector; // not guaranteed to exist uint32_t non_desktop; uint32_t panel_orientation; // not guaranteed to exist + uint32_t content_type; // not guaranteed to exist // atomic-modesetting only From 1f96f388e9db8ca8b196fc9f72008094fd634177 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 11:54:57 +0200 Subject: [PATCH 185/298] backend/drm: make serial optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The EDID 1.4 spec says that the serial number is optional: > If this field is not used, then enter “00h, 00h, 00h, 00h”. Leave the wlr_output.serial field NULL in that case, and hide it from the output description. --- backend/drm/drm.c | 10 +++++++--- backend/drm/util.c | 10 ++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 3a4a683fb..cca0a8d44 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1343,9 +1343,13 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, struct wlr_output *output = &wlr_conn->output; char description[128]; - snprintf(description, sizeof(description), "%s %s %s (%s%s%s)", - output->make, output->model, output->serial, output->name, - subconnector ? " via " : "", subconnector ? subconnector : ""); + snprintf(description, sizeof(description), "%s %s%s%s (%s%s%s)", + output->make, output->model, + output->serial ? " " : "", + output->serial ? output->serial : "", + output->name, + subconnector ? " via " : "", + subconnector ? subconnector : ""); wlr_output_set_description(output, description); free(subconnector); diff --git a/backend/drm/util.c b/backend/drm/util.c index eb4190926..b25d9c8c0 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -86,7 +86,11 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) uint32_t serial = data[12] | (data[13] << 8) | (data[14] << 8) | (data[15] << 8); char serial_str[32]; - snprintf(serial_str, sizeof(serial_str), "0x%08" PRIX32, serial); + if (serial != 0) { + snprintf(serial_str, sizeof(serial_str), "0x%08" PRIX32, serial); + } else { + serial_str[0] = '\0'; + } for (size_t i = 72; i <= 108; i += 18) { uint16_t flag = (data[i] << 8) | data[i + 1]; @@ -112,7 +116,9 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) } output->model = strdup(model_str); - output->serial = strdup(serial_str); + if (output->serial[0] != '\0') { + output->serial = strdup(serial_str); + } } const char *conn_get_name(uint32_t type_id) { From 5cca72958a37c3474df1975c271d8884cf3ec6d2 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 7 Jun 2022 17:08:08 +0200 Subject: [PATCH 186/298] backend/drm: fix NULL pointer deference due to typo --- backend/drm/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/drm/util.c b/backend/drm/util.c index b25d9c8c0..d56eee38f 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -116,7 +116,7 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) } output->model = strdup(model_str); - if (output->serial[0] != '\0') { + if (serial_str[0] != '\0') { output->serial = strdup(serial_str); } } From 0deef6fe44a939a47a170fa8eae55c9ea08520d9 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 3 Jun 2022 00:15:42 +0200 Subject: [PATCH 187/298] output: fix leak of empty back buffer lock This refactors output_ensure_buffer() to not mutate the state passed, making the previous subtle behavior much more explicit. Fixes: d483dd2f ("output: add wlr_output_commit_state") Closes: #3442 --- include/types/wlr_output.h | 2 +- types/output/output.c | 51 +++++++++++++++++++++++---------- types/output/render.c | 58 ++++++++++++++++++++++++++------------ 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h index 9223407a2..5f0cbe337 100644 --- a/include/types/wlr_output.h +++ b/include/types/wlr_output.h @@ -13,6 +13,6 @@ struct wlr_drm_format *output_pick_format(struct wlr_output *output, const struct wlr_drm_format_set *display_formats, uint32_t format); void output_clear_back_buffer(struct wlr_output *output); bool output_ensure_buffer(struct wlr_output *output, - struct wlr_output_state *state); + const struct wlr_output_state *state, bool *new_back_buffer); #endif diff --git a/types/output/output.c b/types/output/output.c index c69b517ff..a4cb6f740 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -677,22 +677,29 @@ static bool output_basic_test(struct wlr_output *output, bool wlr_output_test_state(struct wlr_output *output, const struct wlr_output_state *state) { - bool had_buffer = state->committed & WLR_OUTPUT_STATE_BUFFER; - - // Duplicate the state because we might mutate it in output_ensure_buffer - struct wlr_output_state pending = *state; - if (!output_basic_test(output, &pending)) { - return false; - } - if (!output_ensure_buffer(output, &pending)) { + if (!output_basic_test(output, state)) { return false; } if (!output->impl->test) { return true; } - bool success = output->impl->test(output, &pending); - if (!had_buffer) { + bool new_back_buffer = false; + if (!output_ensure_buffer(output, state, &new_back_buffer)) { + return false; + } + + // Create a shallow copy of the state with the new buffer + // potentially included to pass to the backend. + struct wlr_output_state copy = *state; + if (new_back_buffer) { + assert((copy.committed & WLR_OUTPUT_STATE_BUFFER) == 0); + copy.committed |= WLR_OUTPUT_STATE_BUFFER; + copy.buffer = output->back_buffer; + } + + bool success = output->impl->test(output, ©); + if (new_back_buffer) { output_clear_back_buffer(output); } return success; @@ -710,13 +717,23 @@ bool wlr_output_commit_state(struct wlr_output *output, return false; } - // Duplicate the state because we might mutate it in output_ensure_buffer - struct wlr_output_state pending = *state; - if (!output_ensure_buffer(output, &pending)) { + bool new_back_buffer = false; + if (!output_ensure_buffer(output, state, &new_back_buffer)) { output_clear_back_buffer(output); return false; } + // Create a shallow copy of the state with the new back buffer + // potentially included to pass to the backend. + struct wlr_output_state pending = *state; + if (new_back_buffer) { + assert((pending.committed & WLR_OUTPUT_STATE_BUFFER) == 0); + pending.committed |= WLR_OUTPUT_STATE_BUFFER; + // Lock the buffer to ensure it stays valid past the + // output_clear_back_buffer() call below. + pending.buffer = wlr_buffer_lock(output->back_buffer); + } + if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) && output->idle_frame != NULL) { wl_event_source_remove(output->idle_frame); @@ -746,6 +763,9 @@ bool wlr_output_commit_state(struct wlr_output *output, if (!output->impl->commit(output, &pending)) { wlr_buffer_unlock(back_buffer); + if (new_back_buffer) { + wlr_buffer_unlock(pending.buffer); + } return false; } @@ -820,8 +840,9 @@ bool wlr_output_commit_state(struct wlr_output *output, }; wlr_signal_emit_safe(&output->events.commit, &event); - if (back_buffer != NULL) { - wlr_buffer_unlock(back_buffer); + wlr_buffer_unlock(back_buffer); + if (new_back_buffer) { + wlr_buffer_unlock(pending.buffer); } return true; diff --git a/types/output/render.c b/types/output/render.c index ab586d645..2e38919a1 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -99,7 +99,7 @@ static bool output_create_swapchain(struct wlr_output *output, } static bool output_attach_back_buffer(struct wlr_output *output, - struct wlr_output_state *state, int *buffer_age) { + const struct wlr_output_state *state, int *buffer_age) { assert(output->back_buffer == NULL); if (!output_create_swapchain(output, state, true)) { @@ -151,11 +151,11 @@ bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) { return output_attach_render(output, &output->pending, buffer_age); } -static bool output_attach_empty_buffer(struct wlr_output *output, - struct wlr_output_state *state) { +static bool output_attach_empty_back_buffer(struct wlr_output *output, + const struct wlr_output_state *state) { assert(!(state->committed & WLR_OUTPUT_STATE_BUFFER)); - if (!output_attach_render(output, state, NULL)) { + if (!output_attach_back_buffer(output, state, NULL)) { return false; } @@ -170,8 +170,28 @@ static bool output_attach_empty_buffer(struct wlr_output *output, return true; } +static bool output_test_with_back_buffer(struct wlr_output *output, + const struct wlr_output_state *state) { + assert(output->impl->test != NULL); + + // Create a shallow copy of the state with the empty back buffer included + // to pass to the backend. + struct wlr_output_state copy = *state; + assert((copy.committed & WLR_OUTPUT_STATE_BUFFER) == 0); + copy.committed |= WLR_OUTPUT_STATE_BUFFER; + assert(output->back_buffer != NULL); + copy.buffer = output->back_buffer; + + return output->impl->test(output, ©); +} + +// This function may attach a new, empty back buffer if necessary. +// If so, the new_back_buffer out parameter will be set to true. bool output_ensure_buffer(struct wlr_output *output, - struct wlr_output_state *state) { + const struct wlr_output_state *state, + bool *new_back_buffer) { + assert(*new_back_buffer == false); + // If we're lighting up an output or changing its mode, make sure to // provide a new buffer bool needs_new_buffer = false; @@ -196,15 +216,16 @@ bool output_ensure_buffer(struct wlr_output *output, wlr_log(WLR_DEBUG, "Attaching empty buffer to output for modeset"); - if (!output_attach_empty_buffer(output, state)) { - goto error; + if (!output_attach_empty_back_buffer(output, state)) { + return false; } - if (!output->impl->test || output->impl->test(output, state)) { + + if (output_test_with_back_buffer(output, state)) { + *new_back_buffer = true; return true; } output_clear_back_buffer(output); - state->committed &= ~WLR_OUTPUT_STATE_BUFFER; if (output->swapchain->format->len == 0) { return false; @@ -217,17 +238,18 @@ bool output_ensure_buffer(struct wlr_output *output, if (!output_create_swapchain(output, state, false)) { return false; } - if (!output_attach_empty_buffer(output, state)) { - goto error; - } - if (!output->impl->test(output, state)) { - goto error; - } - return true; -error: + if (!output_attach_empty_back_buffer(output, state)) { + return false; + } + + if (output_test_with_back_buffer(output, state)) { + *new_back_buffer = true; + return true; + } + output_clear_back_buffer(output); - state->committed &= ~WLR_OUTPUT_STATE_BUFFER; + return false; } From 09498499f6e830e70883ef158de16523d4b08c6f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 18:16:48 +0200 Subject: [PATCH 188/298] output: fix make/model/serial memory leak These have been turned into `char *` in be86145322e6 ("output: turn make/model/serial into char *"), but forgot to add the cleanup logic. --- types/output/output.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types/output/output.c b/types/output/output.c index a4cb6f740..22b3e79ee 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -481,6 +481,9 @@ void wlr_output_destroy(struct wlr_output *output) { free(output->name); free(output->description); + free(output->make); + free(output->model); + free(output->serial); output_state_finish(&output->pending); From b89ed9015c3fbe8d339e9d65cf70fdca6e5645bc Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 18:18:11 +0200 Subject: [PATCH 189/298] util/global: fix memory leak on display destroy in wlr_global_destroy_safe If the display is destroyed before wlr_global_destroy_safe's timer fires, the struct destroy_global_data is leaked. This shouldn't cause issues in practice because the timer will never fire, but makes it harder to spot compositor memory leaks. --- util/global.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/util/global.c b/util/global.c index fa99a9946..93636a898 100644 --- a/util/global.c +++ b/util/global.c @@ -4,16 +4,27 @@ struct destroy_global_data { struct wl_global *global; struct wl_event_source *event_source; + struct wl_listener display_destroy; }; -static int destroy_global(void *_data) { - struct destroy_global_data *data = _data; +static void destroy_global(struct destroy_global_data *data) { + wl_list_remove(&data->display_destroy.link); wl_global_destroy(data->global); wl_event_source_remove(data->event_source); free(data); +} + +static int handle_timer_event(void *data) { + destroy_global(data); return 0; } +static void handle_display_destroy(struct wl_listener *listener, void *_data) { + struct destroy_global_data *data = + wl_container_of(listener, data, display_destroy); + destroy_global(data); +} + void wlr_global_destroy_safe(struct wl_global *global) { // Don't destroy the global immediately. If the global has been created // recently, clients might try to bind to it after we've destroyed it. @@ -33,11 +44,14 @@ void wlr_global_destroy_safe(struct wl_global *global) { } data->global = global; data->event_source = - wl_event_loop_add_timer(event_loop, destroy_global, data); + wl_event_loop_add_timer(event_loop, handle_timer_event, data); if (data->event_source == NULL) { free(data); wl_global_destroy(global); return; } wl_event_source_timer_update(data->event_source, 5000); + + data->display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &data->display_destroy); } From 0173275f7ed709dc9c3c6115bc8112bf1185d6ec Mon Sep 17 00:00:00 2001 From: Consolatis <40171-Consolatis@users.noreply.gitlab.freedesktop.org> Date: Tue, 7 Jun 2022 20:52:26 +0200 Subject: [PATCH 190/298] scene/output_layout: Fix crash in scene_output_layout_output_destroy Closes: #3448 --- types/scene/output_layout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/output_layout.c b/types/scene/output_layout.c index 900cabc30..1d1484ad1 100644 --- a/types/scene/output_layout.c +++ b/types/scene/output_layout.c @@ -26,10 +26,10 @@ struct wlr_scene_output_layout_output { static void scene_output_layout_output_destroy( struct wlr_scene_output_layout_output *solo) { - wlr_scene_output_destroy(solo->scene_output); wl_list_remove(&solo->layout_output_destroy.link); wl_list_remove(&solo->scene_output_destroy.link); wl_list_remove(&solo->link); + wlr_scene_output_destroy(solo->scene_output); free(solo); } From 6688a3d9ea40aaf345945a2df8b67e0ca1fad00f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 18:54:42 +0200 Subject: [PATCH 191/298] output: add output state setters This ensures compositors don't forget to set the committed flag or the mode_type when setting a field. --- include/wlr/types/wlr_output.h | 17 +++++++++++ types/meson.build | 1 + types/output/state.c | 52 ++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 types/output/state.c diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index d3d44132b..4f8bff0df 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -501,6 +501,23 @@ bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor); +void wlr_output_state_set_enabled(struct wlr_output_state *state, + bool enabled); +void wlr_output_state_set_mode(struct wlr_output_state *state, + struct wlr_output_mode *mode); +void wlr_output_state_set_custom_mode(struct wlr_output_state *state, + int32_t width, int32_t height, int32_t refresh); +void wlr_output_state_set_scale(struct wlr_output_state *state, float scale); +void wlr_output_state_set_transform(struct wlr_output_state *state, + enum wl_output_transform transform); +void wlr_output_state_set_adaptive_sync_enabled(struct wlr_output_state *state, + bool enabled); +void wlr_output_state_set_render_format(struct wlr_output_state *state, + uint32_t format); +void wlr_output_state_set_subpixel(struct wlr_output_state *state, + enum wl_output_subpixel subpixel); + + /** * Returns the transform that, when composed with `tr`, gives * `WL_OUTPUT_TRANSFORM_NORMAL`. diff --git a/types/meson.build b/types/meson.build index 2900561e1..16870b836 100644 --- a/types/meson.build +++ b/types/meson.build @@ -6,6 +6,7 @@ wlr_files += files( 'output/cursor.c', 'output/output.c', 'output/render.c', + 'output/state.c', 'output/transform.c', 'scene/subsurface_tree.c', 'scene/surface.c', diff --git a/types/output/state.c b/types/output/state.c new file mode 100644 index 000000000..abfe5a647 --- /dev/null +++ b/types/output/state.c @@ -0,0 +1,52 @@ +#include "types/wlr_output.h" + +void wlr_output_state_set_enabled(struct wlr_output_state *state, + bool enabled) { + state->committed |= WLR_OUTPUT_STATE_ENABLED; + state->enabled = enabled; +} + +void wlr_output_state_set_mode(struct wlr_output_state *state, + struct wlr_output_mode *mode) { + state->committed |= WLR_OUTPUT_STATE_MODE; + state->mode_type = WLR_OUTPUT_STATE_MODE_FIXED; + state->mode = mode; +} + +void wlr_output_state_set_custom_mode(struct wlr_output_state *state, + int32_t width, int32_t height, int32_t refresh) { + state->committed |= WLR_OUTPUT_STATE_MODE; + state->mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM; + state->custom_mode.width = width; + state->custom_mode.height = height; + state->custom_mode.refresh = refresh; +} + +void wlr_output_state_set_scale(struct wlr_output_state *state, float scale) { + state->committed |= WLR_OUTPUT_STATE_SCALE; + state->scale = scale; +} + +void wlr_output_state_set_transform(struct wlr_output_state *state, + enum wl_output_transform transform) { + state->committed |= WLR_OUTPUT_STATE_TRANSFORM; + state->transform = transform; +} + +void wlr_output_state_set_adaptive_sync_enabled(struct wlr_output_state *state, + bool enabled) { + state->committed |= WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; + state->adaptive_sync_enabled = enabled; +} + +void wlr_output_state_set_render_format(struct wlr_output_state *state, + uint32_t format) { + state->committed |= WLR_OUTPUT_STATE_RENDER_FORMAT; + state->render_format = format; +} + +void wlr_output_state_set_subpixel(struct wlr_output_state *state, + enum wl_output_subpixel subpixel) { + state->committed |= WLR_OUTPUT_STATE_SUBPIXEL; + state->subpixel = subpixel; +} From 43a9b0fbb900ff22f3920b3218699717bffbf61d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 19:26:02 +0200 Subject: [PATCH 192/298] output: compare state before commit Before calling wlr_output_impl.{test,commit}, perform a cheap comparison between the current and candidate state. Unset any fields which didn't change. --- types/output/output.c | 87 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 12 deletions(-) diff --git a/types/output/output.c b/types/output/output.c index 22b3e79ee..5b1a28645 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -579,6 +579,63 @@ void output_pending_resolution(struct wlr_output *output, } } +/** + * Compare a struct wlr_output_state with the current state of a struct + * wlr_output. + * + * Returns a bitfield of the unchanged fields. + * + * Some fields are not checked: damage always changes in-between frames, the + * gamma LUT is too expensive to check, the contents of the buffer might have + * changed, etc. + */ +static uint32_t output_compare_state(struct wlr_output *output, + const struct wlr_output_state *state) { + uint32_t fields = 0; + if (state->committed & WLR_OUTPUT_STATE_MODE) { + bool unchanged = false; + switch (state->mode_type) { + case WLR_OUTPUT_STATE_MODE_FIXED: + unchanged = output->current_mode == state->mode; + break; + case WLR_OUTPUT_STATE_MODE_CUSTOM: + unchanged = output->width == state->custom_mode.width && + output->height == state->custom_mode.height && + output->refresh == state->custom_mode.refresh; + break; + } + if (unchanged) { + fields |= WLR_OUTPUT_STATE_MODE; + } + } + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && output->enabled == state->enabled) { + fields |= WLR_OUTPUT_STATE_ENABLED; + } + if ((state->committed & WLR_OUTPUT_STATE_SCALE) && output->scale == state->scale) { + fields |= WLR_OUTPUT_STATE_SCALE; + } + if ((state->committed & WLR_OUTPUT_STATE_TRANSFORM) && + output->transform == state->transform) { + fields |= WLR_OUTPUT_STATE_TRANSFORM; + } + if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { + bool enabled = + output->adaptive_sync_status != WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; + if (enabled == state->adaptive_sync_enabled) { + fields |= WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; + } + } + if ((state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) && + output->render_format == state->render_format) { + fields |= WLR_OUTPUT_STATE_RENDER_FORMAT; + } + if ((state->committed & WLR_OUTPUT_STATE_SUBPIXEL) && + output->subpixel == state->subpixel) { + fields |= WLR_OUTPUT_STATE_SUBPIXEL; + } + return fields; +} + static bool output_basic_test(struct wlr_output *output, const struct wlr_output_state *state) { if (state->committed & WLR_OUTPUT_STATE_BUFFER) { @@ -680,7 +737,14 @@ static bool output_basic_test(struct wlr_output *output, bool wlr_output_test_state(struct wlr_output *output, const struct wlr_output_state *state) { - if (!output_basic_test(output, state)) { + uint32_t unchanged = output_compare_state(output, state); + + // Create a shallow copy of the state with only the fields which have been + // changed and potentially a new buffer. + struct wlr_output_state copy = *state; + copy.committed &= ~unchanged; + + if (!output_basic_test(output, ©)) { return false; } if (!output->impl->test) { @@ -688,13 +752,9 @@ bool wlr_output_test_state(struct wlr_output *output, } bool new_back_buffer = false; - if (!output_ensure_buffer(output, state, &new_back_buffer)) { + if (!output_ensure_buffer(output, ©, &new_back_buffer)) { return false; } - - // Create a shallow copy of the state with the new buffer - // potentially included to pass to the backend. - struct wlr_output_state copy = *state; if (new_back_buffer) { assert((copy.committed & WLR_OUTPUT_STATE_BUFFER) == 0); copy.committed |= WLR_OUTPUT_STATE_BUFFER; @@ -714,21 +774,24 @@ bool wlr_output_test(struct wlr_output *output) { bool wlr_output_commit_state(struct wlr_output *output, const struct wlr_output_state *state) { - if (!output_basic_test(output, state)) { + uint32_t unchanged = output_compare_state(output, state); + + // Create a shallow copy of the state with only the fields which have been + // changed and potentially a new buffer. + struct wlr_output_state pending = *state; + pending.committed &= ~unchanged; + + if (!output_basic_test(output, &pending)) { wlr_log(WLR_ERROR, "Basic output test failed for %s", output->name); output_clear_back_buffer(output); return false; } bool new_back_buffer = false; - if (!output_ensure_buffer(output, state, &new_back_buffer)) { + if (!output_ensure_buffer(output, &pending, &new_back_buffer)) { output_clear_back_buffer(output); return false; } - - // Create a shallow copy of the state with the new back buffer - // potentially included to pass to the backend. - struct wlr_output_state pending = *state; if (new_back_buffer) { assert((pending.committed & WLR_OUTPUT_STATE_BUFFER) == 0); pending.committed |= WLR_OUTPUT_STATE_BUFFER; From c2e4ba1dd092ac8dcd393c6f9ab317fcd3a8dce6 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 19:32:20 +0200 Subject: [PATCH 193/298] output: use state setters in wlr_output_set_* --- types/output/output.c | 83 +++++-------------------------------------- 1 file changed, 8 insertions(+), 75 deletions(-) diff --git a/types/output/output.c b/types/output/output.c index 5b1a28645..ae18ea8de 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -205,52 +205,17 @@ static void output_update_matrix(struct wlr_output *output) { } void wlr_output_enable(struct wlr_output *output, bool enable) { - if (output->enabled == enable) { - output->pending.committed &= ~WLR_OUTPUT_STATE_ENABLED; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_ENABLED; - output->pending.enabled = enable; -} - -static void output_state_clear_mode(struct wlr_output_state *state) { - if (!(state->committed & WLR_OUTPUT_STATE_MODE)) { - return; - } - - state->mode = NULL; - - state->committed &= ~WLR_OUTPUT_STATE_MODE; + wlr_output_state_set_enabled(&output->pending, enable); } void wlr_output_set_mode(struct wlr_output *output, struct wlr_output_mode *mode) { - output_state_clear_mode(&output->pending); - - if (output->current_mode == mode) { - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_MODE; - output->pending.mode_type = WLR_OUTPUT_STATE_MODE_FIXED; - output->pending.mode = mode; + wlr_output_state_set_mode(&output->pending, mode); } void wlr_output_set_custom_mode(struct wlr_output *output, int32_t width, int32_t height, int32_t refresh) { - output_state_clear_mode(&output->pending); - - if (output->width == width && output->height == height && - output->refresh == refresh) { - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_MODE; - output->pending.mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM; - output->pending.custom_mode.width = width; - output->pending.custom_mode.height = height; - output->pending.custom_mode.refresh = refresh; + wlr_output_state_set_custom_mode(&output->pending, width, height, refresh); } void wlr_output_update_mode(struct wlr_output *output, @@ -295,56 +260,24 @@ void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width, void wlr_output_set_transform(struct wlr_output *output, enum wl_output_transform transform) { - if (output->transform == transform) { - output->pending.committed &= ~WLR_OUTPUT_STATE_TRANSFORM; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_TRANSFORM; - output->pending.transform = transform; + wlr_output_state_set_transform(&output->pending, transform); } void wlr_output_set_scale(struct wlr_output *output, float scale) { - if (output->scale == scale) { - output->pending.committed &= ~WLR_OUTPUT_STATE_SCALE; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_SCALE; - output->pending.scale = scale; + wlr_output_state_set_scale(&output->pending, scale); } void wlr_output_enable_adaptive_sync(struct wlr_output *output, bool enabled) { - bool currently_enabled = - output->adaptive_sync_status != WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; - if (currently_enabled == enabled) { - output->pending.committed &= ~WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; - output->pending.adaptive_sync_enabled = enabled; + wlr_output_state_set_adaptive_sync_enabled(&output->pending, enabled); } void wlr_output_set_render_format(struct wlr_output *output, uint32_t format) { - if (output->render_format == format) { - output->pending.committed &= ~WLR_OUTPUT_STATE_RENDER_FORMAT; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_RENDER_FORMAT; - output->pending.render_format = format; + wlr_output_state_set_render_format(&output->pending, format); } void wlr_output_set_subpixel(struct wlr_output *output, enum wl_output_subpixel subpixel) { - if (output->subpixel == subpixel) { - output->pending.committed &= ~WLR_OUTPUT_STATE_SUBPIXEL; - return; - } - - output->pending.committed |= WLR_OUTPUT_STATE_SUBPIXEL; - output->pending.subpixel = subpixel; + wlr_output_state_set_subpixel(&output->pending, subpixel); } void wlr_output_set_name(struct wlr_output *output, const char *name) { From c2e046022f36001fd2b9fd369ac14acf73a20e23 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 23:13:33 +0200 Subject: [PATCH 194/298] render/gles2: simplify flipped projection Instead of computing the projection, then flipping, just provide the correct transform to wlr_matrix_projection(). --- render/gles2/renderer.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index e7bfe0e00..c47081aed 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -204,7 +204,7 @@ static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, // refresh projection matrix wlr_matrix_projection(renderer->projection, width, height, - WL_OUTPUT_TRANSFORM_NORMAL); + WL_OUTPUT_TRANSFORM_FLIPPED_180); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); @@ -245,12 +245,6 @@ static void gles2_scissor(struct wlr_renderer *wlr_renderer, pop_gles2_debug(renderer); } -static const float flip_180[9] = { - 1.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.0f, 0.0f, 1.0f, -}; - static bool gles2_render_subtexture_with_matrix( struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, const struct wlr_fbox *box, const float matrix[static 9], @@ -286,7 +280,6 @@ static bool gles2_render_subtexture_with_matrix( float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); - wlr_matrix_multiply(gl_matrix, flip_180, gl_matrix); // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE @@ -346,7 +339,6 @@ static void gles2_render_quad_with_matrix(struct wlr_renderer *wlr_renderer, float gl_matrix[9]; wlr_matrix_multiply(gl_matrix, renderer->projection, matrix); - wlr_matrix_multiply(gl_matrix, flip_180, gl_matrix); // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE From 96b594110ddbb4ab133ef4c9030a7c416175b20e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 23:15:34 +0200 Subject: [PATCH 195/298] matrix: remove wlr_matrix_projection() 69477051ccff ("matrix: deprecate wlr_matrix_projection") marked it as deprecated. 1 year later, we can now remove it from our public API. --- include/types/wlr_matrix.h | 15 +++++++++++++++ include/wlr/types/wlr_matrix.h | 8 -------- render/gles2/renderer.c | 3 ++- render/vulkan/renderer.c | 5 +++-- types/wlr_matrix.c | 4 ++-- 5 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 include/types/wlr_matrix.h diff --git a/include/types/wlr_matrix.h b/include/types/wlr_matrix.h new file mode 100644 index 000000000..ce599dc1b --- /dev/null +++ b/include/types/wlr_matrix.h @@ -0,0 +1,15 @@ +#ifndef TYPES_WLR_MATRIX_H +#define TYPES_WLR_MATRIX_H + +#include + +/** + * Writes a 2D orthographic projection matrix to mat of (width, height) with a + * specified wl_output_transform. + * + * Equivalent to glOrtho(0, width, 0, height, 1, -1) with the transform applied. + */ +void matrix_projection(float mat[static 9], int width, int height, + enum wl_output_transform transform); + +#endif diff --git a/include/wlr/types/wlr_matrix.h b/include/wlr/types/wlr_matrix.h index 1a8b5be53..043cf6d35 100644 --- a/include/wlr/types/wlr_matrix.h +++ b/include/wlr/types/wlr_matrix.h @@ -43,14 +43,6 @@ void wlr_matrix_rotate(float mat[static 9], float rad); void wlr_matrix_transform(float mat[static 9], enum wl_output_transform transform); -/** Writes a 2D orthographic projection matrix to mat of (width, height) with a - * specified wl_output_transform. - * - * Deprecated: this function is deprecated and will be removed in a future - * version of wlroots. */ -void wlr_matrix_projection(float mat[static 9], int width, int height, - enum wl_output_transform transform); - /** Shortcut for the various matrix operations involved in projecting the * specified wlr_box onto a given orthographic projection with a given * rotation. The result is written to mat, which can be applied to each diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index c47081aed..5a2f31b55 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -17,6 +17,7 @@ #include "render/egl.h" #include "render/gles2.h" #include "render/pixel_format.h" +#include "types/wlr_matrix.h" static const GLfloat verts[] = { 1, 0, // top right @@ -203,7 +204,7 @@ static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, renderer->viewport_height = height; // refresh projection matrix - wlr_matrix_projection(renderer->projection, width, height, + matrix_projection(renderer->projection, width, height, WL_OUTPUT_TRANSFORM_FLIPPED_180); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 21b36bdd6..c373269df 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -23,6 +23,7 @@ #include "render/vulkan/shaders/texture.frag.h" #include "render/vulkan/shaders/quad.frag.h" #include "types/wlr_buffer.h" +#include "types/wlr_matrix.h" // TODO: // - simplify stage allocation, don't track allocations but use ringbuffer-like @@ -564,9 +565,9 @@ static void vulkan_begin(struct wlr_renderer *wlr_renderer, vkCmdSetScissor(cb, 0, 1, &rect); // Refresh projection matrix. - // wlr_matrix_projection assumes a GL corrdinate system so we need + // matrix_projection() assumes a GL coordinate system so we need // to pass WL_OUTPUT_TRANSFORM_FLIPPED_180 to adjust it for vulkan. - wlr_matrix_projection(renderer->projection, width, height, + matrix_projection(renderer->projection, width, height, WL_OUTPUT_TRANSFORM_FLIPPED_180); renderer->render_width = width; diff --git a/types/wlr_matrix.c b/types/wlr_matrix.c index a1b2b31a1..7b6671f57 100644 --- a/types/wlr_matrix.c +++ b/types/wlr_matrix.c @@ -4,6 +4,7 @@ #include #include #include +#include "types/wlr_matrix.h" void wlr_matrix_identity(float mat[static 9]) { static const float identity[9] = { @@ -117,8 +118,7 @@ void wlr_matrix_transform(float mat[static 9], wlr_matrix_multiply(mat, mat, transforms[transform]); } -// Equivalent to glOrtho(0, width, 0, height, 1, -1) with the transform applied -void wlr_matrix_projection(float mat[static 9], int width, int height, +void matrix_projection(float mat[static 9], int width, int height, enum wl_output_transform transform) { memset(mat, 0, sizeof(*mat) * 9); From d57d2e0e368bbf0b94246a3f6dbeb26c7b048993 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Wed, 8 Jun 2022 20:27:50 +0100 Subject: [PATCH 196/298] scene/layer_shell_v1.c: fix bug in width/height calculations ...in wlr_scene_layer_surface_v1_configure() Reproduce bug with waybar by setting `"margin": 5,` in ~/.config/waybar/config. It will result in the right edge of the panel extending outside the edge of the output. The bug can also be reproduced with gtk-layer-demo by anchoring left/right/top/bottom and setting respective margins Relates-to: https://github.com/labwc/labwc/issues/382 --- types/scene/layer_shell_v1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/scene/layer_shell_v1.c b/types/scene/layer_shell_v1.c index eb0bc76e3..b674cd362 100644 --- a/types/scene/layer_shell_v1.c +++ b/types/scene/layer_shell_v1.c @@ -94,7 +94,7 @@ void wlr_scene_layer_surface_v1_configure( if (box.width == 0) { box.x = bounds.x + state->margin.left; box.width = bounds.width - - state->margin.left + state->margin.right; + (state->margin.left + state->margin.right); } else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT && state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) { box.x = bounds.x + bounds.width/2 -box.width/2; @@ -110,7 +110,7 @@ void wlr_scene_layer_surface_v1_configure( if (box.height == 0) { box.y = bounds.y + state->margin.top; box.height = bounds.height - - state->margin.top + state->margin.bottom; + (state->margin.top + state->margin.bottom); } else if (state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP && state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM) { box.y = bounds.y + bounds.height/2 - box.height/2; From e7b217efb97b603ba992b48fee21b58cc2b3644e Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 11 Jun 2022 20:22:54 +0300 Subject: [PATCH 197/298] xdg-shell: improve shell version check --- types/xdg_shell/wlr_xdg_toplevel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index a7ca8257c..f929508ff 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -506,7 +506,8 @@ uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_toplevel *toplevel, uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, uint32_t tiled) { - assert(toplevel->base->client->shell->version >= 2); + assert(toplevel->base->client->shell->version >= + XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION); toplevel->scheduled.tiled = tiled; return wlr_xdg_surface_schedule_configure(toplevel->base); } From 35d1bcff6f6320442e6d3af52b3501b424eefc2b Mon Sep 17 00:00:00 2001 From: bi4k8 Date: Sat, 11 Jun 2022 20:25:35 +0000 Subject: [PATCH 198/298] render/vulkan/pixel_format: do not leak props->... `vulkan_format_props_query` calls `query_modifier_support` which initializes fields of `props` with allocated memory. this memory is leaked if `query_modifier_support` does not find a supported format and shmtex is not supported, as in this case `add_fmt_props` ends up being false and the allocated fields of `props` are never freed. --- render/vulkan/pixel_format.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/render/vulkan/pixel_format.c b/render/vulkan/pixel_format.c index cfab5ffe8..01ac6c7af 100644 --- a/render/vulkan/pixel_format.c +++ b/render/vulkan/pixel_format.c @@ -296,6 +296,8 @@ void vulkan_format_props_query(struct wlr_vk_device *dev, if (add_fmt_props) { dev->format_props[dev->format_prop_count] = props; ++dev->format_prop_count; + } else { + vulkan_format_props_finish(props); } } From f295aff7629eed3a059438a6f404950b939ea0c0 Mon Sep 17 00:00:00 2001 From: bi4k8 Date: Sat, 11 Jun 2022 20:41:16 +0000 Subject: [PATCH 199/298] Add missing & --- render/vulkan/pixel_format.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/vulkan/pixel_format.c b/render/vulkan/pixel_format.c index 01ac6c7af..b4c400700 100644 --- a/render/vulkan/pixel_format.c +++ b/render/vulkan/pixel_format.c @@ -297,7 +297,7 @@ void vulkan_format_props_query(struct wlr_vk_device *dev, dev->format_props[dev->format_prop_count] = props; ++dev->format_prop_count; } else { - vulkan_format_props_finish(props); + vulkan_format_props_finish(&props); } } From 369c6525d798f78231b4ce5830d30af85c7c5997 Mon Sep 17 00:00:00 2001 From: bi4k8 Date: Sat, 11 Jun 2022 20:08:17 +0000 Subject: [PATCH 200/298] render/egl: don't leak memory on error return --- render/egl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/render/egl.c b/render/egl.c index dfba8edd3..168e358c6 100644 --- a/render/egl.c +++ b/render/egl.c @@ -552,6 +552,7 @@ struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display, } if (!egl_init_display(egl, display)) { + free(egl); return NULL; } From f28c0e2046c59aeb9f014ef4c22d4517e38f4721 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 14 Jun 2022 10:08:54 +0200 Subject: [PATCH 201/298] gitignore: remove build dir entries Meson creates a .gitignore file in its build directories [1] so that they never get added to Git. These entries assume users will pick a specific build dir name, so they don't work with e.g. "builddir". [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3582#note_1424666 --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1d1908c83..d73983bfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ -/build/ -/build-*/ /subprojects/ From 29291cb47cdaa72d1142a008fef3301dcb86dfac Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 16 Jun 2022 14:43:24 +0200 Subject: [PATCH 202/298] render/texture: drop wlr_texture_is_opaque Whether a texture is opaque or not doesn't depend on the renderer at all, it just depends on the source buffer. Instead of forcing all renderers to implement wlr_texture_impl.is_opaque, let's move this in common code and use the wlr_buffer format to know whether a texture will be opaque. --- include/types/wlr_buffer.h | 9 +++++++++ include/wlr/render/interface.h | 1 - include/wlr/render/wlr_texture.h | 5 ----- include/wlr/types/wlr_compositor.h | 2 ++ render/gles2/texture.c | 6 ------ render/pixman/renderer.c | 6 ------ render/vulkan/texture.c | 9 --------- render/wlr_texture.c | 7 ------- types/wlr_buffer.c | 26 ++++++++++++++++++++++++++ types/wlr_compositor.c | 6 +++++- 10 files changed, 42 insertions(+), 35 deletions(-) diff --git a/include/types/wlr_buffer.h b/include/types/wlr_buffer.h index bdb6e5b7f..e7097ae25 100644 --- a/include/types/wlr_buffer.h +++ b/include/types/wlr_buffer.h @@ -69,4 +69,13 @@ struct wlr_dmabuf_buffer *dmabuf_buffer_create( */ bool dmabuf_buffer_drop(struct wlr_dmabuf_buffer *buffer); +/** + * Check whether a buffer is fully opaque. + * + * When true is returned, the buffer is guaranteed to be fully opaque, but the + * reverse is not true: false may be returned in cases where the buffer is fully + * opaque. + */ +bool buffer_is_opaque(struct wlr_buffer *buffer); + #endif diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 4207bd304..7e923353e 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -54,7 +54,6 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl); struct wlr_texture_impl { - bool (*is_opaque)(struct wlr_texture *texture); bool (*write_pixels)(struct wlr_texture *texture, uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 93fc221c3..0f39b8a89 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -36,11 +36,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_attributes *attribs); -/** - * Returns true if this texture is using a fully opaque format. - */ -bool wlr_texture_is_opaque(struct wlr_texture *texture); - /** * Update a texture with raw pixels. The texture must be mutable, and the input * data must have the same pixel format that the texture was created with. diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index bff6bc833..034b075b1 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -162,6 +162,8 @@ struct wlr_surface { int width, height; int buffer_width, buffer_height; } previous; + + bool opaque; }; struct wlr_renderer; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 574207448..d794e436b 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -29,11 +29,6 @@ struct wlr_gles2_texture *gles2_get_texture( return (struct wlr_gles2_texture *)wlr_texture; } -static bool gles2_texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - return !texture->has_alpha; -} - static bool check_stride(const struct wlr_pixel_format_info *fmt, uint32_t stride, uint32_t width) { if (stride % (fmt->bpp / 8) != 0) { @@ -161,7 +156,6 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = gles2_texture_is_opaque, .write_pixels = gles2_texture_write_pixels, .destroy = gles2_texture_unref, }; diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 13db08800..2853b7047 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -46,11 +46,6 @@ static struct wlr_pixman_texture *get_texture( return (struct wlr_pixman_texture *)wlr_texture; } -static bool texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_pixman_texture *texture = get_texture(wlr_texture); - return !texture->format_info->has_alpha; -} - static void texture_destroy(struct wlr_texture *wlr_texture) { struct wlr_pixman_texture *texture = get_texture(wlr_texture); wl_list_remove(&texture->link); @@ -61,7 +56,6 @@ static void texture_destroy(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = texture_is_opaque, .destroy = texture_destroy, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 26af98676..35b9562e7 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -33,14 +33,6 @@ static VkImageAspectFlagBits mem_plane_aspect(unsigned i) { } } -static bool vulkan_texture_is_opaque(struct wlr_texture *wlr_texture) { - struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); - const struct wlr_pixel_format_info *format_info = drm_get_pixel_format_info( - texture->format->drm_format); - assert(format_info); - return !format_info->has_alpha; -} - // Will transition the texture to shaderReadOnlyOptimal layout for reading // from fragment shader later on static bool write_pixels(struct wlr_texture *wlr_texture, @@ -199,7 +191,6 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .is_opaque = vulkan_texture_is_opaque, .write_pixels = vulkan_texture_write_pixels, .destroy = vulkan_texture_unref, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 36cbf136d..fa864d02b 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -71,13 +71,6 @@ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, return renderer->impl->texture_from_buffer(renderer, buffer); } -bool wlr_texture_is_opaque(struct wlr_texture *texture) { - if (!texture->impl->is_opaque) { - return false; - } - return texture->impl->is_opaque(texture); -} - bool wlr_texture_write_pixels(struct wlr_texture *texture, uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 96e508b2d..49e205f3c 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -237,6 +237,32 @@ struct wlr_buffer *wlr_buffer_from_resource(struct wl_resource *resource) { return buffer; } +bool buffer_is_opaque(struct wlr_buffer *buffer) { + void *data; + uint32_t format; + size_t stride; + struct wlr_dmabuf_attributes dmabuf; + struct wlr_shm_attributes shm; + if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { + format = dmabuf.format; + } else if (wlr_buffer_get_shm(buffer, &shm)) { + format = shm.format; + } else if (wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + wlr_buffer_end_data_ptr_access(buffer); + } else { + return false; + } + + const struct wlr_pixel_format_info *format_info = + drm_get_pixel_format_info(format); + if (format_info == NULL) { + return false; + } + + return !format_info->has_alpha; +} + struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, struct wlr_renderer *renderer) { struct wlr_texture *texture = wlr_texture_from_buffer(renderer, buffer); diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 8b84a6439..c1cdc3b05 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -10,6 +10,7 @@ #include #include #include +#include "types/wlr_buffer.h" #include "types/wlr_region.h" #include "util/signal.h" #include "util/time.h" @@ -336,9 +337,12 @@ static void surface_apply_damage(struct wlr_surface *surface) { wlr_buffer_unlock(&surface->buffer->base); } surface->buffer = NULL; + surface->opaque = false; return; } + surface->opaque = buffer_is_opaque(surface->current.buffer); + if (surface->buffer != NULL) { if (wlr_client_buffer_apply_damage(surface->buffer, surface->current.buffer, &surface->buffer_damage)) { @@ -372,7 +376,7 @@ static void surface_update_opaque_region(struct wlr_surface *surface) { return; } - if (wlr_texture_is_opaque(texture)) { + if (surface->opaque) { pixman_region32_init_rect(&surface->opaque_region, 0, 0, surface->current.width, surface->current.height); return; From d89285f7835d87cb873e2c5de1219ebdaae5d929 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 21:52:47 +0200 Subject: [PATCH 203/298] output-management-v1: add wlr_output_head_v1_state_apply() This function applies a configuration sent by a client on a struct wlr_output_state. --- include/wlr/types/wlr_output_management_v1.h | 12 +++++++++++ types/wlr_output_management_v1.c | 22 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/wlr/types/wlr_output_management_v1.h b/include/wlr/types/wlr_output_management_v1.h index 0b8d8c207..be56e8127 100644 --- a/include/wlr/types/wlr_output_management_v1.h +++ b/include/wlr/types/wlr_output_management_v1.h @@ -141,4 +141,16 @@ struct wlr_output_configuration_head_v1 * wlr_output_configuration_head_v1_create( struct wlr_output_configuration_v1 *config, struct wlr_output *output); +/** + * Apply the head state on the supplied struct wlr_output_state. + * + * Compositors can then pass the resulting struct wlr_output_state to + * wlr_output_commit_state() or wlr_output_test_state(). + * + * The position needs to be applied manually by the caller. + */ +void wlr_output_head_v1_state_apply( + const struct wlr_output_head_v1_state *head_state, + struct wlr_output_state *output_state); + #endif diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index 2c3ae0275..c44352f17 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -907,3 +907,25 @@ void wlr_output_manager_v1_set_configuration( } manager->current_configuration_dirty = false; } + +void wlr_output_head_v1_state_apply( + const struct wlr_output_head_v1_state *head_state, + struct wlr_output_state *output_state) { + wlr_output_state_set_enabled(output_state, head_state->enabled); + + if (!head_state->enabled) { + return; + } + + if (head_state->mode != NULL) { + wlr_output_state_set_mode(output_state, head_state->mode); + } else { + wlr_output_state_set_custom_mode(output_state, + head_state->custom_mode.width, + head_state->custom_mode.height, + head_state->custom_mode.refresh); + } + + wlr_output_state_set_scale(output_state, head_state->scale); + wlr_output_state_set_transform(output_state, head_state->transform); +} From 1f1c0275be21f02a430b3a9fd51bba9ba5be57d1 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 9 Jun 2022 16:35:44 +0200 Subject: [PATCH 204/298] backend/drm: remove unused CRTC count check drmIsKMS already checks for this. --- backend/drm/drm.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index cca0a8d44..1c22878c3 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1185,14 +1185,6 @@ static void disconnect_drm_connector(struct wlr_drm_connector *conn); void scan_drm_connectors(struct wlr_drm_backend *drm, struct wlr_device_hotplug_event *event) { - /* - * This GPU is not really a modesetting device. - * It's just being used as a renderer. - */ - if (drm->num_crtcs == 0) { - return; - } - if (event != NULL && event->connector_id != 0) { wlr_log(WLR_INFO, "Scanning DRM connector %"PRIu32" on %s", event->connector_id, drm->name); From 1d581656c756fd17a6cf55474d32586f6769663f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Jun 2022 15:03:39 +0200 Subject: [PATCH 205/298] backend/drm: set "max bpc" to the max "max bpc" is a maximum value, the driver is free to choose a smaller value depending on the bandwidth available. Some faulty monitors misbehave with higher bpc values. We'll add a workaround if users get hit by these in practice. References: https://gitlab.freedesktop.org/wayland/weston/-/issues/612 --- backend/drm/atomic.c | 3 +++ backend/drm/drm.c | 8 ++++++++ backend/drm/properties.c | 27 +++++++++++++++++++++++++++ include/backend/drm/drm.h | 1 + include/backend/drm/properties.h | 4 ++++ 5 files changed, 43 insertions(+) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 82ead96e1..ab1b21601 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -284,6 +284,9 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, atomic_add(&atom, conn->id, conn->props.content_type, DRM_MODE_CONTENT_TYPE_GRAPHICS); } + if (active && conn->props.max_bpc != 0 && conn->max_bpc > 0) { + atomic_add(&atom, conn->id, conn->props.max_bpc, conn->max_bpc); + } atomic_add(&atom, crtc->id, crtc->props.mode_id, mode_id); atomic_add(&atom, crtc->id, crtc->props.active, active); if (active) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 1c22878c3..262a533e6 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1317,6 +1317,14 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_conn->output.non_desktop = non_desktop; } + wlr_conn->max_bpc = 0; + if (wlr_conn->props.max_bpc != 0) { + if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc, + NULL, &wlr_conn->max_bpc)) { + wlr_log(WLR_ERROR, "Failed to introspect 'max bpc' property"); + } + } + size_t edid_len = 0; uint8_t *edid = get_drm_prop_blob(drm->fd, wlr_conn->id, wlr_conn->props.edid, &edid_len); diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 51fbc80a6..4f4951771 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -26,6 +27,7 @@ static const struct prop_info connector_info[] = { { "PATH", INDEX(path) }, { "content type", INDEX(content_type) }, { "link-status", INDEX(link_status) }, + { "max bpc", INDEX(max_bpc) }, { "non-desktop", INDEX(non_desktop) }, { "panel orientation", INDEX(panel_orientation) }, { "subconnector", INDEX(subconnector) }, @@ -181,3 +183,28 @@ char *get_drm_prop_enum(int fd, uint32_t obj, uint32_t prop_id) { return str; } + +bool introspect_drm_prop_range(int fd, uint32_t prop_id, + uint64_t *min, uint64_t *max) { + drmModePropertyRes *prop = drmModeGetProperty(fd, prop_id); + if (!prop) { + return false; + } + + if (drmModeGetPropertyType(prop) != DRM_MODE_PROP_RANGE) { + drmModeFreeProperty(prop); + return false; + } + + assert(prop->count_values == 2); + + if (min != NULL) { + *min = prop->values[0]; + } + if (max != NULL) { + *max = prop->values[1]; + } + + drmModeFreeProperty(prop); + return true; +} diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index dbc47364b..700ed6546 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -119,6 +119,7 @@ struct wlr_drm_connector { enum wlr_drm_connector_status status; bool desired_enabled; uint32_t id; + uint64_t max_bpc; struct wlr_drm_lease *lease; struct wlr_drm_crtc *crtc; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index f6c6023ac..b6ca14f19 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -21,6 +21,7 @@ union wlr_drm_connector_props { uint32_t non_desktop; uint32_t panel_orientation; // not guaranteed to exist uint32_t content_type; // not guaranteed to exist + uint32_t max_bpc; // not guaranteed to exist // atomic-modesetting only @@ -76,4 +77,7 @@ bool get_drm_prop(int fd, uint32_t obj, uint32_t prop, uint64_t *ret); void *get_drm_prop_blob(int fd, uint32_t obj, uint32_t prop, size_t *ret_len); char *get_drm_prop_enum(int fd, uint32_t obj, uint32_t prop); +bool introspect_drm_prop_range(int fd, uint32_t prop_id, + uint64_t *min, uint64_t *max); + #endif From 2a1d7d40f4987bda17637796ce2aeae67370b1e3 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 20 Jun 2022 08:36:40 +0200 Subject: [PATCH 206/298] cursor: re-enable NULL buffer for cursor The previous wlr_output_cursor_set_image() allows setting a NULL buffer for the cursor to hide it. This functionality was used by sway to hide the cursor, restore the original semantics by allowing NULL buffers again by avoiding the wlr_buffer allocation in case we have NULL pixels and handing a NULL wlr_buffer to wlr_output_cursor_set_buffer(). --- types/output/cursor.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/types/output/cursor.c b/types/output/cursor.c index bd6f757ef..85973ce93 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -376,15 +376,19 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor, const uint8_t *pixels, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { - struct wlr_readonly_data_buffer *buffer = - readonly_data_buffer_create(DRM_FORMAT_ARGB8888, stride, width, height, - pixels); - if (buffer == NULL) { - return false; + struct wlr_buffer *buffer = NULL; + + if (pixels) { + struct wlr_readonly_data_buffer *ro_buffer = readonly_data_buffer_create( + DRM_FORMAT_ARGB8888, stride, width, height, pixels); + if (ro_buffer == NULL) { + return false; + } + buffer = &ro_buffer->base; } - bool ok = wlr_output_cursor_set_buffer(cursor, &buffer->base, - hotspot_x, hotspot_y); - wlr_buffer_drop(&buffer->base); + bool ok = wlr_output_cursor_set_buffer(cursor, buffer, hotspot_x, hotspot_y); + + wlr_buffer_drop(buffer); return ok; } From ec8b49c93f869010e360bec501d61c18089fbc61 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 21 Jun 2022 14:00:48 +0300 Subject: [PATCH 207/298] subcompositor: consider map on creation wl_subsurface description states: A sub-surface becomes mapped, when a non-NULL wl_buffer is applied and the parent surface is mapped. Note that this doesn't require an explicit commit, which means that a newly created subsurface with a mapped parent and a buffer already attached must be mapped immediately. This can happen with the following sequence of events: - subcompositor.get_subsurface(subsurface, surface, parent) - surface.attach(buffer) - surface.commit() - subsurface.destroy() - subcompositor.get_subsurface(subsurface, surface, parent) Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3449 --- types/wlr_subcompositor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/wlr_subcompositor.c b/types/wlr_subcompositor.c index 2b9b97cd2..9467ec3c7 100644 --- a/types/wlr_subcompositor.c +++ b/types/wlr_subcompositor.c @@ -374,6 +374,8 @@ static struct wlr_subsurface *subsurface_create(struct wlr_surface *surface, surface->role_data = subsurface; + subsurface_consider_map(subsurface, true); + return subsurface; } From 8d2fa15e9d7c07f9230f20deffd6ca4ba1078853 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 21 Jun 2022 17:34:25 +0300 Subject: [PATCH 208/298] xdg-toplevel: post no memory on strdup() fail --- types/xdg_shell/wlr_xdg_toplevel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index f929508ff..dee2571fb 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -157,6 +157,7 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client, tmp = strdup(title); if (tmp == NULL) { + wl_resource_post_no_memory(resource); return; } @@ -173,6 +174,7 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client, tmp = strdup(app_id); if (tmp == NULL) { + wl_resource_post_no_memory(resource); return; } From 5c4384a1330faedf975c8b8644881d50390f3613 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 21 Jun 2022 07:42:58 +0300 Subject: [PATCH 209/298] xdg-popup: use configure fields --- include/wlr/types/wlr_xdg_shell.h | 7 +++++-- types/xdg_shell/wlr_xdg_popup.c | 13 +++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index f6b3b362b..802f03a5e 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -83,11 +83,14 @@ struct wlr_xdg_popup_state { bool reactive; }; +enum wlr_xdg_popup_configure_field { + WLR_XDG_POPUP_CONFIGURE_REPOSITION_TOKEN = 1 << 0, +}; + struct wlr_xdg_popup_configure { + uint32_t fields; // enum wlr_xdg_popup_configure_field struct wlr_box geometry; struct wlr_xdg_positioner_rules rules; - - bool has_reposition_token; uint32_t reposition_token; }; diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index 5f8cd4540..adf94c032 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -21,10 +21,12 @@ struct wlr_xdg_popup_configure *send_xdg_popup_configure( } *configure = popup->scheduled; - if (popup->scheduled.has_reposition_token) { - popup->scheduled.has_reposition_token = false; + uint32_t version = wl_resource_get_version(popup->resource); + + if ((configure->fields & WLR_XDG_POPUP_CONFIGURE_REPOSITION_TOKEN) && + version >= XDG_POPUP_REPOSITIONED_SINCE_VERSION) { xdg_popup_send_repositioned(popup->resource, - popup->scheduled.reposition_token); + configure->reposition_token); } struct wlr_box *geometry = &configure->geometry; @@ -32,6 +34,8 @@ struct wlr_xdg_popup_configure *send_xdg_popup_configure( geometry->x, geometry->y, geometry->width, geometry->height); + popup->scheduled.fields = 0; + return configure; } @@ -315,7 +319,8 @@ static void xdg_popup_handle_reposition( wlr_xdg_positioner_rules_get_geometry( &positioner->rules, &popup->scheduled.geometry); popup->scheduled.rules = positioner->rules; - popup->scheduled.has_reposition_token = true; + + popup->scheduled.fields |= WLR_XDG_POPUP_CONFIGURE_REPOSITION_TOKEN; popup->scheduled.reposition_token = token; wlr_xdg_surface_schedule_configure(popup->base); From 91943a68a6976ef7c4cc70afc07954a00fae678b Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 20 Jun 2022 16:57:29 +0200 Subject: [PATCH 210/298] wlr_input_device: remove anon union field This union is unnecessary since the recent input device refactor and can now be replaced by wlr_*_from_input_device() functions. --- backend/libinput/backend.c | 12 +++--- backend/libinput/events.c | 18 ++++++--- backend/wayland/seat.c | 10 ++--- backend/x11/input_device.c | 6 +-- examples/multi-pointer.c | 10 ++--- examples/output-layout.c | 10 ++--- examples/pointer.c | 10 ++--- examples/quads.c | 10 ++--- examples/rotation.c | 10 ++--- examples/simple.c | 10 ++--- examples/tablet.c | 30 +++++++-------- examples/touch.c | 20 +++++----- include/wlr/types/wlr_input_device.h | 11 ------ include/wlr/types/wlr_keyboard.h | 8 ++++ include/wlr/types/wlr_pointer.h | 8 ++++ include/wlr/types/wlr_switch.h | 8 ++++ include/wlr/types/wlr_tablet_pad.h | 8 ++++ include/wlr/types/wlr_tablet_tool.h | 8 ++++ include/wlr/types/wlr_touch.h | 8 ++++ tinywl/tinywl.c | 12 +++--- types/tablet_v2/wlr_tablet_v2_pad.c | 2 +- types/tablet_v2/wlr_tablet_v2_tablet.c | 2 +- types/wlr_cursor.c | 53 ++++++++++++++------------ types/wlr_keyboard.c | 7 +++- types/wlr_pointer.c | 8 +++- types/wlr_switch.c | 8 +++- types/wlr_tablet_pad.c | 8 +++- types/wlr_tablet_tool.c | 8 +++- types/wlr_touch.c | 8 +++- types/wlr_virtual_keyboard_v1.c | 10 +++-- types/wlr_virtual_pointer_v1.c | 5 +-- 31 files changed, 216 insertions(+), 130 deletions(-) diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 60f456cc1..f47121dbe 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -228,22 +228,22 @@ struct libinput_device *wlr_libinput_get_device_handle( struct wlr_libinput_input_device *dev = NULL; switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - dev = device_from_keyboard(wlr_dev->keyboard); + dev = device_from_keyboard(wlr_keyboard_from_input_device(wlr_dev)); break; case WLR_INPUT_DEVICE_POINTER: - dev = device_from_pointer(wlr_dev->pointer); + dev = device_from_pointer(wlr_pointer_from_input_device(wlr_dev)); break; case WLR_INPUT_DEVICE_SWITCH: - dev = device_from_switch(wlr_dev->switch_device); + dev = device_from_switch(wlr_switch_from_input_device(wlr_dev)); break; case WLR_INPUT_DEVICE_TOUCH: - dev = device_from_touch(wlr_dev->touch); + dev = device_from_touch(wlr_touch_from_input_device(wlr_dev)); break; case WLR_INPUT_DEVICE_TABLET_TOOL: - dev = device_from_tablet(wlr_dev->tablet); + dev = device_from_tablet(wlr_tablet_from_input_device(wlr_dev)); break; case WLR_INPUT_DEVICE_TABLET_PAD: - dev = device_from_tablet_pad(wlr_dev->tablet_pad); + dev = device_from_tablet_pad(wlr_tablet_pad_from_input_device(wlr_dev)); break; } return dev->handle; diff --git a/backend/libinput/events.c b/backend/libinput/events.c index e52dbd956..b9f2f43c5 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -41,17 +41,23 @@ void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) { switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - return wlr_dev->keyboard->impl == &libinput_keyboard_impl; + return wlr_keyboard_from_input_device(wlr_dev)->impl == + &libinput_keyboard_impl; case WLR_INPUT_DEVICE_POINTER: - return wlr_dev->pointer->impl == &libinput_pointer_impl; + return wlr_pointer_from_input_device(wlr_dev)->impl == + &libinput_pointer_impl; case WLR_INPUT_DEVICE_TOUCH: - return wlr_dev->touch->impl == &libinput_touch_impl; + return wlr_touch_from_input_device(wlr_dev)->impl == + &libinput_touch_impl; case WLR_INPUT_DEVICE_TABLET_TOOL: - return wlr_dev->tablet->impl == &libinput_tablet_impl; + return wlr_tablet_from_input_device(wlr_dev)-> impl == + &libinput_tablet_impl; case WLR_INPUT_DEVICE_TABLET_PAD: - return wlr_dev->tablet_pad->impl == &libinput_tablet_pad_impl; + return wlr_tablet_pad_from_input_device(wlr_dev)->impl == + &libinput_tablet_pad_impl; case WLR_INPUT_DEVICE_SWITCH: - return wlr_dev->switch_device->impl == &libinput_switch_impl; + return wlr_switch_from_input_device(wlr_dev)->impl == + &libinput_switch_impl; default: return false; } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index c05591aa3..d1c75b397 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -280,15 +280,15 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { bool wlr_input_device_is_wl(struct wlr_input_device *dev) { switch (dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - return dev->keyboard->impl == &keyboard_impl; + return wlr_keyboard_from_input_device(dev)->impl == &keyboard_impl; case WLR_INPUT_DEVICE_POINTER: - return dev->pointer->impl == &wl_pointer_impl; + return wlr_pointer_from_input_device(dev)->impl == &wl_pointer_impl; case WLR_INPUT_DEVICE_TOUCH: - return dev->touch->impl == &touch_impl; + return wlr_touch_from_input_device(dev)->impl == &touch_impl; case WLR_INPUT_DEVICE_TABLET_TOOL: - return dev->tablet->impl == &wl_tablet_impl; + return wlr_tablet_from_input_device(dev)-> impl == &wl_tablet_impl; case WLR_INPUT_DEVICE_TABLET_PAD: - return dev->tablet_pad->impl == &wl_tablet_pad_impl; + return wlr_tablet_pad_from_input_device(dev)->impl == &wl_tablet_pad_impl; default: return false; } diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index d1f5c2c1f..41168222d 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -317,11 +317,11 @@ void update_x11_pointer_position(struct wlr_x11_output *output, bool wlr_input_device_is_x11(struct wlr_input_device *wlr_dev) { switch (wlr_dev->type) { case WLR_INPUT_DEVICE_KEYBOARD: - return wlr_dev->keyboard->impl == &x11_keyboard_impl; + return wlr_keyboard_from_input_device(wlr_dev)->impl == &x11_keyboard_impl; case WLR_INPUT_DEVICE_POINTER: - return wlr_dev->pointer->impl == &x11_pointer_impl; + return wlr_pointer_from_input_device(wlr_dev)->impl == &x11_pointer_impl; case WLR_INPUT_DEVICE_TOUCH: - return wlr_dev->touch->impl == &x11_touch_impl; + return wlr_touch_from_input_device(wlr_dev)->impl == &x11_touch_impl; default: return false; } diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c index d6189f29f..26311319c 100644 --- a/examples/multi-pointer.c +++ b/examples/multi-pointer.c @@ -64,7 +64,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -188,7 +188,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -211,11 +211,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -228,7 +228,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/output-layout.c b/examples/output-layout.c index a057ca78b..97939953f 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -45,7 +45,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -186,7 +186,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -229,11 +229,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -246,7 +246,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/pointer.c b/examples/pointer.c index 1197386e7..6eb328ac2 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -70,7 +70,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *state; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -231,7 +231,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -297,11 +297,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->state = state; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -314,7 +314,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/quads.c b/examples/quads.c index 88c59f7c4..a9c7a14b8 100644 --- a/examples/quads.c +++ b/examples/quads.c @@ -39,7 +39,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -132,7 +132,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -155,11 +155,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -172,7 +172,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/rotation.c b/examples/rotation.c index a2e868af2..087fa8d18 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -44,7 +44,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -137,7 +137,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -176,11 +176,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -193,7 +193,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/simple.c b/examples/simple.c index e46093be5..5a41d19e4 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -35,7 +35,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -112,7 +112,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -137,11 +137,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -154,7 +154,7 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; diff --git a/examples/tablet.c b/examples/tablet.c index 35def7007..1fb0233bb 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -43,7 +43,7 @@ struct sample_state { struct tablet_tool_state { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_tablet *wlr_tablet; struct wl_listener destroy; struct wl_listener axis; struct wl_listener proximity; @@ -55,7 +55,7 @@ struct tablet_tool_state { struct tablet_pad_state { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_tablet_pad *wlr_tablet_pad; struct wl_listener destroy; struct wl_listener button; struct wl_listener ring; @@ -72,7 +72,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -264,7 +264,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -287,11 +287,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -304,40 +304,40 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; case WLR_INPUT_DEVICE_TABLET_PAD:; struct tablet_pad_state *pstate = calloc(sizeof(struct tablet_pad_state), 1); - pstate->device = device; + pstate->wlr_tablet_pad = wlr_tablet_pad_from_input_device(device); pstate->sample = sample; pstate->destroy.notify = tablet_pad_destroy_notify; wl_signal_add(&device->events.destroy, &pstate->destroy); pstate->button.notify = tablet_pad_button_notify; - wl_signal_add(&device->tablet_pad->events.button, &pstate->button); + wl_signal_add(&pstate->wlr_tablet_pad->events.button, &pstate->button); pstate->ring.notify = tablet_pad_ring_notify; - wl_signal_add(&device->tablet_pad->events.ring, &pstate->ring); + wl_signal_add(&pstate->wlr_tablet_pad->events.ring, &pstate->ring); wl_list_insert(&sample->tablet_pads, &pstate->link); break; case WLR_INPUT_DEVICE_TABLET_TOOL:; - struct wlr_tablet *tablet = device->tablet; + struct wlr_tablet *tablet = wlr_tablet_from_input_device(device); sample->width_mm = tablet->width_mm == 0 ? 20 : tablet->width_mm; sample->height_mm = tablet->height_mm == 0 ? 10 : tablet->height_mm; struct tablet_tool_state *tstate = calloc(sizeof(struct tablet_tool_state), 1); - tstate->device = device; + tstate->wlr_tablet = tablet; tstate->sample = sample; tstate->destroy.notify = tablet_tool_destroy_notify; wl_signal_add(&device->events.destroy, &tstate->destroy); tstate->axis.notify = tablet_tool_axis_notify; - wl_signal_add(&device->tablet->events.axis, &tstate->axis); + wl_signal_add(&tablet->events.axis, &tstate->axis); tstate->proximity.notify = tablet_tool_proximity_notify; - wl_signal_add(&device->tablet->events.proximity, &tstate->proximity); + wl_signal_add(&tablet->events.proximity, &tstate->proximity); tstate->button.notify = tablet_tool_button_notify; - wl_signal_add(&device->tablet->events.button, &tstate->button); + wl_signal_add(&tablet->events.button, &tstate->button); wl_list_insert(&sample->tablet_tools, &tstate->link); break; default: diff --git a/examples/touch.c b/examples/touch.c index 765b41aa8..d33e148aa 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -41,7 +41,7 @@ struct touch_point { struct touch_state { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_touch *wlr_touch; struct wl_listener destroy; struct wl_listener down; struct wl_listener up; @@ -59,7 +59,7 @@ struct sample_output { struct sample_keyboard { struct sample_state *sample; - struct wlr_input_device *device; + struct wlr_keyboard *wlr_keyboard; struct wl_listener key; struct wl_listener destroy; }; @@ -175,7 +175,7 @@ static void keyboard_key_notify(struct wl_listener *listener, void *data) { struct wlr_keyboard_key_event *event = data; uint32_t keycode = event->keycode + 8; const xkb_keysym_t *syms; - int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state, + int nsyms = xkb_state_key_get_syms(keyboard->wlr_keyboard->xkb_state, keycode, &syms); for (int i = 0; i < nsyms; i++) { xkb_keysym_t sym = syms[i]; @@ -198,11 +198,11 @@ static void new_input_notify(struct wl_listener *listener, void *data) { switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD:; struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard)); - keyboard->device = device; + keyboard->wlr_keyboard = wlr_keyboard_from_input_device(device); keyboard->sample = sample; wl_signal_add(&device->events.destroy, &keyboard->destroy); keyboard->destroy.notify = keyboard_destroy_notify; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&keyboard->wlr_keyboard->events.key, &keyboard->key); keyboard->key.notify = keyboard_key_notify; struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { @@ -215,22 +215,22 @@ static void new_input_notify(struct wl_listener *listener, void *data) { wlr_log(WLR_ERROR, "Failed to create XKB keymap"); exit(1); } - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(keyboard->wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); break; case WLR_INPUT_DEVICE_TOUCH:; struct touch_state *tstate = calloc(sizeof(struct touch_state), 1); - tstate->device = device; + tstate->wlr_touch = wlr_touch_from_input_device(device); tstate->sample = sample; tstate->destroy.notify = touch_destroy_notify; wl_signal_add(&device->events.destroy, &tstate->destroy); tstate->down.notify = touch_down_notify; - wl_signal_add(&device->touch->events.down, &tstate->down); + wl_signal_add(&tstate->wlr_touch->events.down, &tstate->down); tstate->motion.notify = touch_motion_notify; - wl_signal_add(&device->touch->events.motion, &tstate->motion); + wl_signal_add(&tstate->wlr_touch->events.motion, &tstate->motion); tstate->up.notify = touch_up_notify; - wl_signal_add(&device->touch->events.up, &tstate->up); + wl_signal_add(&tstate->wlr_touch->events.up, &tstate->up); wl_list_insert(&sample->touch, &tstate->link); break; default: diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h index 8c360aab7..0bbf517bc 100644 --- a/include/wlr/types/wlr_input_device.h +++ b/include/wlr/types/wlr_input_device.h @@ -30,17 +30,6 @@ struct wlr_input_device { unsigned int vendor, product; char *name; - /* wlr_input_device.type determines which of these is valid */ - union { - void *_device; - struct wlr_keyboard *keyboard; - struct wlr_pointer *pointer; - struct wlr_switch *switch_device; - struct wlr_touch *touch; - struct wlr_tablet *tablet; - struct wlr_tablet_pad *tablet_pad; - }; - struct { struct wl_signal destroy; } events; diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index 6a7eff810..39449aea4 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -101,6 +101,14 @@ struct wlr_keyboard_key_event { enum wl_keyboard_key_state state; }; +/** + * Get a struct wlr_keyboard from a struct wlr_input_device. + * + * Asserts that the input device is a keyboard. + */ +struct wlr_keyboard *wlr_keyboard_from_input_device( + struct wlr_input_device *input_device); + bool wlr_keyboard_set_keymap(struct wlr_keyboard *kb, struct xkb_keymap *keymap); diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index 17ab258a9..73e641fc4 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -145,4 +145,12 @@ struct wlr_pointer_hold_end_event { bool cancelled; }; +/** + * Get a struct wlr_pointer from a struct wlr_input_device. + * + * Asserts that the input device is a pointer. + */ +struct wlr_pointer *wlr_pointer_from_input_device( + struct wlr_input_device *input_device); + #endif diff --git a/include/wlr/types/wlr_switch.h b/include/wlr/types/wlr_switch.h index e26c9a3f0..b560f0baa 100644 --- a/include/wlr/types/wlr_switch.h +++ b/include/wlr/types/wlr_switch.h @@ -43,4 +43,12 @@ struct wlr_switch_toggle_event { enum wlr_switch_state switch_state; }; +/** + * Get a struct wlr_switch from a struct wlr_input_device. + * + * Asserts that the input device is a switch. + */ +struct wlr_switch *wlr_switch_from_input_device( + struct wlr_input_device *input_device); + #endif diff --git a/include/wlr/types/wlr_tablet_pad.h b/include/wlr/types/wlr_tablet_pad.h index 32a3231db..f19505a97 100644 --- a/include/wlr/types/wlr_tablet_pad.h +++ b/include/wlr/types/wlr_tablet_pad.h @@ -92,4 +92,12 @@ struct wlr_tablet_pad_strip_event { unsigned int mode; }; +/** + * Get a struct wlr_tablet_pad from a struct wlr_input_device. + * + * Asserts that the input device is a tablet pad. + */ +struct wlr_tablet_pad *wlr_tablet_pad_from_input_device( + struct wlr_input_device *); + #endif diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h index ec0fc42a8..495c7094a 100644 --- a/include/wlr/types/wlr_tablet_tool.h +++ b/include/wlr/types/wlr_tablet_tool.h @@ -144,4 +144,12 @@ struct wlr_tablet_tool_button_event { enum wlr_button_state state; }; +/** + * Get a struct wlr_tablet from a struct wlr_input_device. + * + * Asserts that the input device is a tablet tool. + */ +struct wlr_tablet *wlr_tablet_from_input_device( + struct wlr_input_device *input_device); + #endif diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index 0d2a27b6b..da294f765 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -62,4 +62,12 @@ struct wlr_touch_cancel_event { int32_t touch_id; }; +/** + * Get a struct wlr_touch from a struct wlr_input_device. + * + * Asserts that the input device is a touch device. + */ +struct wlr_touch *wlr_touch_from_input_device( + struct wlr_input_device *input_device); + #endif diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index f96fe7919..2b58a4b5c 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -238,10 +238,12 @@ static void keyboard_handle_destroy(struct wl_listener *listener, void *data) { static void server_new_keyboard(struct tinywl_server *server, struct wlr_input_device *device) { + struct wlr_keyboard *wlr_keyboard = wlr_keyboard_from_input_device(device); + struct tinywl_keyboard *keyboard = calloc(1, sizeof(struct tinywl_keyboard)); keyboard->server = server; - keyboard->wlr_keyboard = device->keyboard; + keyboard->wlr_keyboard = wlr_keyboard; /* We need to prepare an XKB keymap and assign it to the keyboard. This * assumes the defaults (e.g. layout = "us"). */ @@ -249,16 +251,16 @@ static void server_new_keyboard(struct tinywl_server *server, struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); - wlr_keyboard_set_keymap(device->keyboard, keymap); + wlr_keyboard_set_keymap(wlr_keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); - wlr_keyboard_set_repeat_info(device->keyboard, 25, 600); + wlr_keyboard_set_repeat_info(wlr_keyboard, 25, 600); /* Here we set up listeners for keyboard events. */ keyboard->modifiers.notify = keyboard_handle_modifiers; - wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifiers); + wl_signal_add(&wlr_keyboard->events.modifiers, &keyboard->modifiers); keyboard->key.notify = keyboard_handle_key; - wl_signal_add(&device->keyboard->events.key, &keyboard->key); + wl_signal_add(&wlr_keyboard->events.key, &keyboard->key); keyboard->destroy.notify = keyboard_handle_destroy; wl_signal_add(&device->events.destroy, &keyboard->destroy); diff --git a/types/tablet_v2/wlr_tablet_v2_pad.c b/types/tablet_v2/wlr_tablet_v2_pad.c index a468a1248..a7ac9ef8f 100644 --- a/types/tablet_v2/wlr_tablet_v2_pad.c +++ b/types/tablet_v2/wlr_tablet_v2_pad.c @@ -376,7 +376,7 @@ struct wlr_tablet_v2_tablet_pad *wlr_tablet_pad_create( if (!seat) { return NULL; } - struct wlr_tablet_pad *wlr_pad = wlr_device->tablet_pad; + struct wlr_tablet_pad *wlr_pad = wlr_tablet_pad_from_input_device(wlr_device); struct wlr_tablet_v2_tablet_pad *pad = calloc(1, sizeof(struct wlr_tablet_v2_tablet_pad)); if (!pad) { return NULL; diff --git a/types/tablet_v2/wlr_tablet_v2_tablet.c b/types/tablet_v2/wlr_tablet_v2_tablet.c index b9189a26a..38668fda1 100644 --- a/types/tablet_v2/wlr_tablet_v2_tablet.c +++ b/types/tablet_v2/wlr_tablet_v2_tablet.c @@ -60,7 +60,7 @@ struct wlr_tablet_v2_tablet *wlr_tablet_create( if (!seat) { return NULL; } - struct wlr_tablet *wlr_tablet = wlr_device->tablet; + struct wlr_tablet *wlr_tablet = wlr_tablet_from_input_device(wlr_device); struct wlr_tablet_v2_tablet *tablet = calloc(1, sizeof(struct wlr_tablet_v2_tablet)); if (!tablet) { return NULL; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index cd50e61e7..fd3ae5f5e 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -648,75 +648,78 @@ static struct wlr_cursor_device *cursor_device_create( c_device->destroy.notify = handle_device_destroy; if (device->type == WLR_INPUT_DEVICE_POINTER) { - wl_signal_add(&device->pointer->events.motion, &c_device->motion); + struct wlr_pointer *pointer = wlr_pointer_from_input_device(device); + + wl_signal_add(&pointer->events.motion, &c_device->motion); c_device->motion.notify = handle_pointer_motion; - wl_signal_add(&device->pointer->events.motion_absolute, + wl_signal_add(&pointer->events.motion_absolute, &c_device->motion_absolute); c_device->motion_absolute.notify = handle_pointer_motion_absolute; - wl_signal_add(&device->pointer->events.button, &c_device->button); + wl_signal_add(&pointer->events.button, &c_device->button); c_device->button.notify = handle_pointer_button; - wl_signal_add(&device->pointer->events.axis, &c_device->axis); + wl_signal_add(&pointer->events.axis, &c_device->axis); c_device->axis.notify = handle_pointer_axis; - wl_signal_add(&device->pointer->events.frame, &c_device->frame); + wl_signal_add(&pointer->events.frame, &c_device->frame); c_device->frame.notify = handle_pointer_frame; - wl_signal_add(&device->pointer->events.swipe_begin, &c_device->swipe_begin); + wl_signal_add(&pointer->events.swipe_begin, &c_device->swipe_begin); c_device->swipe_begin.notify = handle_pointer_swipe_begin; - wl_signal_add(&device->pointer->events.swipe_update, &c_device->swipe_update); + wl_signal_add(&pointer->events.swipe_update, &c_device->swipe_update); c_device->swipe_update.notify = handle_pointer_swipe_update; - wl_signal_add(&device->pointer->events.swipe_end, &c_device->swipe_end); + wl_signal_add(&pointer->events.swipe_end, &c_device->swipe_end); c_device->swipe_end.notify = handle_pointer_swipe_end; - wl_signal_add(&device->pointer->events.pinch_begin, &c_device->pinch_begin); + wl_signal_add(&pointer->events.pinch_begin, &c_device->pinch_begin); c_device->pinch_begin.notify = handle_pointer_pinch_begin; - wl_signal_add(&device->pointer->events.pinch_update, &c_device->pinch_update); + wl_signal_add(&pointer->events.pinch_update, &c_device->pinch_update); c_device->pinch_update.notify = handle_pointer_pinch_update; - wl_signal_add(&device->pointer->events.pinch_end, &c_device->pinch_end); + wl_signal_add(&pointer->events.pinch_end, &c_device->pinch_end); c_device->pinch_end.notify = handle_pointer_pinch_end; - wl_signal_add(&device->pointer->events.hold_begin, &c_device->hold_begin); + wl_signal_add(&pointer->events.hold_begin, &c_device->hold_begin); c_device->hold_begin.notify = handle_pointer_hold_begin; - wl_signal_add(&device->pointer->events.hold_end, &c_device->hold_end); + wl_signal_add(&pointer->events.hold_end, &c_device->hold_end); c_device->hold_end.notify = handle_pointer_hold_end; } else if (device->type == WLR_INPUT_DEVICE_TOUCH) { - wl_signal_add(&device->touch->events.motion, &c_device->touch_motion); + struct wlr_touch *touch = wlr_touch_from_input_device(device); + + wl_signal_add(&touch->events.motion, &c_device->touch_motion); c_device->touch_motion.notify = handle_touch_motion; - wl_signal_add(&device->touch->events.down, &c_device->touch_down); + wl_signal_add(&touch->events.down, &c_device->touch_down); c_device->touch_down.notify = handle_touch_down; - wl_signal_add(&device->touch->events.up, &c_device->touch_up); + wl_signal_add(&touch->events.up, &c_device->touch_up); c_device->touch_up.notify = handle_touch_up; - wl_signal_add(&device->touch->events.cancel, &c_device->touch_cancel); + wl_signal_add(&touch->events.cancel, &c_device->touch_cancel); c_device->touch_cancel.notify = handle_touch_cancel; - wl_signal_add(&device->touch->events.frame, &c_device->touch_frame); + wl_signal_add(&touch->events.frame, &c_device->touch_frame); c_device->touch_frame.notify = handle_touch_frame; } else if (device->type == WLR_INPUT_DEVICE_TABLET_TOOL) { - wl_signal_add(&device->tablet->events.tip, - &c_device->tablet_tool_tip); + struct wlr_tablet *tablet = wlr_tablet_from_input_device(device); + + wl_signal_add(&tablet->events.tip, &c_device->tablet_tool_tip); c_device->tablet_tool_tip.notify = handle_tablet_tool_tip; - wl_signal_add(&device->tablet->events.proximity, + wl_signal_add(&tablet->events.proximity, &c_device->tablet_tool_proximity); c_device->tablet_tool_proximity.notify = handle_tablet_tool_proximity; - wl_signal_add(&device->tablet->events.axis, - &c_device->tablet_tool_axis); + wl_signal_add(&tablet->events.axis, &c_device->tablet_tool_axis); c_device->tablet_tool_axis.notify = handle_tablet_tool_axis; - wl_signal_add(&device->tablet->events.button, - &c_device->tablet_tool_button); + wl_signal_add(&tablet->events.button, &c_device->tablet_tool_button); c_device->tablet_tool_button.notify = handle_tablet_tool_button; } diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 2a82cfa8e..4d866d007 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -13,6 +13,12 @@ #include "util/signal.h" #include "util/time.h" +struct wlr_keyboard *wlr_keyboard_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_KEYBOARD); + return wl_container_of(input_device, (struct wlr_keyboard *)NULL, base); +} + void keyboard_led_update(struct wlr_keyboard *keyboard) { if (keyboard->xkb_state == NULL) { return; @@ -118,7 +124,6 @@ void wlr_keyboard_init(struct wlr_keyboard *kb, const struct wlr_keyboard_impl *impl, const char *name) { memset(kb, 0, sizeof(*kb)); wlr_input_device_init(&kb->base, WLR_INPUT_DEVICE_KEYBOARD, name); - kb->base.keyboard = kb; kb->impl = impl; wl_signal_init(&kb->events.key); diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index e4d39f6af..be505b6c4 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,11 +7,16 @@ #include "interfaces/wlr_input_device.h" +struct wlr_pointer *wlr_pointer_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_POINTER); + return wl_container_of(input_device, (struct wlr_pointer *)NULL, base); +} + void wlr_pointer_init(struct wlr_pointer *pointer, const struct wlr_pointer_impl *impl, const char *name) { memset(pointer, 0, sizeof(*pointer)); wlr_input_device_init(&pointer->base, WLR_INPUT_DEVICE_POINTER, name); - pointer->base.pointer = pointer; pointer->impl = impl; wl_signal_init(&pointer->events.motion); diff --git a/types/wlr_switch.c b/types/wlr_switch.c index 3b05ec6c0..5a2083ff2 100644 --- a/types/wlr_switch.c +++ b/types/wlr_switch.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,11 +7,16 @@ #include "interfaces/wlr_input_device.h" +struct wlr_switch *wlr_switch_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_SWITCH); + return wl_container_of(input_device, (struct wlr_switch *)NULL, base); +} + void wlr_switch_init(struct wlr_switch *switch_device, const struct wlr_switch_impl *impl, const char *name) { memset(switch_device, 0, sizeof(*switch_device)); wlr_input_device_init(&switch_device->base, WLR_INPUT_DEVICE_SWITCH, name); - switch_device->base.switch_device = switch_device; switch_device->impl = impl; wl_signal_init(&switch_device->events.toggle); diff --git a/types/wlr_tablet_pad.c b/types/wlr_tablet_pad.c index 353b4d431..34c81301c 100644 --- a/types/wlr_tablet_pad.c +++ b/types/wlr_tablet_pad.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -7,11 +8,16 @@ #include "interfaces/wlr_input_device.h" +struct wlr_tablet_pad *wlr_tablet_pad_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_TABLET_PAD); + return wl_container_of(input_device, (struct wlr_tablet_pad *)NULL, base); +} + void wlr_tablet_pad_init(struct wlr_tablet_pad *pad, const struct wlr_tablet_pad_impl *impl, const char *name) { memset(pad, 0, sizeof(*pad)); wlr_input_device_init(&pad->base, WLR_INPUT_DEVICE_TABLET_PAD, name); - pad->base.tablet_pad = pad; pad->impl = impl; wl_signal_init(&pad->events.button); diff --git a/types/wlr_tablet_tool.c b/types/wlr_tablet_tool.c index 7d8eb4187..a25b71a6e 100644 --- a/types/wlr_tablet_tool.c +++ b/types/wlr_tablet_tool.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,11 +7,16 @@ #include "interfaces/wlr_input_device.h" +struct wlr_tablet *wlr_tablet_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_TABLET_TOOL); + return wl_container_of(input_device, (struct wlr_tablet *)NULL, base); +} + void wlr_tablet_init(struct wlr_tablet *tablet, const struct wlr_tablet_impl *impl, const char *name) { memset(tablet, 0, sizeof(*tablet)); wlr_input_device_init(&tablet->base, WLR_INPUT_DEVICE_TABLET_TOOL, name); - tablet->base.tablet = tablet; tablet->impl = impl; wl_signal_init(&tablet->events.axis); diff --git a/types/wlr_touch.c b/types/wlr_touch.c index 28fec1982..d6285180e 100644 --- a/types/wlr_touch.c +++ b/types/wlr_touch.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,11 +7,16 @@ #include "interfaces/wlr_input_device.h" +struct wlr_touch *wlr_touch_from_input_device( + struct wlr_input_device *input_device) { + assert(input_device->type == WLR_INPUT_DEVICE_TOUCH); + return wl_container_of(input_device, (struct wlr_touch *)NULL, base); +} + void wlr_touch_init(struct wlr_touch *touch, const struct wlr_touch_impl *impl, const char *name) { memset(touch, 0, sizeof(*touch)); wlr_input_device_init(&touch->base, WLR_INPUT_DEVICE_TOUCH, name); - touch->base.touch = touch; touch->impl = impl; wl_signal_init(&touch->events.down); diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 791557dbc..2d313575f 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -26,11 +26,15 @@ static struct wlr_virtual_keyboard_v1 *virtual_keyboard_from_resource( struct wlr_virtual_keyboard_v1 *wlr_input_device_get_virtual_keyboard( struct wlr_input_device *wlr_dev) { - if (wlr_dev->type != WLR_INPUT_DEVICE_KEYBOARD - || wlr_dev->keyboard->impl != &keyboard_impl) { + if (wlr_dev->type != WLR_INPUT_DEVICE_KEYBOARD) { return NULL; } - return (struct wlr_virtual_keyboard_v1 *)wlr_dev->keyboard; + struct wlr_keyboard *wlr_keyboard = wlr_keyboard_from_input_device(wlr_dev); + if (wlr_keyboard->impl != &keyboard_impl) { + return NULL; + } + return wl_container_of(wlr_keyboard, + (struct wlr_virtual_keyboard_v1 *)NULL, keyboard); } static void virtual_keyboard_keymap(struct wl_client *client, diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index 931545afe..f1fea0f02 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -106,21 +106,20 @@ static void virtual_pointer_frame(struct wl_client *client, if (pointer == NULL) { return; } - struct wlr_input_device *wlr_dev = &pointer->pointer.base; for (size_t i = 0; i < sizeof(pointer->axis_valid) / sizeof(pointer->axis_valid[0]); ++i) { if (pointer->axis_valid[i]) { /* Deliver pending axis event */ - wlr_signal_emit_safe(&wlr_dev->pointer->events.axis, + wlr_signal_emit_safe(&pointer->pointer.events.axis, &pointer->axis_event[i]); memset(&pointer->axis_event[i], 0, sizeof(pointer->axis_event[i])); pointer->axis_valid[i] = false; } } - wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); + wlr_signal_emit_safe(&pointer->pointer.events.frame, &pointer->pointer); } static void virtual_pointer_axis_source(struct wl_client *client, From b9d55b8769617dc33660dc8e8c27de7bd4f62e4d Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 24 Jun 2022 07:16:41 +0200 Subject: [PATCH 211/298] render/gles2: check GBM is found The GLES2 renderer depends on EGL, which depends on GBM for device selection. --- render/gles2/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/gles2/meson.build b/render/gles2/meson.build index f2cd5fbaf..8656714b6 100644 --- a/render/gles2/meson.build +++ b/render/gles2/meson.build @@ -1,6 +1,6 @@ glesv2 = dependency('glesv2', required: 'gles2' in renderers) -if not (glesv2.found() and egl.found()) +if not (glesv2.found() and egl.found() and gbm.found()) subdir_done() endif From c20468cfa292e99357fd504fc5b5884f6078ca96 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 24 Jun 2022 07:20:42 +0200 Subject: [PATCH 212/298] render: use internal_features to indicate EGL support Instead of checking whether the wlr_egl dependencies are available in the GLES2 code, introduce internal_features['egl'] and check that field. When updating the EGL dependency list, we no longer need to update the GLES2 logic. --- meson.build | 1 + render/gles2/meson.build | 2 +- render/meson.build | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 971be7e63..992b09b64 100644 --- a/meson.build +++ b/meson.build @@ -96,6 +96,7 @@ features = { } internal_features = { 'xcb-errors': false, + 'egl': false, } wayland_project_options = ['tests=false', 'documentation=false'] diff --git a/render/gles2/meson.build b/render/gles2/meson.build index 8656714b6..504f0c11e 100644 --- a/render/gles2/meson.build +++ b/render/gles2/meson.build @@ -1,6 +1,6 @@ glesv2 = dependency('glesv2', required: 'gles2' in renderers) -if not (glesv2.found() and egl.found() and gbm.found()) +if not (glesv2.found() and internal_features['egl']) subdir_done() endif diff --git a/render/meson.build b/render/meson.build index 2bdcced8f..c8c6032fa 100644 --- a/render/meson.build +++ b/render/meson.build @@ -20,6 +20,7 @@ if 'gles2' in renderers or 'auto' in renderers if egl.found() and gbm.found() wlr_deps += [egl, gbm] wlr_files += files('egl.c') + internal_features += { 'egl': true } endif subdir('gles2') endif From 03dc7e2df5d02d7d827ea8ff2153dc941622e5f1 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Mon, 27 Jun 2022 22:56:02 +0200 Subject: [PATCH 213/298] wlr_{keyboard,pointer,touch}: Update event docs Events used by our input devices were recently renamed from wlr_event_* to wlr_*_event, but the documentation and a single point of use was not updated accordingly. Regressed by: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3484 --- include/wlr/types/wlr_keyboard.h | 4 ++-- include/wlr/types/wlr_pointer.h | 24 ++++++++++++------------ include/wlr/types/wlr_touch.h | 8 ++++---- types/wlr_cursor.c | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h index 39449aea4..d53d3c304 100644 --- a/include/wlr/types/wlr_keyboard.h +++ b/include/wlr/types/wlr_keyboard.h @@ -73,8 +73,8 @@ struct wlr_keyboard { struct { /** - * The `key` event signals with a struct wlr_event_keyboard_key_event - * that a key has been pressed or released on the keyboard. This event is + * The `key` event signals with a struct wlr_keyboard_key_event that a + * key has been pressed or released on the keyboard. This event is * emitted before the xkb state of the keyboard has been updated * (including modifiers). */ diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index 73e641fc4..cce2a5a87 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -24,22 +24,22 @@ struct wlr_pointer { char *output_name; struct { - struct wl_signal motion; // struct wlr_event_pointer_motion - struct wl_signal motion_absolute; // struct wlr_event_pointer_motion_absolute - struct wl_signal button; // struct wlr_event_pointer_button - struct wl_signal axis; // struct wlr_event_pointer_axis + struct wl_signal motion; // struct wlr_pointer_motion_event + struct wl_signal motion_absolute; // struct wlr_pointer_motion_absolute_event + struct wl_signal button; // struct wlr_pointer_button_event + struct wl_signal axis; // struct wlr_pointer_axis_event struct wl_signal frame; - struct wl_signal swipe_begin; // struct wlr_event_pointer_swipe_begin - struct wl_signal swipe_update; // struct wlr_event_pointer_swipe_update - struct wl_signal swipe_end; // struct wlr_event_pointer_swipe_end + struct wl_signal swipe_begin; // struct wlr_pointer_swipe_begin_event + struct wl_signal swipe_update; // struct wlr_pointer_swipe_update_event + struct wl_signal swipe_end; // struct wlr_pointer_swipe_end_event - struct wl_signal pinch_begin; // struct wlr_event_pointer_pinch_begin - struct wl_signal pinch_update; // struct wlr_event_pointer_pinch_update - struct wl_signal pinch_end; // struct wlr_event_pointer_pinch_end + struct wl_signal pinch_begin; // struct wlr_pointer_pinch_begin_event + struct wl_signal pinch_update; // struct wlr_pointer_pinch_update_event + struct wl_signal pinch_end; // struct wlr_pointer_pinch_end_event - struct wl_signal hold_begin; // struct wlr_event_pointer_hold_begin - struct wl_signal hold_end; // struct wlr_event_pointer_hold_end + struct wl_signal hold_begin; // struct wlr_pointer_hold_begin_event + struct wl_signal hold_end; // struct wlr_pointer_hold_end_event } events; void *data; diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h index da294f765..82c4b8618 100644 --- a/include/wlr/types/wlr_touch.h +++ b/include/wlr/types/wlr_touch.h @@ -24,10 +24,10 @@ struct wlr_touch { double width_mm, height_mm; struct { - struct wl_signal down; // struct wlr_event_touch_down - struct wl_signal up; // struct wlr_event_touch_up - struct wl_signal motion; // struct wlr_event_touch_motion - struct wl_signal cancel; // struct wlr_event_touch_cancel + struct wl_signal down; // struct wlr_touch_down_event + struct wl_signal up; // struct wlr_touch_up_event + struct wl_signal motion; // struct wlr_touch_motion_event + struct wl_signal cancel; // struct wlr_touch_cancel_event struct wl_signal frame; } events; diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index fd3ae5f5e..d38d279ef 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -365,7 +365,7 @@ void wlr_cursor_set_surface(struct wlr_cursor *cur, struct wlr_surface *surface, } static void handle_pointer_motion(struct wl_listener *listener, void *data) { - struct wlr_event_pointer_motion *event = data; + struct wlr_pointer_motion_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, motion); wlr_signal_emit_safe(&device->cursor->events.motion, event); From 517ea218c6318e1b268ba88b46c4a0fe7713eb82 Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 23 Jun 2022 12:23:37 -0400 Subject: [PATCH 214/298] tinywl: exit on backend, renderer or allocator creation failure --- tinywl/tinywl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 2b58a4b5c..4fc8477c7 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -818,12 +818,21 @@ int main(int argc, char *argv[]) { * backend based on the current environment, such as opening an X11 window * if an X11 server is running. */ server.backend = wlr_backend_autocreate(server.wl_display); + if (server.backend == NULL) { + wlr_log(WLR_ERROR, "failed to create wlr_backend"); + return 1; + } /* Autocreates a renderer, either Pixman, GLES2 or Vulkan for us. The user * can also specify a renderer using the WLR_RENDERER env var. * The renderer is responsible for defining the various pixel formats it * supports for shared memory, this configures that for clients. */ server.renderer = wlr_renderer_autocreate(server.backend); + if (server.renderer == NULL) { + wlr_log(WLR_ERROR, "failed to create wlr_renderer"); + return 1; + } + wlr_renderer_init_wl_display(server.renderer, server.wl_display); /* Autocreates an allocator for us. @@ -832,6 +841,10 @@ int main(int argc, char *argv[]) { * screen */ server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); + if (server.allocator == NULL) { + wlr_log(WLR_ERROR, "failed to create wlr_allocator"); + return 1; + } /* This creates some hands-off wlroots interfaces. The compositor is * necessary for clients to allocate surfaces, the subcompositor allows to From e26c3a02dfa2e071f8a70ee192cd11f2434c6b64 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 29 Jun 2022 11:32:06 +0200 Subject: [PATCH 215/298] build: fix enabled GBM when allocators=auto and auto_features=disabled --- render/allocator/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/allocator/meson.build b/render/allocator/meson.build index f8e452df9..97c5a1c36 100644 --- a/render/allocator/meson.build +++ b/render/allocator/meson.build @@ -1,7 +1,7 @@ allocators = get_option('allocators') if 'auto' in allocators and get_option('auto_features').enabled() allocators = ['gbm'] -elif 'auto' in renderers and get_option('auto_features').disabled() +elif 'auto' in allocators and get_option('auto_features').disabled() allocators = [] endif From 10a821a87ddabfdef50f8c5a562c3aea44215019 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 29 Jun 2022 17:42:57 +0200 Subject: [PATCH 216/298] output: fix missing buffer when using direct scanout When using direct scanout back_buffer is NULL. We'd emit a commit event with WLR_OUTPUT_STATE_BUFFER set but with a NULL buffer field, which is non-sensical. --- types/output/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/output/output.c b/types/output/output.c index ae18ea8de..b45576faa 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -835,7 +835,7 @@ bool wlr_output_commit_state(struct wlr_output *output, .output = output, .committed = pending.committed, .when = &now, - .buffer = back_buffer, + .buffer = (pending.committed & WLR_OUTPUT_STATE_BUFFER) ? pending.buffer : NULL, }; wlr_signal_emit_safe(&output->events.commit, &event); From e0accb2d50f8a3ba74802e6a8673af2eb1aa1e68 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sat, 30 Apr 2022 08:55:16 +0300 Subject: [PATCH 217/298] types: add wlr_damage_ring wlr_damage_ring is effectively wlr_output_damage untied from wlr_output. --- include/wlr/types/wlr_damage_ring.h | 81 ++++++++++++++++++++ types/meson.build | 1 + types/wlr_damage_ring.c | 113 ++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 include/wlr/types/wlr_damage_ring.h create mode 100644 types/wlr_damage_ring.c diff --git a/include/wlr/types/wlr_damage_ring.h b/include/wlr/types/wlr_damage_ring.h new file mode 100644 index 000000000..9415a5563 --- /dev/null +++ b/include/wlr/types/wlr_damage_ring.h @@ -0,0 +1,81 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_TYPES_WLR_DAMAGE_RING_H +#define WLR_TYPES_WLR_DAMAGE_RING_H + +#include + +/* For triple buffering, a history of two frames is required. */ +#define WLR_DAMAGE_RING_PREVIOUS_LEN 2 + +struct wlr_box; + +struct wlr_damage_ring { + int32_t width, height; + + // Difference between the current buffer and the previous one + pixman_region32_t current; + + // private state + + pixman_region32_t previous[WLR_DAMAGE_RING_PREVIOUS_LEN]; + size_t previous_idx; +}; + +void wlr_damage_ring_init(struct wlr_damage_ring *ring); + +void wlr_damage_ring_finish(struct wlr_damage_ring *ring); + +/** + * Set ring bounds and damage the ring fully. + * + * Next time damage will be added, it will be cropped to the ring bounds. + * If at least one of the dimensions is 0, bounds are removed. + * + * By default, a damage ring doesn't have bounds. + */ +void wlr_damage_ring_set_bounds(struct wlr_damage_ring *ring, + int32_t width, int32_t height); + +/** + * Add a region to the current damage. + * + * Returns true if the region intersects the ring bounds, false otherwise. + */ +bool wlr_damage_ring_add(struct wlr_damage_ring *ring, + pixman_region32_t *damage); + +/** + * Add a box to the current damage. + * + * Returns true if the box intersects the ring bounds, false otherwise. + */ +bool wlr_damage_ring_add_box(struct wlr_damage_ring *ring, + const struct wlr_box *box); + +/** + * Damage the ring fully. + */ +void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring); + +/** + * Rotate the damage ring. This needs to be called after using the accumulated + * damage, e.g. after rendering to an output's back buffer. + */ +void wlr_damage_ring_rotate(struct wlr_damage_ring *ring); + +/** + * Get accumulated damage, which is the difference between the current buffer + * and the buffer with age of buffer_age; in context of rendering, this is + * the region that needs to be redrawn. + */ +void wlr_damage_ring_get_buffer_damage(struct wlr_damage_ring *ring, + int buffer_age, pixman_region32_t *damage); + +#endif diff --git a/types/meson.build b/types/meson.build index 16870b836..53bf852b8 100644 --- a/types/meson.build +++ b/types/meson.build @@ -30,6 +30,7 @@ wlr_files += files( 'wlr_buffer.c', 'wlr_compositor.c', 'wlr_cursor.c', + 'wlr_damage_ring.c', 'wlr_data_control_v1.c', 'wlr_drm.c', 'wlr_export_dmabuf_v1.c', diff --git a/types/wlr_damage_ring.c b/types/wlr_damage_ring.c new file mode 100644 index 000000000..378051c7a --- /dev/null +++ b/types/wlr_damage_ring.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include "util/signal.h" + +#define WLR_DAMAGE_RING_MAX_RECTS 20 + +void wlr_damage_ring_init(struct wlr_damage_ring *ring) { + memset(ring, 0, sizeof(*ring)); + + ring->width = INT_MAX; + ring->height = INT_MAX; + + pixman_region32_init(&ring->current); + for (size_t i = 0; i < WLR_DAMAGE_RING_PREVIOUS_LEN; ++i) { + pixman_region32_init(&ring->previous[i]); + } +} + +void wlr_damage_ring_finish(struct wlr_damage_ring *ring) { + pixman_region32_fini(&ring->current); + for (size_t i = 0; i < WLR_DAMAGE_RING_PREVIOUS_LEN; ++i) { + pixman_region32_fini(&ring->previous[i]); + } +} + +void wlr_damage_ring_set_bounds(struct wlr_damage_ring *ring, + int32_t width, int32_t height) { + if (width == 0 || height == 0) { + ring->width = INT_MAX; + ring->height = INT_MAX; + } else { + ring->width = width; + ring->height = height; + } + wlr_damage_ring_add_whole(ring); +} + +bool wlr_damage_ring_add(struct wlr_damage_ring *ring, + pixman_region32_t *damage) { + pixman_region32_t clipped; + pixman_region32_init(&clipped); + pixman_region32_intersect_rect(&clipped, damage, + 0, 0, ring->width, ring->height); + bool intersects = pixman_region32_not_empty(&clipped); + if (intersects) { + pixman_region32_union(&ring->current, &ring->current, &clipped); + } + pixman_region32_fini(&clipped); + return intersects; +} + +bool wlr_damage_ring_add_box(struct wlr_damage_ring *ring, + const struct wlr_box *box) { + struct wlr_box clipped = { + .x = 0, + .y = 0, + .width = ring->width, + .height = ring->height, + }; + if (wlr_box_intersection(&clipped, &clipped, box)) { + pixman_region32_union_rect(&ring->current, + &ring->current, clipped.x, clipped.y, + clipped.width, clipped.height); + return true; + } + return false; +} + +void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring) { + pixman_region32_union_rect(&ring->current, + &ring->current, 0, 0, ring->width, ring->height); +} + +void wlr_damage_ring_rotate(struct wlr_damage_ring *ring) { + // modular decrement + ring->previous_idx = ring->previous_idx + + WLR_DAMAGE_RING_PREVIOUS_LEN - 1; + ring->previous_idx %= WLR_DAMAGE_RING_PREVIOUS_LEN; + + pixman_region32_copy(&ring->previous[ring->previous_idx], &ring->current); + pixman_region32_clear(&ring->current); +} + +void wlr_damage_ring_get_buffer_damage(struct wlr_damage_ring *ring, + int buffer_age, pixman_region32_t *damage) { + if (buffer_age <= 0 || buffer_age - 1 > WLR_DAMAGE_RING_PREVIOUS_LEN) { + pixman_region32_clear(damage); + pixman_region32_union_rect(damage, damage, + 0, 0, ring->width, ring->height); + } else { + pixman_region32_copy(damage, &ring->current); + + // Accumulate damage from old buffers + for (int i = 0; i < buffer_age - 1; ++i) { + int j = (ring->previous_idx + i) % WLR_DAMAGE_RING_PREVIOUS_LEN; + pixman_region32_union(damage, damage, &ring->previous[j]); + } + + // Check the number of rectangles + int n_rects = pixman_region32_n_rects(damage); + if (n_rects > WLR_DAMAGE_RING_MAX_RECTS) { + pixman_box32_t *extents = pixman_region32_extents(damage); + pixman_region32_union_rect(damage, damage, + extents->x1, extents->y1, + extents->x2 - extents->x1, + extents->y2 - extents->y1); + } + } +} From 97f0347780358eb1e052af5bc40f2c0c9b7e170b Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Sun, 22 May 2022 10:18:43 +0300 Subject: [PATCH 218/298] scene: switch to wlr_damage_ring --- include/wlr/types/wlr_scene.h | 4 +- types/scene/wlr_scene.c | 83 +++++++++++++++++++++++------------ 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 49804d83a..74f552887 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -22,6 +22,7 @@ #include #include #include +#include struct wlr_output; struct wlr_output_layout; @@ -160,7 +161,7 @@ struct wlr_scene_output { struct wlr_scene *scene; struct wlr_addon addon; - struct wlr_output_damage *damage; + struct wlr_damage_ring damage_ring; int x, y; @@ -175,6 +176,7 @@ struct wlr_scene_output { struct wl_listener output_commit; struct wl_listener output_mode; + struct wl_listener output_needs_frame; }; /** A layer shell scene helper */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 4cdf4be84..0b127e601 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -5,8 +5,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -422,8 +422,11 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff wlr_region_scale_xy(&output_damage, &trans_damage, output_scale * scale_x, output_scale * scale_y); pixman_region32_translate(&output_damage, - (lx - scene_output->x) * output_scale, (ly - scene_output->y) * output_scale); - wlr_output_damage_add(scene_output->damage, &output_damage); + (lx - scene_output->x) * output_scale, + (ly - scene_output->y) * output_scale); + if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { + wlr_output_schedule_frame(scene_output->output); + } pixman_region32_fini(&output_damage); } @@ -572,7 +575,9 @@ static void _scene_node_damage_whole(struct wlr_scene_node *node, scale_box(&box, scene_output->output->scale); - wlr_output_damage_add_box(scene_output->damage, &box); + if (wlr_damage_ring_add_box(&scene_output->damage_ring, &box)) { + wlr_output_schedule_frame(scene_output->output); + } } } @@ -969,6 +974,15 @@ static const struct wlr_addon_interface output_addon_impl = { .destroy = scene_output_handle_destroy, }; +static void scene_output_update_geometry(struct wlr_scene_output *scene_output) { + int width, height; + wlr_output_transformed_resolution(scene_output->output, &width, &height); + wlr_damage_ring_set_bounds(&scene_output->damage_ring, width, height); + wlr_output_schedule_frame(scene_output->output); + + scene_node_update_outputs(&scene_output->scene->tree.node, NULL); +} + static void scene_output_handle_commit(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wl_container_of(listener, scene_output, output_commit); @@ -977,14 +991,20 @@ static void scene_output_handle_commit(struct wl_listener *listener, void *data) if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { - scene_node_update_outputs(&scene_output->scene->tree.node, NULL); + scene_output_update_geometry(scene_output); } } static void scene_output_handle_mode(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wl_container_of(listener, scene_output, output_mode); - scene_node_update_outputs(&scene_output->scene->tree.node, NULL); + scene_output_update_geometry(scene_output); +} + +static void scene_output_handle_needs_frame(struct wl_listener *listener, void *data) { + struct wlr_scene_output *scene_output = wl_container_of(listener, + scene_output, output_needs_frame); + wlr_output_schedule_frame(scene_output->output); } struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, @@ -994,16 +1014,12 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, return NULL; } - scene_output->damage = wlr_output_damage_create(output); - if (scene_output->damage == NULL) { - free(scene_output); - return NULL; - } - scene_output->output = output; scene_output->scene = scene; wlr_addon_init(&scene_output->addon, &output->addons, scene, &output_addon_impl); + wlr_damage_ring_init(&scene_output->damage_ring); + int prev_output_index = -1; struct wl_list *prev_output_link = &scene->outputs; @@ -1029,8 +1045,10 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, scene_output->output_mode.notify = scene_output_handle_mode; wl_signal_add(&output->events.mode, &scene_output->output_mode); - wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene->tree.node, NULL); + scene_output->output_needs_frame.notify = scene_output_handle_needs_frame; + wl_signal_add(&output->events.needs_frame, &scene_output->output_needs_frame); + + scene_output_update_geometry(scene_output); return scene_output; } @@ -1045,9 +1063,11 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { scene_node_update_outputs(&scene_output->scene->tree.node, scene_output); wlr_addon_finish(&scene_output->addon); + wlr_damage_ring_finish(&scene_output->damage_ring); wl_list_remove(&scene_output->link); wl_list_remove(&scene_output->output_commit.link); wl_list_remove(&scene_output->output_mode.link); + wl_list_remove(&scene_output->output_needs_frame.link); free(scene_output); } @@ -1072,9 +1092,8 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output->x = lx; scene_output->y = ly; - wlr_output_damage_add_whole(scene_output->damage); - scene_node_update_outputs(&scene_output->scene->tree.node, NULL); + scene_output_update_geometry(scene_output); } struct check_scanout_data { @@ -1174,7 +1193,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_log(WLR_DEBUG, "Direct scan-out %s", scanout ? "enabled" : "disabled"); // When exiting direct scan-out, damage everything - wlr_output_damage_add_whole(scene_output->damage); + wlr_damage_ring_add_whole(&scene_output->damage_ring); } scene_output->prev_scanout = scanout; if (scanout) { @@ -1182,7 +1201,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { } if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_RERENDER) { - wlr_output_damage_add_whole(scene_output->damage); + wlr_damage_ring_add_whole(&scene_output->damage_ring); } struct timespec now; @@ -1191,13 +1210,13 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { clock_gettime(CLOCK_MONOTONIC, &now); // add the current frame's damage if there is damage - if (pixman_region32_not_empty(&scene_output->damage->current)) { + if (pixman_region32_not_empty(&scene_output->damage_ring.current)) { struct highlight_region *current_damage = calloc(1, sizeof(*current_damage)); if (current_damage) { pixman_region32_init(¤t_damage->region); pixman_region32_copy(¤t_damage->region, - &scene_output->damage->current); + &scene_output->damage_ring.current); memcpy(¤t_damage->when, &now, sizeof(now)); wl_list_insert(regions, ¤t_damage->link); } @@ -1220,20 +1239,21 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { } } - wlr_output_damage_add(scene_output->damage, &acc_damage); + wlr_damage_ring_add(&scene_output->damage_ring, &acc_damage); pixman_region32_fini(&acc_damage); } - bool needs_frame; - pixman_region32_t damage; - pixman_region32_init(&damage); - if (!wlr_output_damage_attach_render(scene_output->damage, - &needs_frame, &damage)) { - pixman_region32_fini(&damage); + int buffer_age; + if (!wlr_output_attach_render(output, &buffer_age)) { return false; } - if (!needs_frame) { + pixman_region32_t damage; + pixman_region32_init(&damage); + wlr_damage_ring_get_buffer_damage(&scene_output->damage_ring, + buffer_age, &damage); + if (!output->needs_frame && !pixman_region32_not_empty( + &scene_output->damage_ring.current)) { pixman_region32_fini(&damage); wlr_output_rollback(output); return true; @@ -1294,13 +1314,18 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { pixman_region32_t frame_damage; pixman_region32_init(&frame_damage); - wlr_region_transform(&frame_damage, &scene_output->damage->current, + wlr_region_transform(&frame_damage, + &scene_output->damage_ring.current, transform, tr_width, tr_height); wlr_output_set_damage(output, &frame_damage); pixman_region32_fini(&frame_damage); bool success = wlr_output_commit(output); + if (success) { + wlr_damage_ring_rotate(&scene_output->damage_ring); + } + if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT && !wl_list_empty(&scene_output->scene->damage_highlight_regions)) { wlr_output_schedule_frame(scene_output->output); From 694b8c66837ab232f32fabd212869f4e2b4606ad Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Wed, 29 Jun 2022 21:10:08 +0300 Subject: [PATCH 219/298] scene: add missing output damage listener This is necessary to handle damage coming from the backend and software cursors. --- include/wlr/types/wlr_scene.h | 1 + types/scene/wlr_scene.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 74f552887..95f18f375 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -176,6 +176,7 @@ struct wlr_scene_output { struct wl_listener output_commit; struct wl_listener output_mode; + struct wl_listener output_damage; struct wl_listener output_needs_frame; }; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 0b127e601..a6328a367 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1001,6 +1001,15 @@ static void scene_output_handle_mode(struct wl_listener *listener, void *data) { scene_output_update_geometry(scene_output); } +static void scene_output_handle_damage(struct wl_listener *listener, void *data) { + struct wlr_scene_output *scene_output = wl_container_of(listener, + scene_output, output_damage); + struct wlr_output_event_damage *event = data; + if (wlr_damage_ring_add(&scene_output->damage_ring, event->damage)) { + wlr_output_schedule_frame(scene_output->output); + } +} + static void scene_output_handle_needs_frame(struct wl_listener *listener, void *data) { struct wlr_scene_output *scene_output = wl_container_of(listener, scene_output, output_needs_frame); @@ -1045,6 +1054,9 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, scene_output->output_mode.notify = scene_output_handle_mode; wl_signal_add(&output->events.mode, &scene_output->output_mode); + scene_output->output_damage.notify = scene_output_handle_damage; + wl_signal_add(&output->events.damage, &scene_output->output_damage); + scene_output->output_needs_frame.notify = scene_output_handle_needs_frame; wl_signal_add(&output->events.needs_frame, &scene_output->output_needs_frame); @@ -1067,6 +1079,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wl_list_remove(&scene_output->link); wl_list_remove(&scene_output->output_commit.link); wl_list_remove(&scene_output->output_mode.link); + wl_list_remove(&scene_output->output_damage.link); wl_list_remove(&scene_output->output_needs_frame.link); free(scene_output); From ffb53a6103bcaf23a9991008dc7fee09fb803542 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 1 Jul 2022 20:37:34 +0200 Subject: [PATCH 220/298] Document NULL return value of foo_from_wlr_surface() functions wlr_xdg_surface_from_wlr_surface() for example may return NULL even if the surface has the xdg surface role if the corresponding xdg surface has been destroyed. --- include/wlr/types/wlr_input_method_v2.h | 11 +++++++++++ include/wlr/types/wlr_layer_shell_v1.h | 9 +++++++++ include/wlr/types/wlr_session_lock_v1.h | 10 ++++++++++ include/wlr/types/wlr_subcompositor.h | 9 +++++++-- include/wlr/types/wlr_xdg_shell.h | 9 +++++++++ include/wlr/xwayland.h | 9 +++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_input_method_v2.h b/include/wlr/types/wlr_input_method_v2.h index 316cecd5d..8baeae57b 100644 --- a/include/wlr/types/wlr_input_method_v2.h +++ b/include/wlr/types/wlr_input_method_v2.h @@ -122,9 +122,20 @@ void wlr_input_method_v2_send_done(struct wlr_input_method_v2 *input_method); void wlr_input_method_v2_send_unavailable( struct wlr_input_method_v2 *input_method); +/** + * Returns true if the surface has the input popup surface role. + */ bool wlr_surface_is_input_popup_surface_v2(struct wlr_surface *surface); + +/** + * Get a struct wlr_input_popup_surface_v2 from a struct wlr_surface. + * Asserts that the surface has the input popup surface role. + * May return NULL even if the surface has the input popup surface role if the + * corresponding input popup surface has been destroyed. + */ struct wlr_input_popup_surface_v2 *wlr_input_popup_surface_v2_from_wlr_surface( struct wlr_surface *surface); + void wlr_input_popup_surface_v2_send_text_input_rectangle( struct wlr_input_popup_surface_v2 *popup_surface, struct wlr_box *sbox); diff --git a/include/wlr/types/wlr_layer_shell_v1.h b/include/wlr/types/wlr_layer_shell_v1.h index e97c73117..3ebdbeda6 100644 --- a/include/wlr/types/wlr_layer_shell_v1.h +++ b/include/wlr/types/wlr_layer_shell_v1.h @@ -140,8 +140,17 @@ uint32_t wlr_layer_surface_v1_configure(struct wlr_layer_surface_v1 *surface, */ void wlr_layer_surface_v1_destroy(struct wlr_layer_surface_v1 *surface); +/** + * Returns true if the surface has the layer surface role. + */ bool wlr_surface_is_layer_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_layer_surface from a struct wlr_surface. + * Asserts that the surface has the layer surface role. + * May return NULL even if the surface has the layer surface role if the + * corresponding layer surface has been destroyed. + */ struct wlr_layer_surface_v1 *wlr_layer_surface_v1_from_wlr_surface( struct wlr_surface *surface); diff --git a/include/wlr/types/wlr_session_lock_v1.h b/include/wlr/types/wlr_session_lock_v1.h index 101fe56cc..c09978c70 100644 --- a/include/wlr/types/wlr_session_lock_v1.h +++ b/include/wlr/types/wlr_session_lock_v1.h @@ -91,7 +91,17 @@ uint32_t wlr_session_lock_surface_v1_configure( struct wlr_session_lock_surface_v1 *lock_surface, uint32_t width, uint32_t height); +/** + * Returns true if the surface has the session lock surface role. + */ bool wlr_surface_is_session_lock_surface_v1(struct wlr_surface *surface); + +/** + * Get a struct wlr_session_lock_surface_v1 from a struct wlr_surface. + * Asserts that the surface has the session lock surface role. + * May return NULL even if the surface has the session lock surface role if the + * corresponding session lock surface has been destroyed. + */ struct wlr_session_lock_surface_v1 *wlr_session_lock_surface_v1_from_wlr_surface( struct wlr_surface *surface); diff --git a/include/wlr/types/wlr_subcompositor.h b/include/wlr/types/wlr_subcompositor.h index d8e57ed83..e7f6ab2f5 100644 --- a/include/wlr/types/wlr_subcompositor.h +++ b/include/wlr/types/wlr_subcompositor.h @@ -63,11 +63,16 @@ struct wlr_subcompositor { } events; }; +/** + * Returns true if the surface has the subsurface role. + */ bool wlr_surface_is_subsurface(struct wlr_surface *surface); /** - * Get a subsurface from a surface. Can return NULL if the subsurface has been - * destroyed. + * Get a struct wlr_subsurface from a struct wlr_surface. + * Asserts that the surface has the subsurface role. + * May return NULL even if the surface has the subsurface role if the + * corresponding subsurface has been destroyed. */ struct wlr_subsurface *wlr_subsurface_from_wlr_surface( struct wlr_surface *surface); diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 802f03a5e..b4ef2e94c 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -462,8 +462,17 @@ struct wlr_surface *wlr_xdg_surface_popup_surface_at( struct wlr_xdg_surface *surface, double sx, double sy, double *sub_x, double *sub_y); +/** + * Returns true if the surface has the xdg surface role. + */ bool wlr_surface_is_xdg_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_xdg_surface from a struct wlr_surface. + * Asserts that the surface has the xdg surface role. + * May return NULL even if the surface has the xdg surface role if the + * corresponding xdg surface has been destroyed. + */ struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface( struct wlr_surface *surface); diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index f1c76f69c..ca35da802 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -273,8 +273,17 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface, void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, struct wlr_seat *seat); +/** + * Returns true if the surface has the xwayland surface role. + */ bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_xwayland_surface from a struct wlr_surface. + * Asserts that the surface has the xwayland surface role. + * May return NULL even if the surface has the xwayland surface role if the + * corresponding xwayland surface has been destroyed. + */ struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( struct wlr_surface *surface); From fdfdd01a796a736a2c41a80e2670972b3d4b1eff Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 3 Jul 2022 12:15:08 -0400 Subject: [PATCH 221/298] wlr_scene: Use direct assignment for damage indicator timestamps --- types/scene/wlr_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index a6328a367..828d06e6e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1230,7 +1230,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { pixman_region32_init(¤t_damage->region); pixman_region32_copy(¤t_damage->region, &scene_output->damage_ring.current); - memcpy(¤t_damage->when, &now, sizeof(now)); + current_damage->when = now; wl_list_insert(regions, ¤t_damage->link); } } From 5dc1d4671dd2ca3c1f0f09587c463fdbb542f0a4 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 3 Jul 2022 12:20:41 -0400 Subject: [PATCH 222/298] wlr_scene: Maintain damage highlight regions per output The logic doesn't support handling multiple outputs so let's not break the assumption and handle damages per output much like how damage_ring is done. --- include/wlr/types/wlr_scene.h | 3 ++- types/scene/wlr_scene.c | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 95f18f375..85d0f94eb 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -93,7 +93,6 @@ struct wlr_scene { struct wl_listener presentation_destroy; enum wlr_scene_debug_damage_option debug_damage_option; - struct wl_list damage_highlight_regions; }; /** A scene-graph node displaying a single surface. */ @@ -178,6 +177,8 @@ struct wlr_scene_output { struct wl_listener output_mode; struct wl_listener output_damage; struct wl_listener output_needs_frame; + + struct wl_list damage_highlight_regions; }; /** A layer shell scene helper */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 828d06e6e..68b05b7c8 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -74,12 +74,6 @@ struct highlight_region { struct wl_list link; }; -static void highlight_region_destroy(struct highlight_region *damage) { - wl_list_remove(&damage->link); - pixman_region32_fini(&damage->region); - free(damage); -} - void wlr_scene_node_destroy(struct wlr_scene_node *node) { if (node == NULL) { return; @@ -119,11 +113,6 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_scene_output_destroy(scene_output); } - struct highlight_region *damage, *tmp_damage; - wl_list_for_each_safe(damage, tmp_damage, &scene->damage_highlight_regions, link) { - highlight_region_destroy(damage); - } - wl_list_remove(&scene->presentation_destroy.link); } else { assert(node->parent); @@ -158,7 +147,6 @@ struct wlr_scene *wlr_scene_create(void) { wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); - wl_list_init(&scene->damage_highlight_regions); char *debug_damage = getenv("WLR_SCENE_DEBUG_DAMAGE"); if (debug_damage) { @@ -1028,6 +1016,7 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, wlr_addon_init(&scene_output->addon, &output->addons, scene, &output_addon_impl); wlr_damage_ring_init(&scene_output->damage_ring); + wl_list_init(&scene_output->damage_highlight_regions); int prev_output_index = -1; struct wl_list *prev_output_link = &scene->outputs; @@ -1065,6 +1054,12 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, return scene_output; } +static void highlight_region_destroy(struct highlight_region *damage) { + wl_list_remove(&damage->link); + pixman_region32_fini(&damage->region); + free(damage); +} + void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { if (scene_output == NULL) { return; @@ -1074,6 +1069,11 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { scene_node_update_outputs(&scene_output->scene->tree.node, scene_output); + struct highlight_region *damage, *tmp_damage; + wl_list_for_each_safe(damage, tmp_damage, &scene_output->damage_highlight_regions, link) { + highlight_region_destroy(damage); + } + wlr_addon_finish(&scene_output->addon); wlr_damage_ring_finish(&scene_output->damage_ring); wl_list_remove(&scene_output->link); @@ -1219,7 +1219,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct timespec now; if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { - struct wl_list *regions = &scene_output->scene->damage_highlight_regions; + struct wl_list *regions = &scene_output->damage_highlight_regions; clock_gettime(CLOCK_MONOTONIC, &now); // add the current frame's damage if there is damage @@ -1292,7 +1292,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { struct highlight_region *damage; - wl_list_for_each(damage, &scene_output->scene->damage_highlight_regions, link) { + wl_list_for_each(damage, &scene_output->damage_highlight_regions, link) { struct timespec time_diff; timespec_sub(&time_diff, &now, &damage->when); int64_t time_diff_ms = timespec_to_msec(&time_diff); @@ -1340,7 +1340,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { } if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT && - !wl_list_empty(&scene_output->scene->damage_highlight_regions)) { + !wl_list_empty(&scene_output->damage_highlight_regions)) { wlr_output_schedule_frame(scene_output->output); } From c8f8ac672caf10a6b2688ed47ddda53cd3af145c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 11 Jul 2022 07:58:35 +0200 Subject: [PATCH 223/298] build: bump Wayland to v1.21 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 992b09b64..944dfa3ee 100644 --- a/meson.build +++ b/meson.build @@ -101,7 +101,7 @@ internal_features = { wayland_project_options = ['tests=false', 'documentation=false'] wayland_server = dependency('wayland-server', - version: '>=1.20', + version: '>=1.21', fallback: 'wayland', default_options: wayland_project_options, ) From c84cc660f0309a4139010be3cea631c464c52c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 25 Feb 2022 17:30:27 +0100 Subject: [PATCH 224/298] build: check if libinput supports high-res scroll Starting with Linux Kernel v5.0 two new axes are available for mice that support high-resolution wheel scrolling: REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES. Both axes send data in fractions of 120 where each multiple of 120 amounts to one logical scroll event. Fractions of 120 indicate a wheel movement less than one detent. Three new events are now available on libinput: LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, LIBINPUT_EVENT_POINTER_SCROLL_FINGER, and LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. These events replace the LIBINPUT_EVENT_POINTER_AXIS event, so new clients should simply ignore that event. Also, two new APIs are available to access the high-resolution data: libinput_event_pointer_get_scroll_value() and libinput_event_pointer_get_scroll_value_v120(). Add a project argument (LIBINPUT_HAS_SCROLL_VALUE120) to allow building against old versions of libinput or, where high-resolution scroll is available, support it. --- backend/libinput/meson.build | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/libinput/meson.build b/backend/libinput/meson.build index 38ba05f12..2f3ccab3e 100644 --- a/backend/libinput/meson.build +++ b/backend/libinput/meson.build @@ -28,8 +28,8 @@ wlr_files += files( features += { 'libinput-backend': true } wlr_deps += libinput -# libinput hold gestures are available since 1.19.0 -add_project_arguments( +# libinput hold gestures and high resolution scroll are available since 1.19.0 +add_project_arguments([ '-DLIBINPUT_HAS_HOLD_GESTURES=@0@'.format(libinput.version().version_compare('>=1.19.0').to_int()), - language: 'c', -) + '-DLIBINPUT_HAS_SCROLL_VALUE120=@0@'.format(libinput.version().version_compare('>=1.19.0').to_int()), +], language: 'c') From 65c436407f37118618b348b9b7303b55322d66a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 25 Feb 2022 17:30:31 +0100 Subject: [PATCH 225/298] pointer: transform low-res to high-res axis events Currently, the "wlr_event_pointer_axis" event stores low-resolution values in its "delta_discrete" field. Low-resolution values are always multiples of one, i.e., 1 for one wheel detent, 2 for two wheel detents, etc. In order to simplify internal handling of events, always transform in the backend from the low-resolution value into the high-resolution value. The transformation is performed by multiplying by 120. The 120 magic number is used by the kernel and it is exposed to clients in the "WLR_POINTER_AXIS_DISCRETE_STEP" constant. --- backend/libinput/pointer.c | 1 + backend/wayland/pointer.c | 2 +- include/wlr/types/wlr_pointer.h | 2 ++ types/seat/wlr_seat_pointer.c | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 124a4fda3..b391b0e5d 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -116,6 +116,7 @@ void handle_pointer_axis(struct libinput_event *event, libinput_event_pointer_get_axis_value(pevent, axes[i]); wlr_event.delta_discrete = libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); + wlr_event.delta_discrete *= WLR_POINTER_AXIS_DISCRETE_STEP; wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); } } diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index db31f1abb..897f7108c 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -184,7 +184,7 @@ static void pointer_handle_axis_discrete(void *data, return; } - pointer->axis_discrete = discrete; + pointer->axis_discrete = discrete * WLR_POINTER_AXIS_DISCRETE_STEP; } static const struct wl_pointer_listener pointer_listener = { diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index cce2a5a87..16aed1dc7 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -78,6 +78,8 @@ enum wlr_axis_orientation { WLR_AXIS_ORIENTATION_HORIZONTAL, }; +#define WLR_POINTER_AXIS_DISCRETE_STEP 120 + struct wlr_pointer_axis_event { struct wlr_pointer *pointer; uint32_t time_msec; diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index ef058999b..d4ec38441 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -301,7 +301,7 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, if (value_discrete && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { wl_pointer_send_axis_discrete(resource, orientation, - value_discrete); + value_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); } wl_pointer_send_axis(resource, time, orientation, From c6032d6b1cc1cfb884924bb8afbdd200c3258d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 25 Feb 2022 17:30:42 +0100 Subject: [PATCH 226/298] backend/libinput: handle high-res scroll events On newer versions of libinput, the event LIBINPUT_EVENT_POINTER_AXIS has been deprecated in favour of LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, LIBINPUT_EVENT_POINTER_SCROLL_FINGER and LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS. Where new events are provided by the backend, ignore LIBINPUT_EVENT_POINTER_AXIS, receive high-resolution scroll events from libinput and emit the appropiate wlr_pointer signal. --- backend/libinput/events.c | 17 +++++++++++++++++ backend/libinput/pointer.c | 39 ++++++++++++++++++++++++++++++++++++++ include/backend/libinput.h | 4 ++++ 3 files changed, 60 insertions(+) diff --git a/backend/libinput/events.c b/backend/libinput/events.c index b9f2f43c5..c5d9c67a3 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -176,8 +176,25 @@ void handle_libinput_event(struct wlr_libinput_backend *backend, handle_pointer_button(event, &dev->pointer); break; case LIBINPUT_EVENT_POINTER_AXIS: +#if !LIBINPUT_HAS_SCROLL_VALUE120 + /* This event must be ignored in favour of the SCROLL_* events */ handle_pointer_axis(event, &dev->pointer); +#endif break; +#if LIBINPUT_HAS_SCROLL_VALUE120 + case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: + handle_pointer_axis_value120(event, &dev->pointer, + WLR_AXIS_SOURCE_WHEEL); + break; + case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: + handle_pointer_axis_value120(event, &dev->pointer, + WLR_AXIS_SOURCE_FINGER); + break; + case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: + handle_pointer_axis_value120(event, &dev->pointer, + WLR_AXIS_SOURCE_CONTINUOUS); + break; +#endif case LIBINPUT_EVENT_TOUCH_DOWN: handle_touch_down(event, &dev->touch); break; diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index b391b0e5d..50b63c90e 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -123,6 +123,45 @@ void handle_pointer_axis(struct libinput_event *event, wlr_signal_emit_safe(&pointer->events.frame, pointer); } +#if LIBINPUT_HAS_SCROLL_VALUE120 +void handle_pointer_axis_value120(struct libinput_event *event, + struct wlr_pointer *pointer, enum wlr_axis_source source) { + struct libinput_event_pointer *pevent = + libinput_event_get_pointer_event(event); + struct wlr_pointer_axis_event wlr_event = { 0 }; + wlr_event.pointer = pointer; + wlr_event.time_msec = + usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); + wlr_event.source = source; + + const enum libinput_pointer_axis axes[] = { + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + }; + for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) { + if (!libinput_event_pointer_has_axis(pevent, axes[i])) { + continue; + } + switch (axes[i]) { + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL; + break; + } + wlr_event.delta = + libinput_event_pointer_get_scroll_value(pevent, axes[i]); + if (source == WLR_AXIS_SOURCE_WHEEL) { + wlr_event.delta_discrete = + libinput_event_pointer_get_scroll_value_v120(pevent, axes[i]); + } + wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); + } + wlr_signal_emit_safe(&pointer->events.frame, pointer); +} +#endif + void handle_pointer_swipe_begin(struct libinput_event *event, struct wlr_pointer *pointer) { struct libinput_event_gesture *gevent = diff --git a/include/backend/libinput.h b/include/backend/libinput.h index 7c1dc30aa..1ec94c2d9 100644 --- a/include/backend/libinput.h +++ b/include/backend/libinput.h @@ -70,6 +70,10 @@ void handle_pointer_button(struct libinput_event *event, struct wlr_pointer *pointer); void handle_pointer_axis(struct libinput_event *event, struct wlr_pointer *pointer); +#if LIBINPUT_HAS_SCROLL_VALUE120 +void handle_pointer_axis_value120(struct libinput_event *event, + struct wlr_pointer *pointer, enum wlr_axis_source source); +#endif void handle_pointer_swipe_begin(struct libinput_event *event, struct wlr_pointer *pointer); void handle_pointer_swipe_update(struct libinput_event *event, From e00f042f801cf2f5f16bf2f8661d68b40e6d00e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 25 Feb 2022 17:30:51 +0100 Subject: [PATCH 227/298] backend/libinput: code style consistency Reduce a level of identation in "handle_pointer_axis" to keep the consistency with "handle_pointer_axis_value120". --- backend/libinput/pointer.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 50b63c90e..841d3dfca 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -103,22 +103,24 @@ void handle_pointer_axis(struct libinput_event *event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, }; for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) { - if (libinput_event_pointer_has_axis(pevent, axes[i])) { - switch (axes[i]) { - case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: - wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL; - break; - case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: - wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL; - break; - } - wlr_event.delta = - libinput_event_pointer_get_axis_value(pevent, axes[i]); - wlr_event.delta_discrete = - libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); - wlr_event.delta_discrete *= WLR_POINTER_AXIS_DISCRETE_STEP; - wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); + if (!libinput_event_pointer_has_axis(pevent, axes[i])) { + continue; } + + switch (axes[i]) { + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL; + break; + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL; + break; + } + wlr_event.delta = + libinput_event_pointer_get_axis_value(pevent, axes[i]); + wlr_event.delta_discrete = + libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); + wlr_event.delta_discrete *= WLR_POINTER_AXIS_DISCRETE_STEP; + wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); } wlr_signal_emit_safe(&pointer->events.frame, pointer); } From 11f49b6b6a4c0d269c502738fd8b5bc6fd187768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 25 Feb 2022 17:31:01 +0100 Subject: [PATCH 228/298] backend/wayland: handle high-res scroll events Receive high-resolution scroll events from the parent compositor using a Wayland listiner and emit the appropiate wlr_pointer signal. --- backend/wayland/backend.c | 9 ++++++++- backend/wayland/pointer.c | 12 ++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 998757f5f..07df69121 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -346,8 +346,15 @@ static void registry_global(void *data, struct wl_registry *registry, wl->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4); } else if (strcmp(iface, wl_seat_interface.name) == 0) { + uint32_t target_version = version; + if (version < 5) { + target_version = 5; + } + if (version > 8) { + target_version = 8; + } struct wl_seat *wl_seat = wl_registry_bind(registry, name, - &wl_seat_interface, 5); + &wl_seat_interface, target_version); if (!create_wl_seat(wl_seat, wl)) { wl_seat_destroy(wl_seat); } diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index 897f7108c..b2f85459c 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -187,6 +187,17 @@ static void pointer_handle_axis_discrete(void *data, pointer->axis_discrete = discrete * WLR_POINTER_AXIS_DISCRETE_STEP; } +static void pointer_handle_axis_value120(void *data, + struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + pointer->axis_discrete = value120; +} + static const struct wl_pointer_listener pointer_listener = { .enter = pointer_handle_enter, .leave = pointer_handle_leave, @@ -197,6 +208,7 @@ static const struct wl_pointer_listener pointer_listener = { .axis_source = pointer_handle_axis_source, .axis_stop = pointer_handle_axis_stop, .axis_discrete = pointer_handle_axis_discrete, + .axis_value120 = pointer_handle_axis_value120, }; static void gesture_swipe_begin(void *data, From 40dc5121aa4cc76ed9a6ededd6ff56570c1a2e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Sun, 27 Mar 2022 19:04:45 +0200 Subject: [PATCH 229/298] seat: support high-resolution clients Upgrade the seat protocol to version 8 and handle clients that support high-resolution scroll wheel events. Since the backend already sends discrete values in the 120 range, forwarding them is enough. --- types/seat/wlr_seat.c | 2 +- types/seat/wlr_seat_pointer.c | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index 5280bc465..d7652c124 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -13,7 +13,7 @@ #include "util/global.h" #include "util/signal.h" -#define SEAT_VERSION 7 +#define SEAT_VERSION 8 static void seat_handle_get_pointer(struct wl_client *client, struct wl_resource *seat_resource, uint32_t id) { diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index d4ec38441..1ddc1467c 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -269,6 +269,14 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time, return serial; } +static void send_axis_value120(struct wl_resource *resource, uint32_t time, + enum wlr_axis_orientation orientation, double value, + int32_t value_discrete) { + wl_pointer_send_axis_value120(resource, orientation, value_discrete); + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(value)); +} + void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, enum wlr_axis_orientation orientation, double value, int32_t value_discrete, enum wlr_axis_source source) { @@ -298,14 +306,18 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, wl_pointer_send_axis_source(resource, source); } if (value) { - if (value_discrete && - version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - wl_pointer_send_axis_discrete(resource, orientation, + if (value_discrete) { + if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) { + send_axis_value120(resource, time, orientation, value, + value_discrete); + } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + wl_pointer_send_axis_discrete(resource, orientation, value_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); + } + } else { + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(value)); } - - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(value)); } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { wl_pointer_send_axis_stop(resource, time, orientation); } From add44b3e2e4ff7ef98b16813fb3c9e1d8b398008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Sun, 27 Mar 2022 19:07:25 +0200 Subject: [PATCH 230/298] seat: support low-resolution clients When the client doesn't support high-resolution scroll, accumulate deltas until we can notify a discrete event. Some mice have a free spinning wheel, making possible to lock the wheel when the accumulator value is not 0. To avoid synchronization issues between the mouse wheel and the accumulators, store the last delta and when the scroll direction changes, reset the accumulator. --- include/wlr/types/wlr_seat.h | 13 ++++++++++ types/seat/wlr_seat_pointer.c | 48 +++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 8c1d46613..d19844497 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -54,6 +54,19 @@ struct wlr_seat_client { // for use by wlr_seat_client_{next_serial,validate_event_serial} struct wlr_serial_ringset serials; bool needs_touch_frame; + + // When the client doesn't support high-resolution scroll, accumulate deltas + // until we can notify a discrete event. + // Some mice have a free spinning wheel, making possible to lock the wheel + // when the accumulator value is not 0. To avoid synchronization issues + // between the mouse wheel and the accumulators, store the last delta and + // when the scroll direction changes, reset the accumulator. + // Indexed by wlr_axis_orientation. + struct { + int32_t acc_discrete[2]; + int32_t last_discrete[2]; + double acc_axis[2]; + } value120; }; struct wlr_touch_point { diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 1ddc1467c..7d37fb129 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -269,6 +269,48 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time, return serial; } +static bool should_reset_value120_accumulators(int32_t current, int32_t last) { + if (last == 0) { + return true; + } + + return (current < 0 && last > 0) || (current > 0 && last < 0); +} + +static void update_value120_accumulators(struct wlr_seat_client *client, + enum wlr_axis_orientation orientation, + double value, int32_t value_discrete) { + int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; + int32_t *last_discrete = &client->value120.last_discrete[orientation]; + double *acc_axis = &client->value120.acc_axis[orientation]; + if (should_reset_value120_accumulators(value_discrete, *last_discrete)) { + *acc_discrete = 0; + *acc_axis = 0; + } + *acc_discrete += value_discrete; + *last_discrete = value_discrete; + *acc_axis += value; +} + +static void send_axis_discrete(struct wlr_seat_client *client, + struct wl_resource *resource, uint32_t time, + enum wlr_axis_orientation orientation, double value, + int32_t value_discrete) { + int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; + double *acc_axis = &client->value120.acc_axis[orientation]; + + if (abs(*acc_discrete) < WLR_POINTER_AXIS_DISCRETE_STEP) { + return; + } + + wl_pointer_send_axis_discrete(resource, orientation, + *acc_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(*acc_axis)); + *acc_discrete %= WLR_POINTER_AXIS_DISCRETE_STEP; + *acc_axis = 0; +} + static void send_axis_value120(struct wl_resource *resource, uint32_t time, enum wlr_axis_orientation orientation, double value, int32_t value_discrete) { @@ -294,6 +336,8 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, send_source = true; } + update_value120_accumulators(client, orientation, value, value_discrete); + struct wl_resource *resource; wl_resource_for_each(resource, &client->pointers) { if (wlr_seat_client_from_pointer_resource(resource) == NULL) { @@ -311,8 +355,8 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, send_axis_value120(resource, time, orientation, value, value_discrete); } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - wl_pointer_send_axis_discrete(resource, orientation, - value_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); + send_axis_discrete(client, resource, time, orientation, + value, value_discrete); } } else { wl_pointer_send_axis(resource, time, orientation, From 972a5cdf7a9701a266119d60da48624ca8ebf703 Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Wed, 20 Jul 2022 19:21:14 -0400 Subject: [PATCH 231/298] render/gles2: simplify alpha depth check GL_ALPHA_BITS is the number of bits of the alpha channel of the currently bound frame buffer's color buffer -- which is precisely renderer->current_buffer->rbo . Thus, instead of binding the color buffer and checking its properties, we can query the already bound frame buffer. Note that GL_IMPLEMENTATION_COLOR_READ_{FORMAT,TYPE} are also properties of frame buffer's color buffer. --- render/gles2/renderer.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 5a2f31b55..c00a7f51c 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -395,15 +395,10 @@ static uint32_t gles2_preferred_read_format( push_gles2_debug(renderer); - GLint gl_format = -1, gl_type = -1; + GLint gl_format = -1, gl_type = -1, alpha_size = -1; glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_format); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_type); - - EGLint alpha_size = -1; - glBindRenderbuffer(GL_RENDERBUFFER, renderer->current_buffer->rbo); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, - GL_RENDERBUFFER_ALPHA_SIZE, &alpha_size); - glBindRenderbuffer(GL_RENDERBUFFER, 0); + glGetIntegerv(GL_ALPHA_BITS, &alpha_size); pop_gles2_debug(renderer); From bd587a7f431e53764d5e8051f2717d32d4c62b69 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jul 2022 22:04:20 +0200 Subject: [PATCH 232/298] backend/drm: use drmModeGetConnectorTypeName No need to manually maintain this table now. The wlroots names and the libdrm (= kernel) names all match. References: https://gitlab.freedesktop.org/mesa/drm/-/commit/50f8d517733d24fce6693ffae552f9833e2e6aa9 --- backend/drm/drm.c | 9 +++++++-- backend/drm/util.c | 31 ------------------------------- include/backend/drm/util.h | 2 -- meson.build | 2 +- 4 files changed, 8 insertions(+), 36 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 262a533e6..660477b66 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1250,9 +1250,14 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_conn->status = WLR_DRM_CONN_DISCONNECTED; wlr_conn->id = drm_conn->connector_id; + const char *conn_name = + drmModeGetConnectorTypeName(drm_conn->connector_type); + if (conn_name == NULL) { + conn_name = "Unknown"; + } + snprintf(wlr_conn->name, sizeof(wlr_conn->name), - "%s-%"PRIu32, conn_get_name(drm_conn->connector_type), - drm_conn->connector_type_id); + "%s-%"PRIu32, conn_name, drm_conn->connector_type_id); wl_list_insert(drm->outputs.prev, &wlr_conn->link); wlr_log(WLR_INFO, "Found connector '%s'", wlr_conn->name); diff --git a/backend/drm/util.c b/backend/drm/util.c index d56eee38f..2083e6179 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -121,37 +121,6 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) } } -const char *conn_get_name(uint32_t type_id) { - switch (type_id) { - case DRM_MODE_CONNECTOR_Unknown: return "Unknown"; - case DRM_MODE_CONNECTOR_VGA: return "VGA"; - case DRM_MODE_CONNECTOR_DVII: return "DVI-I"; - case DRM_MODE_CONNECTOR_DVID: return "DVI-D"; - case DRM_MODE_CONNECTOR_DVIA: return "DVI-A"; - case DRM_MODE_CONNECTOR_Composite: return "Composite"; - case DRM_MODE_CONNECTOR_SVIDEO: return "SVIDEO"; - case DRM_MODE_CONNECTOR_LVDS: return "LVDS"; - case DRM_MODE_CONNECTOR_Component: return "Component"; - case DRM_MODE_CONNECTOR_9PinDIN: return "DIN"; - case DRM_MODE_CONNECTOR_DisplayPort: return "DP"; - case DRM_MODE_CONNECTOR_HDMIA: return "HDMI-A"; - case DRM_MODE_CONNECTOR_HDMIB: return "HDMI-B"; - case DRM_MODE_CONNECTOR_TV: return "TV"; - case DRM_MODE_CONNECTOR_eDP: return "eDP"; - case DRM_MODE_CONNECTOR_VIRTUAL: return "Virtual"; - case DRM_MODE_CONNECTOR_DSI: return "DSI"; - case DRM_MODE_CONNECTOR_DPI: return "DPI"; - case DRM_MODE_CONNECTOR_WRITEBACK: return "Writeback"; -#ifdef DRM_MODE_CONNECTOR_SPI - case DRM_MODE_CONNECTOR_SPI: return "SPI"; -#endif -#ifdef DRM_MODE_CONNECTOR_USB - case DRM_MODE_CONNECTOR_USB: return "USB"; -#endif - default: return "Unknown"; - } -} - static bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) { for (size_t i = 0; i < n; ++i) { if (arr[i] == key) { diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h index 323894b56..fc632e12b 100644 --- a/include/backend/drm/util.h +++ b/include/backend/drm/util.h @@ -11,8 +11,6 @@ struct wlr_drm_connector; int32_t calculate_refresh_rate(const drmModeModeInfo *mode); // Populates the make/model/phys_{width,height} of output from the edid data void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data); -// Returns the string representation of a DRM output type -const char *conn_get_name(uint32_t type_id); // Part of match_obj enum { diff --git a/meson.build b/meson.build index 944dfa3ee..d04d3c167 100644 --- a/meson.build +++ b/meson.build @@ -107,7 +107,7 @@ wayland_server = dependency('wayland-server', ) drm = dependency('libdrm', - version: '>=2.4.109', + version: '>=2.4.112', fallback: 'libdrm', default_options: [ 'libkms=false', From 7b5e890e61a27375725068a7d1884b26851b3102 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 8 Jul 2022 22:07:23 +0200 Subject: [PATCH 233/298] backend/drm: use drmModeConnectorGetPossibleCrtcs This function has been merged in libdrm. References: https://gitlab.freedesktop.org/mesa/drm/-/commit/3ee004ef529f43366fdd1f4d32b26872cc82c6ca --- backend/drm/drm.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 660477b66..6d7168e9a 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1164,23 +1164,6 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { } } -static uint32_t get_possible_crtcs(int fd, const drmModeConnector *conn) { - uint32_t possible_crtcs = 0; - - for (int i = 0; i < conn->count_encoders; ++i) { - drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoders[i]); - if (!enc) { - continue; - } - - possible_crtcs |= enc->possible_crtcs; - - drmModeFreeEncoder(enc); - } - - return possible_crtcs; -} - static void disconnect_drm_connector(struct wlr_drm_connector *conn); void scan_drm_connectors(struct wlr_drm_backend *drm, @@ -1389,7 +1372,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wl_list_insert(wlr_conn->output.modes.prev, &mode->wlr_mode.link); } - wlr_conn->possible_crtcs = get_possible_crtcs(drm->fd, drm_conn); + wlr_conn->possible_crtcs = + drmModeConnectorGetPossibleCrtcs(drm->fd, drm_conn); if (wlr_conn->possible_crtcs == 0) { wlr_drm_conn_log(wlr_conn, WLR_ERROR, "No CRTC possible"); } From 7298c42139f9f8c5538dd0ba837699d63609839e Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Mon, 18 Jul 2022 15:58:56 +0300 Subject: [PATCH 234/298] seat/pointer: rework sending axis events This commit fixes: - sending discrete scrolling events to multiple pointer resources - sending events to clients which don't support wl_pointer.axis_discrete --- types/seat/wlr_seat_pointer.c | 73 ++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 7d37fb129..36ce42b34 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -279,10 +279,17 @@ static bool should_reset_value120_accumulators(int32_t current, int32_t last) { static void update_value120_accumulators(struct wlr_seat_client *client, enum wlr_axis_orientation orientation, - double value, int32_t value_discrete) { + double value, int32_t value_discrete, + double *low_res_value, int32_t *low_res_value_discrete) { + if (value_discrete == 0) { + // Continuous scrolling has no effect on accumulators + return; + } + int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; int32_t *last_discrete = &client->value120.last_discrete[orientation]; double *acc_axis = &client->value120.acc_axis[orientation]; + if (should_reset_value120_accumulators(value_discrete, *last_discrete)) { *acc_discrete = 0; *acc_axis = 0; @@ -290,33 +297,17 @@ static void update_value120_accumulators(struct wlr_seat_client *client, *acc_discrete += value_discrete; *last_discrete = value_discrete; *acc_axis += value; -} -static void send_axis_discrete(struct wlr_seat_client *client, - struct wl_resource *resource, uint32_t time, - enum wlr_axis_orientation orientation, double value, - int32_t value_discrete) { - int32_t *acc_discrete = &client->value120.acc_discrete[orientation]; - double *acc_axis = &client->value120.acc_axis[orientation]; - - if (abs(*acc_discrete) < WLR_POINTER_AXIS_DISCRETE_STEP) { - return; + // Compute low resolution event values for older clients and reset + // the accumulators if needed + *low_res_value_discrete = *acc_discrete / WLR_POINTER_AXIS_DISCRETE_STEP; + if (*low_res_value_discrete == 0) { + *low_res_value = 0; + } else { + *acc_discrete -= *low_res_value_discrete * WLR_POINTER_AXIS_DISCRETE_STEP; + *low_res_value = *acc_axis; + *acc_axis = 0; } - - wl_pointer_send_axis_discrete(resource, orientation, - *acc_discrete / WLR_POINTER_AXIS_DISCRETE_STEP); - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(*acc_axis)); - *acc_discrete %= WLR_POINTER_AXIS_DISCRETE_STEP; - *acc_axis = 0; -} - -static void send_axis_value120(struct wl_resource *resource, uint32_t time, - enum wlr_axis_orientation orientation, double value, - int32_t value_discrete) { - wl_pointer_send_axis_value120(resource, orientation, value_discrete); - wl_pointer_send_axis(resource, time, orientation, - wl_fixed_from_double(value)); } void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, @@ -336,7 +327,10 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, send_source = true; } - update_value120_accumulators(client, orientation, value, value_discrete); + double low_res_value; + int32_t low_res_value_discrete; + update_value120_accumulators(client, orientation, value, value_discrete, + &low_res_value, &low_res_value_discrete); struct wl_resource *resource; wl_resource_for_each(resource, &client->pointers) { @@ -346,19 +340,36 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, uint32_t version = wl_resource_get_version(resource); + if (version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION && + value_discrete != 0 && low_res_value_discrete == 0) { + // The client doesn't support high resolution discrete scrolling + // and we haven't accumulated enough wheel clicks for a single + // low resolution event. Don't send anything. + continue; + } + if (send_source && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { wl_pointer_send_axis_source(resource, source); } if (value) { if (value_discrete) { if (version >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION) { - send_axis_value120(resource, time, orientation, value, + // High resolution discrete scrolling + wl_pointer_send_axis_value120(resource, orientation, value_discrete); - } else if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - send_axis_discrete(client, resource, time, orientation, - value, value_discrete); + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(value)); + } else { + // Low resolution discrete scrolling + if (version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + wl_pointer_send_axis_discrete(resource, orientation, + low_res_value_discrete); + } + wl_pointer_send_axis(resource, time, orientation, + wl_fixed_from_double(low_res_value)); } } else { + // Continuous scrolling wl_pointer_send_axis(resource, time, orientation, wl_fixed_from_double(value)); } From 30bf8a4303bc5df3cb87b7e6555592dbf8d95cf1 Mon Sep 17 00:00:00 2001 From: Quantum Date: Thu, 28 Jul 2022 02:25:31 -0400 Subject: [PATCH 235/298] seat/pointer: fix uninitialized variable warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This results in the following warning, which in release mode causes an error due to -Werror: ../types/seat/wlr_seat_pointer.c: In function ‘wlr_seat_pointer_send_axis’: ../types/seat/wlr_seat_pointer.c:344:25: error: ‘low_res_value_discrete’ may be used uninitialized in this function [-Werror=maybe-uninitialized] 343 | if (version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION && | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 344 | value_discrete != 0 && low_res_value_discrete == 0) { | ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors --- types/seat/wlr_seat_pointer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 36ce42b34..2b49b79fa 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -328,7 +328,7 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, } double low_res_value; - int32_t low_res_value_discrete; + int32_t low_res_value_discrete = 0; update_value120_accumulators(client, orientation, value, value_discrete, &low_res_value, &low_res_value_discrete); From f1e05a64933d78830e0d783758f8d584ce16b825 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 6 May 2022 19:52:56 +0200 Subject: [PATCH 236/298] xdg-shell: add support for v5 This version adds a wm_capabilities event. --- include/wlr/types/wlr_xdg_shell.h | 17 ++++++++++++ protocol/meson.build | 2 +- types/xdg_shell/wlr_xdg_shell.c | 2 +- types/xdg_shell/wlr_xdg_toplevel.c | 44 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index b4ef2e94c..90371282e 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -140,8 +140,16 @@ struct wlr_xdg_toplevel_state { uint32_t min_width, min_height; }; +enum wlr_xdg_toplevel_wm_capabilities { + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU = 1 << 0, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE = 1 << 1, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 1 << 2, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE = 1 << 3, +}; + enum wlr_xdg_toplevel_configure_field { WLR_XDG_TOPLEVEL_CONFIGURE_BOUNDS = 1 << 0, + WLR_XDG_TOPLEVEL_CONFIGURE_WM_CAPABILITIES = 1 << 1, }; struct wlr_xdg_toplevel_configure { @@ -152,6 +160,7 @@ struct wlr_xdg_toplevel_configure { struct { uint32_t width, height; } bounds; + uint32_t wm_capabilities; // enum wlr_xdg_toplevel_wm_capabilities }; struct wlr_xdg_toplevel_requested { @@ -394,6 +403,14 @@ uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_toplevel *toplevel, uint32_t wlr_xdg_toplevel_set_bounds(struct wlr_xdg_toplevel *toplevel, int32_t width, int32_t height); +/** + * Configure the window manager capabilities for this toplevel. `caps` is a + * bitfield of `enum wlr_xdg_toplevel_wm_capabilities`. Returns the associated + * configure serial. + */ +uint32_t wlr_xdg_toplevel_set_wm_capabilities(struct wlr_xdg_toplevel *toplevel, + uint32_t caps); + /** * Request that this toplevel closes. */ diff --git a/protocol/meson.build b/protocol/meson.build index 179c731dc..4cc018742 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -1,5 +1,5 @@ wayland_protos = dependency('wayland-protocols', - version: '>=1.25', + version: '>=1.26', fallback: 'wayland-protocols', default_options: ['tests=false'], ) diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 9008de4ed..06d11847f 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -3,7 +3,7 @@ #include "types/wlr_xdg_shell.h" #include "util/signal.h" -#define WM_BASE_VERSION 4 +#define WM_BASE_VERSION 5 static const struct xdg_wm_base_interface xdg_shell_impl; diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index dee2571fb..878b00912 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -39,6 +39,31 @@ struct wlr_xdg_toplevel_configure *send_xdg_toplevel_configure( configure->bounds.width, configure->bounds.height); } + if ((configure->fields & WLR_XDG_TOPLEVEL_CONFIGURE_WM_CAPABILITIES) && + version >= XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) { + size_t caps_len = 0; + uint32_t caps[32]; + if (configure->wm_capabilities & WLR_XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU) { + caps[caps_len++] = XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU; + } + if (configure->wm_capabilities & WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE) { + caps[caps_len++] = XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE; + } + if (configure->wm_capabilities & WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN) { + caps[caps_len++] = XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN; + } + if (configure->wm_capabilities & WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE) { + caps[caps_len++] = XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE; + } + assert(caps_len <= sizeof(caps) / sizeof(caps[0])); + + struct wl_array caps_array = { + .size = caps_len * sizeof(caps[0]), + .data = caps, + }; + xdg_toplevel_send_wm_capabilities(toplevel->resource, &caps_array); + } + size_t nstates = 0; uint32_t states[32]; if (configure->maximized) { @@ -97,6 +122,16 @@ void handle_xdg_toplevel_committed(struct wlr_xdg_toplevel *toplevel) { // is added wlr_xdg_surface_schedule_configure(toplevel->base); toplevel->added = true; + + if (toplevel->base->client->shell->version >= + XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION) { + // The first configure event must carry WM capabilities + wlr_xdg_toplevel_set_wm_capabilities(toplevel, + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU | + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE | + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN | + WLR_XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE); + } return; } @@ -524,3 +559,12 @@ uint32_t wlr_xdg_toplevel_set_bounds(struct wlr_xdg_toplevel *toplevel, toplevel->scheduled.bounds.height = height; return wlr_xdg_surface_schedule_configure(toplevel->base); } + +uint32_t wlr_xdg_toplevel_set_wm_capabilities(struct wlr_xdg_toplevel *toplevel, + uint32_t caps) { + assert(toplevel->base->client->shell->version >= + XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION); + toplevel->scheduled.fields |= WLR_XDG_TOPLEVEL_CONFIGURE_WM_CAPABILITIES; + toplevel->scheduled.wm_capabilities = caps; + return wlr_xdg_surface_schedule_configure(toplevel->base); +} From b24b50ec0c1c54a14acf34df2c95b37043d15b49 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 18 Jan 2022 19:48:40 +0100 Subject: [PATCH 237/298] single-pixel-buffer-v1: new protocol implementation This implements the single-pixel-buffer-v1 protocol [1], to allow clients to create 1x1 buffers with a single color. [1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/104 --- .../wlr/types/wlr_single_pixel_buffer_v1.h | 19 ++ protocol/meson.build | 1 + types/meson.build | 1 + types/wlr_single_pixel_buffer_v1.c | 172 ++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 include/wlr/types/wlr_single_pixel_buffer_v1.h create mode 100644 types/wlr_single_pixel_buffer_v1.c diff --git a/include/wlr/types/wlr_single_pixel_buffer_v1.h b/include/wlr/types/wlr_single_pixel_buffer_v1.h new file mode 100644 index 000000000..3eba546a5 --- /dev/null +++ b/include/wlr/types/wlr_single_pixel_buffer_v1.h @@ -0,0 +1,19 @@ +/* + * This an unstable interface of wlroots. No guarantees are made regarding the + * future consistency of this API. + */ +#ifndef WLR_USE_UNSTABLE +#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" +#endif + +#ifndef WLR_TYPES_WLR_SINGLE_PIXEL_BUFFER_V1 +#define WLR_TYPES_WLR_SINGLE_PIXEL_BUFFER_V1 + +#include + +struct wlr_single_pixel_buffer_manager_v1; + +struct wlr_single_pixel_buffer_manager_v1 *wlr_single_pixel_buffer_manager_v1_create( + struct wl_display *display); + +#endif diff --git a/protocol/meson.build b/protocol/meson.build index 4cc018742..920c181ca 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -21,6 +21,7 @@ protocols = { 'xdg-activation-v1': wl_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml', 'drm-lease-v1': wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', 'ext-session-lock-v1': wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', + 'single-pixel-buffer-v1': wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', # Unstable upstream protocols 'fullscreen-shell-unstable-v1': wl_protocol_dir / 'unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml', diff --git a/types/meson.build b/types/meson.build index 53bf852b8..19360eb7d 100644 --- a/types/meson.build +++ b/types/meson.build @@ -63,6 +63,7 @@ wlr_files += files( 'wlr_screencopy_v1.c', 'wlr_server_decoration.c', 'wlr_session_lock_v1.c', + 'wlr_single_pixel_buffer_v1.c', 'wlr_subcompositor.c', 'wlr_switch.c', 'wlr_tablet_pad.c', diff --git a/types/wlr_single_pixel_buffer_v1.c b/types/wlr_single_pixel_buffer_v1.c new file mode 100644 index 000000000..e4dac829f --- /dev/null +++ b/types/wlr_single_pixel_buffer_v1.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include "single-pixel-buffer-v1-protocol.h" + +#define SINGLE_PIXEL_MANAGER_VERSION 1 + +struct wlr_single_pixel_buffer_manager_v1 { + struct wl_global *global; + + struct wl_listener display_destroy; +}; + +struct wlr_single_pixel_buffer_v1 { + struct wlr_buffer base; + struct wl_resource *resource; + uint32_t r, g, b, a; + uint8_t argb8888[4]; // packed little-endian DRM_FORMAT_ARGB8888 +}; + +static void destroy_resource(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static const struct wl_buffer_interface wl_buffer_impl = { + .destroy = destroy_resource, +}; + +static const struct wlr_buffer_impl buffer_impl; + +static bool buffer_resource_is_instance(struct wl_resource *resource) { + return wl_resource_instance_of(resource, &wl_buffer_interface, + &wl_buffer_impl); +} + +static struct wlr_single_pixel_buffer_v1 *single_pixel_buffer_v1_from_resource( + struct wl_resource *resource) { + assert(buffer_resource_is_instance(resource)); + return wl_resource_get_user_data(resource); +} + +static struct wlr_buffer *buffer_from_resource( + struct wl_resource *resource) { + return &single_pixel_buffer_v1_from_resource(resource)->base; +} + +static const struct wlr_buffer_resource_interface buffer_resource_interface = { + .name = "single_pixel_buffer_v1", + .is_instance = buffer_resource_is_instance, + .from_resource = buffer_from_resource, +}; + +static void buffer_destroy(struct wlr_buffer *wlr_buffer) { + struct wlr_single_pixel_buffer_v1 *buffer = + wl_container_of(wlr_buffer, buffer, base); + if (buffer->resource != NULL) { + wl_resource_set_user_data(buffer->resource, NULL); + } + free(buffer); +} + +static bool buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, + uint32_t flags, void **data, uint32_t *format, size_t *stride) { + struct wlr_single_pixel_buffer_v1 *buffer = + wl_container_of(wlr_buffer, buffer, base); + if (flags & ~WLR_BUFFER_DATA_PTR_ACCESS_READ) { + return false; // the buffer is read-only + } + *data = &buffer->argb8888; + *format = DRM_FORMAT_ARGB8888; + *stride = sizeof(buffer->argb8888); + return true; +} + +static void buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { + // This space is intentionally left blank +} + +static const struct wlr_buffer_impl buffer_impl = { + .destroy = buffer_destroy, + .begin_data_ptr_access = buffer_begin_data_ptr_access, + .end_data_ptr_access = buffer_end_data_ptr_access, +}; + +static void buffer_handle_resource_destroy(struct wl_resource *resource) { + struct wlr_single_pixel_buffer_v1 *buffer = single_pixel_buffer_v1_from_resource(resource); + buffer->resource = NULL; + wlr_buffer_drop(&buffer->base); +} + +static void manager_handle_create_u32_rgba_buffer(struct wl_client *client, + struct wl_resource *resource, uint32_t id, uint32_t r, uint32_t g, + uint32_t b, uint32_t a) { + struct wlr_single_pixel_buffer_v1 *buffer = calloc(1, sizeof(*buffer)); + if (buffer == NULL) { + wl_client_post_no_memory(client); + return; + } + + buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id); + if (buffer->resource == NULL) { + wl_client_post_no_memory(client); + free(buffer); + return; + } + + wlr_buffer_init(&buffer->base, &buffer_impl, 1, 1); + wl_resource_set_implementation(buffer->resource, + &wl_buffer_impl, buffer, buffer_handle_resource_destroy); + + buffer->r = r; + buffer->g = g; + buffer->b = b; + buffer->a = a; + + double f = (double)0xFF / 0xFFFFFFFF; + buffer->argb8888[0] = (uint8_t)((double)buffer->b * f); + buffer->argb8888[1] = (uint8_t)((double)buffer->g * f); + buffer->argb8888[2] = (uint8_t)((double)buffer->r * f); + buffer->argb8888[3] = (uint8_t)((double)buffer->a * f); +} + +static const struct wp_single_pixel_buffer_manager_v1_interface manager_impl = { + .destroy = destroy_resource, + .create_u32_rgba_buffer = manager_handle_create_u32_rgba_buffer, +}; + +static void manager_bind(struct wl_client *client, void *data, + uint32_t version, uint32_t id) { + struct wl_resource *resource = wl_resource_create(client, + &wp_single_pixel_buffer_manager_v1_interface, version, id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &manager_impl, NULL, NULL); +} + +static void handle_display_destroy(struct wl_listener *listener, void *data) { + struct wlr_single_pixel_buffer_manager_v1 *manager = + wl_container_of(listener, manager, display_destroy); + wl_global_destroy(manager->global); + free(manager); +} + +struct wlr_single_pixel_buffer_manager_v1 *wlr_single_pixel_buffer_manager_v1_create( + struct wl_display *display) { + struct wlr_single_pixel_buffer_manager_v1 *manager = calloc(1, sizeof(*manager)); + if (manager == NULL) { + return NULL; + } + + manager->global = wl_global_create(display, + &wp_single_pixel_buffer_manager_v1_interface, + SINGLE_PIXEL_MANAGER_VERSION, + NULL, manager_bind); + if (manager->global == NULL) { + free(manager); + return NULL; + } + + manager->display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &manager->display_destroy); + + wlr_buffer_register_resource_interface(&buffer_resource_interface); + + return manager; +} From 668b2740ff0fed82f8e486b2abdb536cfe8c2da9 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 2 Aug 2022 18:26:46 +0200 Subject: [PATCH 238/298] Set mapped before firing map/unmap events This allows whatever the user calls from the signal handlers to react to observe the new state rather than the old, e.g. that a surface is no longer mapped in the unmap handler. --- types/data_device/wlr_drag.c | 2 +- types/wlr_input_method_v2.c | 2 +- types/wlr_layer_shell_v1.c | 3 ++- types/wlr_subcompositor.c | 4 ++-- types/xdg_shell/wlr_xdg_surface.c | 3 ++- xwayland/xwm.c | 4 ++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index 9865d9309..0843870dc 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -112,8 +112,8 @@ static void drag_icon_set_mapped(struct wlr_drag_icon *icon, bool mapped) { icon->mapped = true; wlr_signal_emit_safe(&icon->events.map, icon); } else if (!mapped && icon->mapped) { - wlr_signal_emit_safe(&icon->events.unmap, icon); icon->mapped = false; + wlr_signal_emit_safe(&icon->events.unmap, icon); } } diff --git a/types/wlr_input_method_v2.c b/types/wlr_input_method_v2.c index fe1568690..4a436e41d 100644 --- a/types/wlr_input_method_v2.c +++ b/types/wlr_input_method_v2.c @@ -143,8 +143,8 @@ static void popup_surface_set_mapped( popup_surface->mapped = true; wlr_signal_emit_safe(&popup_surface->events.map, popup_surface); } else if (!mapped && popup_surface->mapped) { - wlr_signal_emit_safe(&popup_surface->events.unmap, popup_surface); popup_surface->mapped = false; + wlr_signal_emit_safe(&popup_surface->events.unmap, popup_surface); } } diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index 038ea1d87..daee6290b 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -262,6 +262,8 @@ static const struct zwlr_layer_surface_v1_interface layer_surface_implementation }; static void layer_surface_unmap(struct wlr_layer_surface_v1 *surface) { + surface->configured = surface->mapped = false; + // TODO: probably need to ungrab before this event wlr_signal_emit_safe(&surface->events.unmap, surface); @@ -275,7 +277,6 @@ static void layer_surface_unmap(struct wlr_layer_surface_v1 *surface) { layer_surface_configure_destroy(configure); } - surface->configured = surface->mapped = false; } static void layer_surface_destroy(struct wlr_layer_surface_v1 *surface) { diff --git a/types/wlr_subcompositor.c b/types/wlr_subcompositor.c index 9467ec3c7..75902cac5 100644 --- a/types/wlr_subcompositor.c +++ b/types/wlr_subcompositor.c @@ -229,8 +229,8 @@ static void subsurface_consider_map(struct wlr_subsurface *subsurface, } // Now we can map the subsurface - wlr_signal_emit_safe(&subsurface->events.map, subsurface); subsurface->mapped = true; + wlr_signal_emit_safe(&subsurface->events.map, subsurface); // Try mapping all children too struct wlr_subsurface *child; @@ -249,8 +249,8 @@ static void subsurface_unmap(struct wlr_subsurface *subsurface) { return; } - wlr_signal_emit_safe(&subsurface->events.unmap, subsurface); subsurface->mapped = false; + wlr_signal_emit_safe(&subsurface->events.unmap, subsurface); // Unmap all children struct wlr_subsurface *child; diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 9ea8fa33b..c40cf35e0 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -29,6 +29,7 @@ static void xdg_surface_configure_destroy( void unmap_xdg_surface(struct wlr_xdg_surface *surface) { assert(surface->role != WLR_XDG_SURFACE_ROLE_NONE); + surface->configured = false; struct wlr_xdg_popup *popup, *popup_tmp; wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) { @@ -37,6 +38,7 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { // TODO: probably need to ungrab before this event if (surface->mapped) { + surface->mapped = false; wlr_signal_emit_safe(&surface->events.unmap, NULL); } @@ -56,7 +58,6 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { xdg_surface_configure_destroy(configure); } - surface->configured = surface->mapped = false; if (surface->configure_idle) { wl_event_source_remove(surface->configure_idle); surface->configure_idle = NULL; diff --git a/xwayland/xwm.c b/xwayland/xwm.c index b398f2abf..1bacd1ce0 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -836,8 +836,8 @@ static void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) { } if (!surface->mapped && wlr_surface_has_buffer(surface->surface)) { - wlr_signal_emit_safe(&surface->events.map, surface); surface->mapped = true; + wlr_signal_emit_safe(&surface->events.map, surface); xwm_set_net_client_list(surface->xwm); } } @@ -853,8 +853,8 @@ static void xwayland_surface_role_precommit(struct wlr_surface *wlr_surface, if (state->committed & WLR_SURFACE_STATE_BUFFER && state->buffer == NULL) { // This is a NULL commit if (surface->mapped) { - wlr_signal_emit_safe(&surface->events.unmap, surface); surface->mapped = false; + wlr_signal_emit_safe(&surface->events.unmap, surface); xwm_set_net_client_list(surface->xwm); } } From 7abe8352db188b82ff59dec945ac66ede3709375 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 4 Aug 2022 22:56:20 +0200 Subject: [PATCH 239/298] xdg_shell: Destroy popups after unmap event This aligns with wlr_layer_shell_v1, and better matches how we normally use teardown signals. --- types/xdg_shell/wlr_xdg_surface.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index c40cf35e0..5c337543b 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -31,17 +31,17 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { assert(surface->role != WLR_XDG_SURFACE_ROLE_NONE); surface->configured = false; - struct wlr_xdg_popup *popup, *popup_tmp; - wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) { - wlr_xdg_popup_destroy(popup); - } - // TODO: probably need to ungrab before this event if (surface->mapped) { surface->mapped = false; wlr_signal_emit_safe(&surface->events.unmap, NULL); } + struct wlr_xdg_popup *popup, *popup_tmp; + wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) { + wlr_xdg_popup_destroy(popup); + } + switch (surface->role) { case WLR_XDG_SURFACE_ROLE_TOPLEVEL: unmap_xdg_toplevel(surface->toplevel); From 3baf2a6bcfc4cb86c364f5724aaec80f28715a01 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 2 Aug 2022 18:28:06 +0200 Subject: [PATCH 240/298] scene/layer_shell: Ignore unmapped exclusion zone Only the exclusion zone for mapped layer shell surfaces should be respected. In particular, a layer shell surface that was mapped with an exclusion zone but is now unmapped should not adjust the usable area. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3471 --- types/scene/layer_shell_v1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/layer_shell_v1.c b/types/scene/layer_shell_v1.c index b674cd362..229869830 100644 --- a/types/scene/layer_shell_v1.c +++ b/types/scene/layer_shell_v1.c @@ -125,7 +125,7 @@ void wlr_scene_layer_surface_v1_configure( wlr_scene_node_set_position(&scene_layer_surface->tree->node, box.x, box.y); wlr_layer_surface_v1_configure(layer_surface, box.width, box.height); - if (state->exclusive_zone > 0) { + if (layer_surface->mapped && state->exclusive_zone > 0) { layer_surface_exclusive_zone(state, usable_area); } } From f72aeacd6e0366b99a39996f561bf87c8ab86d41 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 8 Aug 2022 00:40:21 -0400 Subject: [PATCH 241/298] wlr_scene: Add option to disable direct scanout Closes: #3405 Supersedes: !3562 Co-authored-by: Xiao YaoBing --- docs/env_vars.md | 1 + include/wlr/types/wlr_scene.h | 1 + types/scene/wlr_scene.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+) diff --git a/docs/env_vars.md b/docs/env_vars.md index 6a0a94421..e5d5d62b8 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -50,6 +50,7 @@ wlroots reads these environment variables * *WLR_SCENE_DEBUG_DAMAGE*: specifies debug options for screen damage related tasks for compositors that use scenes (available options: none, rerender, highlight) +* *WLR_SCENE_DISABLE_DIRECT_SCANOUT*: disables direct scan-out for debugging. # Generic diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 85d0f94eb..a87379210 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -93,6 +93,7 @@ struct wlr_scene { struct wl_listener presentation_destroy; enum wlr_scene_debug_damage_option debug_damage_option; + bool direct_scanout; }; /** A scene-graph node displaying a single surface. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 68b05b7c8..3c4581163 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -164,6 +164,20 @@ struct wlr_scene *wlr_scene_create(void) { scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_NONE; } + char *disable_direct_scanout = getenv("WLR_SCENE_DISABLE_DIRECT_SCANOUT"); + if (disable_direct_scanout) { + wlr_log(WLR_INFO, "Loading WLR_SCENE_DISABLE_DIRECT_SCANOUT option: %s", disable_direct_scanout); + } + + if (!disable_direct_scanout || strcmp(disable_direct_scanout, "0") == 0) { + scene->direct_scanout = true; + } else if (strcmp(disable_direct_scanout, "1") == 0) { + scene->direct_scanout = false; + } else { + wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DISABLE_DIRECT_SCANOUT option: %s", disable_direct_scanout); + scene->direct_scanout = true; + } + return scene; } @@ -1140,6 +1154,10 @@ static void check_scanout_iterator(struct wlr_scene_node *node, } static bool scene_output_scanout(struct wlr_scene_output *scene_output) { + if (!scene_output->scene->direct_scanout) { + return false; + } + if (scene_output->scene->debug_damage_option == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { // We don't want to enter direct scan out if we have highlight regions From 6a5fb22698f3e69109ec5aae79b9cff239eeaf2e Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 28 Jul 2022 10:25:35 +0200 Subject: [PATCH 242/298] backend/drm: remove unused WLR_DRM_CONN_CLEANUP --- include/backend/drm/drm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 700ed6546..0fb164c4c 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -95,7 +95,6 @@ enum wlr_drm_connector_status { WLR_DRM_CONN_DISCONNECTED, // An output just has been plugged in and is waiting for a modeset WLR_DRM_CONN_NEEDS_MODESET, - WLR_DRM_CONN_CLEANUP, WLR_DRM_CONN_CONNECTED, }; From 08973d24304807a91634765103ec488743881e80 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 28 Jul 2022 10:33:45 +0200 Subject: [PATCH 243/298] backend/drm: drop WLR_DRM_CONN_NEEDS_MODESET - Add wlr_output.enabled checks to CONNECTED checks - Replace NEEDS_MODESET with CONNECTED --- backend/drm/drm.c | 19 ++++++------------- include/backend/drm/drm.h | 2 -- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 6d7168e9a..c2ea0f8de 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -707,8 +707,7 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn, return true; } - if (conn->status != WLR_DRM_CONN_CONNECTED - && conn->status != WLR_DRM_CONN_NEEDS_MODESET) { + if (conn->status != WLR_DRM_CONN_CONNECTED) { wlr_drm_conn_log(conn, WLR_ERROR, "Cannot modeset a disconnected output"); return false; @@ -735,7 +734,6 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn, return false; } - conn->status = WLR_DRM_CONN_CONNECTED; wlr_output_update_mode(&conn->output, wlr_mode); wlr_output_update_enabled(&conn->output, true); conn->desired_enabled = true; @@ -1086,9 +1084,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { // Only search CRTCs for user-enabled outputs (that are already // connected or in need of a modeset) - if ((conn->status == WLR_DRM_CONN_CONNECTED || - conn->status == WLR_DRM_CONN_NEEDS_MODESET) && - conn->desired_enabled) { + if (conn->status == WLR_DRM_CONN_CONNECTED && conn->desired_enabled) { connector_constraints[i] = conn->possible_crtcs; } else { // Will always fail to match anything @@ -1119,8 +1115,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { */ for (size_t i = 0; i < num_outputs; ++i) { struct wlr_drm_connector *conn = connectors[i]; - if (conn->status == WLR_DRM_CONN_CONNECTED && - conn->desired_enabled && + if (conn->status == WLR_DRM_CONN_CONNECTED && conn->output.enabled && connector_match[i] == -1) { wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; " "keeping old configuration"); @@ -1147,7 +1142,6 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { if (connector_match[i] == -1) { if (prev_enabled) { wlr_drm_conn_log(conn, WLR_DEBUG, "Output has lost its CRTC"); - conn->status = WLR_DRM_CONN_NEEDS_MODESET; wlr_output_update_enabled(&conn->output, false); wlr_output_update_mode(&conn->output, NULL); } @@ -1157,7 +1151,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { conn->crtc = &drm->crtcs[connector_match[i]]; // Only realloc buffers if we have actually been modeset - if (conn->status != WLR_DRM_CONN_CONNECTED) { + if (conn->status != WLR_DRM_CONN_CONNECTED || !conn->output.enabled) { continue; } wlr_output_damage_whole(&conn->output); @@ -1383,10 +1377,9 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_output_update_enabled(&wlr_conn->output, wlr_conn->crtc != NULL); wlr_conn->desired_enabled = true; - wlr_conn->status = WLR_DRM_CONN_NEEDS_MODESET; + wlr_conn->status = WLR_DRM_CONN_CONNECTED; new_outputs[new_outputs_len++] = wlr_conn; - } else if ((wlr_conn->status == WLR_DRM_CONN_CONNECTED || - wlr_conn->status == WLR_DRM_CONN_NEEDS_MODESET) && + } else if (wlr_conn->status == WLR_DRM_CONN_CONNECTED && drm_conn->connection != DRM_MODE_CONNECTED) { wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->name); disconnect_drm_connector(wlr_conn); diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 0fb164c4c..8ab0c279d 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -93,8 +93,6 @@ struct wlr_drm_backend { enum wlr_drm_connector_status { // Connector is available but no output is plugged in WLR_DRM_CONN_DISCONNECTED, - // An output just has been plugged in and is waiting for a modeset - WLR_DRM_CONN_NEEDS_MODESET, WLR_DRM_CONN_CONNECTED, }; From f24409468213d363bcc7dca3130c78619ee1a138 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 28 Jul 2022 10:38:21 +0200 Subject: [PATCH 244/298] backend/drm: drop enum wlr_drm_connector_status We can just use libdrm's drmModeConnection enum instead. --- backend/drm/drm.c | 24 ++++++++++++------------ include/backend/drm/drm.h | 8 +------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c2ea0f8de..432f0427b 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -707,7 +707,7 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn, return true; } - if (conn->status != WLR_DRM_CONN_CONNECTED) { + if (conn->status != DRM_MODE_CONNECTED) { wlr_drm_conn_log(conn, WLR_ERROR, "Cannot modeset a disconnected output"); return false; @@ -905,7 +905,7 @@ static void drm_connector_destroy_output(struct wlr_output *output) { dealloc_crtc(conn); - conn->status = WLR_DRM_CONN_DISCONNECTED; + conn->status = DRM_MODE_DISCONNECTED; conn->desired_enabled = false; conn->possible_crtcs = 0; conn->pending_page_flip_crtc = 0; @@ -1084,7 +1084,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { // Only search CRTCs for user-enabled outputs (that are already // connected or in need of a modeset) - if (conn->status == WLR_DRM_CONN_CONNECTED && conn->desired_enabled) { + if (conn->status == DRM_MODE_CONNECTED && conn->desired_enabled) { connector_constraints[i] = conn->possible_crtcs; } else { // Will always fail to match anything @@ -1115,7 +1115,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { */ for (size_t i = 0; i < num_outputs; ++i) { struct wlr_drm_connector *conn = connectors[i]; - if (conn->status == WLR_DRM_CONN_CONNECTED && conn->output.enabled && + if (conn->status == DRM_MODE_CONNECTED && conn->output.enabled && connector_match[i] == -1) { wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; " "keeping old configuration"); @@ -1151,7 +1151,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) { conn->crtc = &drm->crtcs[connector_match[i]]; // Only realloc buffers if we have actually been modeset - if (conn->status != WLR_DRM_CONN_CONNECTED || !conn->output.enabled) { + if (conn->status != DRM_MODE_CONNECTED || !conn->output.enabled) { continue; } wlr_output_damage_whole(&conn->output); @@ -1224,7 +1224,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, } wlr_conn->backend = drm; - wlr_conn->status = WLR_DRM_CONN_DISCONNECTED; + wlr_conn->status = DRM_MODE_DISCONNECTED; wlr_conn->id = drm_conn->connector_id; const char *conn_name = @@ -1271,7 +1271,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, } } - if (wlr_conn->status == WLR_DRM_CONN_DISCONNECTED && + if (wlr_conn->status == DRM_MODE_DISCONNECTED && drm_conn->connection == DRM_MODE_CONNECTED) { wlr_log(WLR_INFO, "'%s' connected", wlr_conn->name); wlr_log(WLR_DEBUG, "Current CRTC: %d", @@ -1377,9 +1377,9 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, wlr_output_update_enabled(&wlr_conn->output, wlr_conn->crtc != NULL); wlr_conn->desired_enabled = true; - wlr_conn->status = WLR_DRM_CONN_CONNECTED; + wlr_conn->status = DRM_MODE_CONNECTED; new_outputs[new_outputs_len++] = wlr_conn; - } else if (wlr_conn->status == WLR_DRM_CONN_CONNECTED && + } else if (wlr_conn->status == DRM_MODE_CONNECTED && drm_conn->connection != DRM_MODE_CONNECTED) { wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->name); disconnect_drm_connector(wlr_conn); @@ -1469,7 +1469,7 @@ static void handle_page_flip(int fd, unsigned seq, conn->pending_page_flip_crtc = 0; - if (conn->status != WLR_DRM_CONN_CONNECTED || conn->crtc == NULL) { + if (conn->status != DRM_MODE_CONNECTED || conn->crtc == NULL) { wlr_drm_conn_log(conn, WLR_DEBUG, "Ignoring page-flip event for disabled connector"); return; @@ -1532,7 +1532,7 @@ int handle_drm_event(int fd, uint32_t mask, void *data) { } static void disconnect_drm_connector(struct wlr_drm_connector *conn) { - if (conn->status == WLR_DRM_CONN_DISCONNECTED) { + if (conn->status == DRM_MODE_DISCONNECTED) { return; } @@ -1540,7 +1540,7 @@ static void disconnect_drm_connector(struct wlr_drm_connector *conn) { // our wlr_drm_connector. wlr_output_destroy(&conn->output); - assert(conn->status == WLR_DRM_CONN_DISCONNECTED); + assert(conn->status == DRM_MODE_DISCONNECTED); } void destroy_drm_connector(struct wlr_drm_connector *conn) { diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h index 8ab0c279d..f362f18a0 100644 --- a/include/backend/drm/drm.h +++ b/include/backend/drm/drm.h @@ -90,12 +90,6 @@ struct wlr_drm_backend { struct wlr_drm_format_set mgpu_formats; }; -enum wlr_drm_connector_status { - // Connector is available but no output is plugged in - WLR_DRM_CONN_DISCONNECTED, - WLR_DRM_CONN_CONNECTED, -}; - struct wlr_drm_mode { struct wlr_output_mode wlr_mode; drmModeModeInfo drm_mode; @@ -113,7 +107,7 @@ struct wlr_drm_connector { struct wlr_drm_backend *backend; char name[24]; - enum wlr_drm_connector_status status; + drmModeConnection status; bool desired_enabled; uint32_t id; uint64_t max_bpc; From 8c3c6987dbdffa74eb1fee901b4ab1d73641e29f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 11 Aug 2022 09:09:37 +0200 Subject: [PATCH 245/298] backend/wayland: fix touch device not added on startup We were firing the new_input signal on backend initialization, before the compositor had the chance to add a listener for it. Mimick what's done for wl_keyboard: if the backend hasn't been started, delay wl_touch initialization. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3473 --- backend/wayland/backend.c | 4 ++++ backend/wayland/seat.c | 6 ++++-- include/backend/wayland.h | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 07df69121..2980324f6 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -424,6 +424,10 @@ static bool backend_start(struct wlr_backend *backend) { init_seat_keyboard(seat); } + if (seat->wl_touch) { + init_seat_touch(seat); + } + if (wl->tablet_manager) { init_seat_tablet(seat); } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index d1c75b397..655f9dad1 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -212,7 +212,7 @@ static const struct wlr_touch_impl touch_impl = { .name = "wl-touch", }; -static void init_seat_touch(struct wlr_wl_seat *seat) { +void init_seat_touch(struct wlr_wl_seat *seat) { assert(seat->wl_touch); char name[128] = {0}; @@ -333,7 +333,9 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wlr_log(WLR_DEBUG, "seat '%s' offering touch", seat->name); seat->wl_touch = wl_seat_get_touch(wl_seat); - init_seat_touch(seat); + if (backend->started) { + init_seat_touch(seat); + } } if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch != NULL) { wlr_log(WLR_DEBUG, "seat '%s' dropping touch", seat->name); diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 5baaac9d8..3a0b13271 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -144,6 +144,8 @@ void init_seat_pointer(struct wlr_wl_seat *seat); void finish_seat_pointer(struct wlr_wl_seat *seat); void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); +void init_seat_touch(struct wlr_wl_seat *seat); + void init_seat_tablet(struct wlr_wl_seat *seat); void finish_seat_tablet(struct wlr_wl_seat *seat); From 98cf38601fdf32fdd1d40ed4a92b1f31fb75d667 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 29 May 2022 11:50:47 +0200 Subject: [PATCH 246/298] render: replace wlr_texture_write_pixels with update_from_buffer This lets the renderer handle the wlr_buffer directly, just like it does in texture_from_buffer. This also allows the renderer to batch the rectangle updates, and update more than the damage region if desirable (e.g. too many rects), so can be more efficient. --- include/wlr/render/interface.h | 6 ++-- include/wlr/render/wlr_texture.h | 17 +++++++---- include/wlr/types/wlr_buffer.h | 3 -- render/gles2/texture.c | 46 ++++++++++++++++++++++-------- render/vulkan/texture.c | 47 +++++++++++++++++++++++++----- render/wlr_texture.c | 20 ++++++++----- types/wlr_buffer.c | 49 +------------------------------- 7 files changed, 101 insertions(+), 87 deletions(-) diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 7e923353e..20d755f9d 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -54,10 +54,8 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl); struct wlr_texture_impl { - bool (*write_pixels)(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data); + bool (*update_from_buffer)(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage); void (*destroy)(struct wlr_texture *texture); }; diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 0f39b8a89..5d4b0b618 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -9,6 +9,7 @@ #ifndef WLR_RENDER_WLR_TEXTURE_H #define WLR_RENDER_WLR_TEXTURE_H +#include #include #include #include @@ -37,13 +38,17 @@ struct wlr_texture *wlr_texture_from_dmabuf(struct wlr_renderer *renderer, struct wlr_dmabuf_attributes *attribs); /** - * Update a texture with raw pixels. The texture must be mutable, and the input - * data must have the same pixel format that the texture was created with. + * Update a texture with a struct wlr_buffer's contents. + * + * The update might be rejected (in case the texture is immutable, the buffer + * has an unsupported type/format, etc), so callers must be prepared to fall + * back to re-creating the texture from scratch via wlr_texture_from_buffer(). + * + * The damage can be used by the renderer as an optimization: only the supplied + * region needs to be updated. */ -bool wlr_texture_write_pixels(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data); +bool wlr_texture_update_from_buffer(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage); /** * Destroys the texture. diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 17b93e5c4..b24c0ccd1 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -151,9 +151,6 @@ struct wlr_client_buffer { // private state struct wl_listener source_destroy; - - // If the client buffer has been created from a wl_shm buffer - uint32_t shm_source_format; }; /** diff --git a/render/gles2/texture.c b/render/gles2/texture.c index d794e436b..8b4ce6739 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -44,14 +44,24 @@ static bool check_stride(const struct wlr_pixel_format_info *fmt, return true; } -static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data) { +static bool gles2_texture_update_from_buffer(struct wlr_texture *wlr_texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); if (texture->target != GL_TEXTURE_2D || texture->image != EGL_NO_IMAGE_KHR) { - wlr_log(WLR_ERROR, "Cannot write pixels to immutable texture"); + return false; + } + + void *data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + return false; + } + + if (format != texture->drm_format) { + wlr_buffer_end_data_ptr_access(buffer); return false; } @@ -63,7 +73,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, drm_get_pixel_format_info(texture->drm_format); assert(drm_fmt); - if (!check_stride(drm_fmt, stride, width)) { + if (!check_stride(drm_fmt, stride, buffer->width)) { + wlr_buffer_end_data_ptr_access(buffer); return false; } @@ -75,12 +86,21 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, glBindTexture(GL_TEXTURE_2D, texture->tex); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8)); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, src_x); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, src_y); + int rects_len = 0; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len); - glTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, width, height, - fmt->gl_format, fmt->gl_type, data); + for (int i = 0; i < rects_len; i++) { + pixman_box32_t rect = rects[i]; + + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (drm_fmt->bpp / 8)); + glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1); + + int width = rect.x2 - rect.x1; + int height = rect.y2 - rect.y1; + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, + fmt->gl_format, fmt->gl_type, data); + } glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); @@ -92,6 +112,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, wlr_egl_restore_context(&prev_ctx); + wlr_buffer_end_data_ptr_access(buffer); + return true; } @@ -156,7 +178,7 @@ static void gles2_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .write_pixels = gles2_texture_write_pixels, + .update_from_buffer = gles2_texture_update_from_buffer, .destroy = gles2_texture_unref, }; diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 35b9562e7..88298d93a 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -136,12 +136,45 @@ static bool write_pixels(struct wlr_texture *wlr_texture, return true; } -static bool vulkan_texture_write_pixels(struct wlr_texture *wlr_texture, - uint32_t stride, uint32_t width, uint32_t height, uint32_t src_x, - uint32_t src_y, uint32_t dst_x, uint32_t dst_y, const void *vdata) { - return write_pixels(wlr_texture, stride, width, height, src_x, src_y, - dst_x, dst_y, vdata, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); +static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { + struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); + + void *data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(buffer, + WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { + return false; + } + + bool ok = true; + + if (format != texture->format->drm_format) { + ok = false; + goto out; + } + + int rects_len = 0; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &rects_len); + + for (int i = 0; i < rects_len; i++) { + pixman_box32_t rect = rects[i]; + uint32_t width = rect.x2 - rect.x1; + uint32_t height = rect.y2 - rect.y1; + + // TODO: only map memory once + ok = write_pixels(wlr_texture, stride, width, height, rect.x1, rect.y1, + rect.x1, rect.y1, data, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); + if (!ok) { + goto out; + } + } + +out: + wlr_buffer_end_data_ptr_access(buffer); + return ok; } void vulkan_texture_destroy(struct wlr_vk_texture *texture) { @@ -191,7 +224,7 @@ static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { } static const struct wlr_texture_impl texture_impl = { - .write_pixels = vulkan_texture_write_pixels, + .update_from_buffer = vulkan_texture_update_from_buffer, .destroy = vulkan_texture_unref, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index fa864d02b..7a59af30d 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -71,13 +71,19 @@ struct wlr_texture *wlr_texture_from_buffer(struct wlr_renderer *renderer, return renderer->impl->texture_from_buffer(renderer, buffer); } -bool wlr_texture_write_pixels(struct wlr_texture *texture, - uint32_t stride, uint32_t width, uint32_t height, - uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, - const void *data) { - if (!texture->impl->write_pixels) { +bool wlr_texture_update_from_buffer(struct wlr_texture *texture, + struct wlr_buffer *buffer, pixman_region32_t *damage) { + if (!texture->impl->update_from_buffer) { return false; } - return texture->impl->write_pixels(texture, stride, width, height, - src_x, src_y, dst_x, dst_y, data); + if (texture->width != (uint32_t)buffer->width || + texture->height != (uint32_t)buffer->height) { + return false; + } + const pixman_box32_t *extents = pixman_region32_extents(damage); + if (extents->x1 < 0 || extents->y1 < 0 || extents->x2 > buffer->width || + extents->y2 > buffer->height) { + return false; + } + return texture->impl->update_from_buffer(texture, buffer, damage); } diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 49e205f3c..b63ce88ad 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -285,14 +285,6 @@ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy); client_buffer->source_destroy.notify = client_buffer_handle_source_destroy; - if (buffer_is_shm_client_buffer(buffer)) { - struct wlr_shm_client_buffer *shm_client_buffer = - shm_client_buffer_from_buffer(buffer); - client_buffer->shm_source_format = shm_client_buffer->format; - } else { - client_buffer->shm_source_format = DRM_FORMAT_INVALID; - } - // Ensure the buffer will be released before being destroyed wlr_buffer_lock(&client_buffer->base); wlr_buffer_drop(&client_buffer->base); @@ -307,46 +299,7 @@ bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer, return false; } - if ((uint32_t)next->width != client_buffer->texture->width || - (uint32_t)next->height != client_buffer->texture->height) { - return false; - } - - if (client_buffer->shm_source_format == DRM_FORMAT_INVALID) { - // Uploading only damaged regions only works for wl_shm buffers and - // mutable textures (created from wl_shm buffer) - return false; - } - - void *data; - uint32_t format; - size_t stride; - if (!wlr_buffer_begin_data_ptr_access(next, WLR_BUFFER_DATA_PTR_ACCESS_READ, - &data, &format, &stride)) { - return false; - } - - if (format != client_buffer->shm_source_format) { - // Uploading to textures can't change the format - wlr_buffer_end_data_ptr_access(next); - return false; - } - - int n; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &n); - for (int i = 0; i < n; ++i) { - pixman_box32_t *r = &rects[i]; - if (!wlr_texture_write_pixels(client_buffer->texture, stride, - r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1, - r->x1, r->y1, data)) { - wlr_buffer_end_data_ptr_access(next); - return false; - } - } - - wlr_buffer_end_data_ptr_access(next); - - return true; + return wlr_texture_update_from_buffer(client_buffer->texture, next, damage); } static const struct wlr_buffer_impl shm_client_buffer_impl; From 42d68d75324f33a1b65528ba6ea89ca9b624a201 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 29 Jun 2021 13:26:31 +0200 Subject: [PATCH 247/298] surface: add WLR_SURFACE_STATE_OFFSET This indicates whether the surface offset has changed. --- include/wlr/types/wlr_compositor.h | 1 + types/wlr_compositor.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 034b075b1..b0d1eed6a 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -28,6 +28,7 @@ enum wlr_surface_state_field { WLR_SURFACE_STATE_SCALE = 1 << 6, WLR_SURFACE_STATE_FRAME_CALLBACK_LIST = 1 << 7, WLR_SURFACE_STATE_VIEWPORT = 1 << 8, + WLR_SURFACE_STATE_OFFSET = 1 << 9, }; struct wlr_surface_state { diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index c1cdc3b05..f76e920a3 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -53,7 +53,8 @@ static void surface_handle_attach(struct wl_client *client, } } - surface->pending.committed |= WLR_SURFACE_STATE_BUFFER; + surface->pending.committed |= + WLR_SURFACE_STATE_BUFFER | WLR_SURFACE_STATE_OFFSET; surface->pending.dx = dx; surface->pending.dy = dy; @@ -279,11 +280,14 @@ static void surface_state_move(struct wlr_surface_state *state, if (next->committed & WLR_SURFACE_STATE_TRANSFORM) { state->transform = next->transform; } - if (next->committed & WLR_SURFACE_STATE_BUFFER) { + if (next->committed & WLR_SURFACE_STATE_OFFSET) { state->dx = next->dx; state->dy = next->dy; next->dx = next->dy = 0; - + } else { + state->dx = state->dy = 0; + } + if (next->committed & WLR_SURFACE_STATE_BUFFER) { wlr_buffer_unlock(state->buffer); state->buffer = NULL; if (next->buffer) { @@ -291,8 +295,6 @@ static void surface_state_move(struct wlr_surface_state *state, } wlr_buffer_unlock(next->buffer); next->buffer = NULL; - } else { - state->dx = state->dy = 0; } if (next->committed & WLR_SURFACE_STATE_SURFACE_DAMAGE) { pixman_region32_copy(&state->surface_damage, &next->surface_damage); From c2359d0321e03606ca7e2b69b69170fca4c4009a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 29 Jun 2021 13:32:07 +0200 Subject: [PATCH 248/298] surface: implement wl_surface.offset References: https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/123 --- types/wlr_compositor.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index f76e920a3..331d932d5 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -15,7 +15,7 @@ #include "util/signal.h" #include "util/time.h" -#define COMPOSITOR_VERSION 4 +#define COMPOSITOR_VERSION 5 #define CALLBACK_VERSION 1 static int min(int fst, int snd) { @@ -44,6 +44,14 @@ static void surface_handle_attach(struct wl_client *client, struct wl_resource *buffer_resource, int32_t dx, int32_t dy) { struct wlr_surface *surface = wlr_surface_from_resource(resource); + if (wl_resource_get_version(resource) >= WL_SURFACE_OFFSET_SINCE_VERSION && + (dx != 0 || dy != 0)) { + wl_resource_post_error(resource, WL_SURFACE_ERROR_INVALID_OFFSET, + "Offset must be zero on wl_surface.attach version >= %"PRIu32, + WL_SURFACE_OFFSET_SINCE_VERSION); + return; + } + struct wlr_buffer *buffer = NULL; if (buffer_resource != NULL) { buffer = wlr_buffer_from_resource(buffer_resource); @@ -53,13 +61,16 @@ static void surface_handle_attach(struct wl_client *client, } } - surface->pending.committed |= - WLR_SURFACE_STATE_BUFFER | WLR_SURFACE_STATE_OFFSET; - surface->pending.dx = dx; - surface->pending.dy = dy; + surface->pending.committed |= WLR_SURFACE_STATE_BUFFER; wlr_buffer_unlock(surface->pending.buffer); surface->pending.buffer = buffer; + + if (wl_resource_get_version(resource) < WL_SURFACE_OFFSET_SINCE_VERSION) { + surface->pending.committed |= WLR_SURFACE_STATE_OFFSET; + surface->pending.dx = dx; + surface->pending.dy = dy; + } } static void surface_handle_damage(struct wl_client *client, @@ -578,6 +589,15 @@ static void surface_handle_damage_buffer(struct wl_client *client, x, y, width, height); } +static void surface_handle_offset(struct wl_client *client, + struct wl_resource *resource, int32_t x, int32_t y) { + struct wlr_surface *surface = wlr_surface_from_resource(resource); + + surface->pending.committed |= WLR_SURFACE_STATE_OFFSET; + surface->pending.dx = x; + surface->pending.dy = y; +} + static const struct wl_surface_interface surface_implementation = { .destroy = surface_handle_destroy, .attach = surface_handle_attach, @@ -588,7 +608,8 @@ static const struct wl_surface_interface surface_implementation = { .commit = surface_handle_commit, .set_buffer_transform = surface_handle_set_buffer_transform, .set_buffer_scale = surface_handle_set_buffer_scale, - .damage_buffer = surface_handle_damage_buffer + .damage_buffer = surface_handle_damage_buffer, + .offset = surface_handle_offset, }; struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource) { From 7f17774d185607752efb21042ff887dfef85f658 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 11 Aug 2022 03:14:14 -0400 Subject: [PATCH 249/298] wlr_scene: Introduce scene_nodes_in_box Will query the scene for all nodes that appear in the given wlr_box. The nodes will be sent to the iterator from closest to farthest from the eye. Refactor wlr_scene_node_at to use this new function. --- types/scene/wlr_scene.c | 125 +++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 3c4581163..64b898d8e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -195,6 +195,50 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) { static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); +typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node, + int sx, int sy, void *data); + +static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, + scene_node_box_iterator_func_t iterator, void *user_data, int lx, int ly) { + if (!node->enabled) { + return false; + } + + switch (node->type) { + case WLR_SCENE_NODE_TREE:; + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each_reverse(child, &scene_tree->children, link) { + if (_scene_nodes_in_box(child, box, iterator, user_data, lx + child->x, ly + child->y)) { + return true; + } + } + break; + case WLR_SCENE_NODE_RECT: + case WLR_SCENE_NODE_BUFFER:; + struct wlr_box node_box = { .x = lx, .y = ly }; + scene_node_get_size(node, &node_box.width, &node_box.height); + bool intersects; + + intersects = wlr_box_intersection(&node_box, &node_box, box); + + if (intersects && iterator(node, lx, ly, user_data)) { + return true; + } + break; + } + + return false; +} + +static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, + scene_node_box_iterator_func_t iterator, void *user_data) { + int x, y; + wlr_scene_node_coords(node, &x, &y); + + return _scene_nodes_in_box(node, box, iterator, user_data, x, y); +} + // This function must be called whenever the coordinates/dimensions of a scene // buffer or scene output change. It is not necessary to call when a scene // buffer's node is enabled/disabled or obscured by other nodes. @@ -745,55 +789,56 @@ void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node, scene_node_for_each_scene_buffer(node, 0, 0, user_iterator, user_data); } -struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, - double lx, double ly, double *nx, double *ny) { - if (!node->enabled) { - return NULL; - } +struct node_at_data { + double lx, ly; + double rx, ry; + struct wlr_scene_node *node; +}; - // TODO: optimize by storing a bounding box in each node? - lx -= node->x; - ly -= node->y; +static bool scene_node_at_iterator(struct wlr_scene_node *node, + int lx, int ly, void *data) { + struct node_at_data *at_data = data; - bool intersects = false; - switch (node->type) { - case WLR_SCENE_NODE_TREE:; - struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); - struct wlr_scene_node *child; - wl_list_for_each_reverse(child, &scene_tree->children, link) { - struct wlr_scene_node *node = - wlr_scene_node_at(child, lx, ly, nx, ny); - if (node != NULL) { - return node; - } - } - break; - case WLR_SCENE_NODE_RECT:; - int width, height; - scene_node_get_size(node, &width, &height); - intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; - break; - case WLR_SCENE_NODE_BUFFER:; + double rx = at_data->lx - lx; + double ry = at_data->ly - ly; + + if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (scene_buffer->point_accepts_input) { - intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly); - } else { - int width, height; - scene_node_get_size(node, &width, &height); - intersects = lx >= 0 && lx < width && ly >= 0 && ly < height; + if (scene_buffer->point_accepts_input && + !scene_buffer->point_accepts_input(scene_buffer, rx, ry)) { + return false; } - break; } - if (intersects) { - if (nx != NULL) { - *nx = lx; + at_data->rx = rx; + at_data->ry = ry; + at_data->node = node; + return true; +} + +struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node, + double lx, double ly, double *nx, double *ny) { + struct wlr_box box = { + .x = floor(lx), + .y = floor(ly), + .width = 1, + .height = 1 + }; + + struct node_at_data data = { + .lx = lx, + .ly = ly + }; + + if (scene_nodes_in_box(node, &box, scene_node_at_iterator, &data)) { + if (nx) { + *nx = data.rx; } - if (ny != NULL) { - *ny = ly; + if (ny) { + *ny = data.ry; } - return node; + return data.node; } return NULL; From f411ca040ebac4cede9862a4d443472c25baccc6 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 17:53:45 -0400 Subject: [PATCH 250/298] wlr_scene: Damage scene on node destroy by disabling node This removes one trivial call of scene_node_damage_whole. It's easier to disable the node later than it is to do the damage dance later. --- types/scene/wlr_scene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 64b898d8e..4f62a8828 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -79,13 +79,13 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { return; } - scene_node_damage_whole(node); - // We want to call the destroy listeners before we do anything else // in case the destroy signal would like to remove children before they // are recursively destroyed. wlr_signal_emit_safe(&node->events.destroy, NULL); + wlr_scene_node_set_enabled(node, false); + struct wlr_scene *scene = scene_node_get_root(node); if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); From 028606512dfe9fe9d565f600669d06c35aa20f3a Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 17:58:13 -0400 Subject: [PATCH 251/298] wlr_scene: Add per scene node visibility --- include/wlr/types/wlr_scene.h | 4 ++++ types/scene/wlr_scene.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index a87379210..da0a794ab 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -64,6 +64,10 @@ struct wlr_scene_node { void *data; struct wlr_addon_set addons; + + // private state + + pixman_region32_t visible; }; enum wlr_scene_debug_damage_option { diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 4f62a8828..f4815ece1 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -58,6 +58,7 @@ static void scene_node_init(struct wlr_scene_node *node, wl_list_init(&node->link); wl_signal_init(&node->events.destroy); + pixman_region32_init(&node->visible); if (parent != NULL) { wl_list_insert(parent->children.prev, &node->link); @@ -127,6 +128,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_addon_set_finish(&node->addons); wl_list_remove(&node->link); + pixman_region32_fini(&node->visible); free(node); } @@ -610,6 +612,9 @@ static void _scene_node_damage_whole(struct wlr_scene_node *node, int width, height; scene_node_get_size(node, &width, &height); + pixman_region32_fini(&node->visible); + pixman_region32_init_rect(&node->visible, lx, ly, width, height); + struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { struct wlr_box box = { From c6246272fd46136a2cc3924d7c7f01cfa6e33f0c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 23:25:05 -0400 Subject: [PATCH 252/298] wlr_scene: Rework damage handling Simplify damage handling by using our cached visibility state. Damaging can happen in one step because since we can use the old visibility state which represent what portions of the screen the scene node was. This way we can damage everything in one step after the fact. --- types/scene/wlr_scene.c | 311 ++++++++++++++++++++++++---------------- 1 file changed, 189 insertions(+), 122 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index f4815ece1..498fa878a 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -67,8 +67,6 @@ static void scene_node_init(struct wlr_scene_node *node, wlr_addon_set_init(&node->addons); } -static void scene_node_damage_whole(struct wlr_scene_node *node); - struct highlight_region { pixman_region32_t region; struct timespec when; @@ -241,14 +239,44 @@ static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, return _scene_nodes_in_box(node, box, iterator, user_data, x, y); } -// This function must be called whenever the coordinates/dimensions of a scene -// buffer or scene output change. It is not necessary to call when a scene -// buffer's node is enabled/disabled or obscured by other nodes. -static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, - int lx, int ly, struct wlr_scene *scene, - struct wlr_scene_output *ignore) { - struct wlr_box buffer_box = { .x = lx, .y = ly }; - scene_node_get_size(&scene_buffer->node, &buffer_box.width, &buffer_box.height); +struct scene_update_data { + pixman_region32_t *visible; + pixman_region32_t *update_region; + struct wl_list *outputs; +}; + +static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) { + if (!pixman_region32_not_empty(damage)) { + return; + } + + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output, &scene->outputs, link) { + pixman_region32_t output_damage; + pixman_region32_init(&output_damage); + pixman_region32_copy(&output_damage, damage); + pixman_region32_translate(&output_damage, + -scene_output->x, -scene_output->y); + wlr_region_scale(&output_damage, &output_damage, + scene_output->output->scale); + if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { + wlr_output_schedule_frame(scene_output->output); + } + pixman_region32_fini(&output_damage); + } +} + +static void update_node_update_outputs(struct wlr_scene_node *node, + struct wl_list *outputs, struct wlr_scene_output *ignore) { + if (node->type != WLR_SCENE_NODE_BUFFER) { + return; + } + + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + + struct wlr_box buffer_box; + wlr_scene_node_coords(node, &buffer_box.x, &buffer_box.y); + scene_node_get_size(node, &buffer_box.width, &buffer_box.height); int largest_overlap = 0; scene_buffer->primary_output = NULL; @@ -262,7 +290,7 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, // to have a reasonable value. Otherwise, they may get a value that's in // the middle of a calculation. struct wlr_scene_output *scene_output; - wl_list_for_each(scene_output, &scene->outputs, link) { + wl_list_for_each(scene_output, outputs, link) { if (scene_output == ignore) { continue; } @@ -291,7 +319,7 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, uint64_t old_active = scene_buffer->active_outputs; scene_buffer->active_outputs = active_outputs; - wl_list_for_each(scene_output, &scene->outputs, link) { + wl_list_for_each(scene_output, outputs, link) { uint64_t mask = 1ull << scene_output->index; bool intersects = active_outputs & mask; bool intersects_before = old_active & mask; @@ -304,29 +332,118 @@ static void scene_buffer_update_outputs(struct wlr_scene_buffer *scene_buffer, } } -static void _scene_node_update_outputs(struct wlr_scene_node *node, - int lx, int ly, struct wlr_scene *scene, - struct wlr_scene_output *ignore) { - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - scene_buffer_update_outputs(scene_buffer, lx, ly, scene, ignore); - } else if (node->type == WLR_SCENE_NODE_TREE) { +static bool scene_node_update_iterator(struct wlr_scene_node *node, + int lx, int ly, void *_data) { + struct scene_update_data *data = _data; + + struct wlr_box box = { .x = lx, .y = ly }; + scene_node_get_size(node, &box.width, &box.height); + + pixman_region32_fini(&node->visible); + pixman_region32_init_rect(&node->visible, lx, ly, box.width, box.height); + + update_node_update_outputs(node, data->outputs, NULL); + + return false; +} + +static void scene_node_visibility(struct wlr_scene_node *node, + pixman_region32_t *visible) { + if (!node->enabled) { + return; + } + + if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { - _scene_node_update_outputs(child, lx + child->x, - ly + child->y, scene, ignore); + scene_node_visibility(child, visible); } + return; } + + pixman_region32_union(visible, visible, &node->visible); } -static void scene_node_update_outputs(struct wlr_scene_node *node, - struct wlr_scene_output *ignore) { +static void scene_node_bounds(struct wlr_scene_node *node, + int x, int y, pixman_region32_t *visible) { + if (!node->enabled) { + return; + } + + if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_bounds(child, x + child->x, y + child->y, visible); + } + return; + } + + int width, height; + scene_node_get_size(node, &width, &height); + pixman_region32_union_rect(visible, visible, x, y, width, height); +} + +static void scene_update_region(struct wlr_scene *scene, + pixman_region32_t *update_region) { + pixman_region32_t visible; + pixman_region32_init(&visible); + pixman_region32_copy(&visible, update_region); + + struct scene_update_data data = { + .visible = &visible, + .update_region = update_region, + .outputs = &scene->outputs, + }; + + struct pixman_box32 *region_box = pixman_region32_extents(update_region); + struct wlr_box box = { + .x = region_box->x1, + .y = region_box->y1, + .width = region_box->x2 - region_box->x1, + .height = region_box->y2 - region_box->y1, + }; + + // update node visibility and output enter/leave events + scene_nodes_in_box(&scene->tree.node, &box, scene_node_update_iterator, &data); + + pixman_region32_fini(&visible); +} + +static void scene_node_update(struct wlr_scene_node *node, + pixman_region32_t *damage) { struct wlr_scene *scene = scene_node_get_root(node); - int lx, ly; - wlr_scene_node_coords(node, &lx, &ly); - _scene_node_update_outputs(node, lx, ly, scene, ignore); + + int x, y; + if (!wlr_scene_node_coords(node, &x, &y)) { + if (damage) { + scene_update_region(scene, damage); + scene_damage_outputs(scene, damage); + pixman_region32_fini(damage); + } + + return; + } + + pixman_region32_t visible; + if (!damage) { + pixman_region32_init(&visible); + scene_node_visibility(node, &visible); + damage = &visible; + } + + pixman_region32_t update_region; + pixman_region32_init(&update_region); + pixman_region32_copy(&update_region, damage); + scene_node_bounds(node, x, y, &update_region); + + scene_update_region(scene, &update_region); + pixman_region32_fini(&update_region); + + scene_node_visibility(node, damage); + scene_damage_outputs(scene, damage); + pixman_region32_fini(damage); } struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, @@ -343,7 +460,7 @@ struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent, scene_rect->height = height; memcpy(scene_rect->color, color, sizeof(scene_rect->color)); - scene_node_damage_whole(&scene_rect->node); + scene_node_update(&scene_rect->node, NULL); return scene_rect; } @@ -353,10 +470,9 @@ void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height) return; } - scene_node_damage_whole(&rect->node); rect->width = width; rect->height = height; - scene_node_damage_whole(&rect->node); + scene_node_update(&rect->node, NULL); } void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[static 4]) { @@ -365,7 +481,7 @@ void wlr_scene_rect_set_color(struct wlr_scene_rect *rect, const float color[sta } memcpy(rect->color, color, sizeof(rect->color)); - scene_node_damage_whole(&rect->node); + scene_node_update(&rect->node, NULL); } struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, @@ -386,9 +502,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, wl_signal_init(&scene_buffer->events.output_present); wl_signal_init(&scene_buffer->events.frame_done); - scene_node_damage_whole(&scene_buffer->node); - - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update(&scene_buffer->node, NULL); return scene_buffer; } @@ -401,10 +515,6 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff assert(buffer || !damage); if (buffer != scene_buffer->buffer) { - if (!damage) { - scene_node_damage_whole(&scene_buffer->node); - } - wlr_texture_destroy(scene_buffer->texture); scene_buffer->texture = NULL; wlr_buffer_unlock(scene_buffer->buffer); @@ -415,10 +525,8 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff scene_buffer->buffer = NULL; } - scene_node_update_outputs(&scene_buffer->node, NULL); - if (!damage) { - scene_node_damage_whole(&scene_buffer->node); + scene_node_update(&scene_buffer->node, NULL); } } @@ -500,7 +608,7 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, memset(cur, 0, sizeof(*cur)); } - scene_node_damage_whole(&scene_buffer->node); + scene_node_update(&scene_buffer->node, NULL); } void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, @@ -509,12 +617,9 @@ void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer, return; } - scene_node_damage_whole(&scene_buffer->node); scene_buffer->dst_width = width; scene_buffer->dst_height = height; - scene_node_damage_whole(&scene_buffer->node); - - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update(&scene_buffer->node, NULL); } void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, @@ -523,11 +628,8 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, return; } - scene_node_damage_whole(&scene_buffer->node); scene_buffer->transform = transform; - scene_node_damage_whole(&scene_buffer->node); - - scene_node_update_outputs(&scene_buffer->node, NULL); + scene_node_update(&scene_buffer->node, NULL); } void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, @@ -594,67 +696,21 @@ static void scale_box(struct wlr_box *box, float scale) { box->y = round(box->y * scale); } -static void _scene_node_damage_whole(struct wlr_scene_node *node, - struct wlr_scene *scene, int lx, int ly) { - if (!node->enabled) { - return; - } - - if (node->type == WLR_SCENE_NODE_TREE) { - struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); - struct wlr_scene_node *child; - wl_list_for_each(child, &scene_tree->children, link) { - _scene_node_damage_whole(child, scene, - lx + child->x, ly + child->y); - } - } - - int width, height; - scene_node_get_size(node, &width, &height); - - pixman_region32_fini(&node->visible); - pixman_region32_init_rect(&node->visible, lx, ly, width, height); - - struct wlr_scene_output *scene_output; - wl_list_for_each(scene_output, &scene->outputs, link) { - struct wlr_box box = { - .x = lx - scene_output->x, - .y = ly - scene_output->y, - .width = width, - .height = height, - }; - - scale_box(&box, scene_output->output->scale); - - if (wlr_damage_ring_add_box(&scene_output->damage_ring, &box)) { - wlr_output_schedule_frame(scene_output->output); - } - } -} - -static void scene_node_damage_whole(struct wlr_scene_node *node) { - struct wlr_scene *scene = scene_node_get_root(node); - if (wl_list_empty(&scene->outputs)) { - return; - } - - int lx, ly; - if (!wlr_scene_node_coords(node, &lx, &ly)) { - return; - } - - _scene_node_damage_whole(node, scene, lx, ly); -} - void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) { if (node->enabled == enabled) { return; } - // One of these damage_whole() calls will short-circuit and be a no-op - scene_node_damage_whole(node); + int x, y; + pixman_region32_t visible; + pixman_region32_init(&visible); + if (wlr_scene_node_coords(node, &x, &y)) { + scene_node_visibility(node, &visible); + } + node->enabled = enabled; - scene_node_damage_whole(node); + + scene_node_update(node, &visible); } void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) { @@ -662,12 +718,9 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) { return; } - scene_node_damage_whole(node); node->x = x; node->y = y; - scene_node_damage_whole(node); - - scene_node_update_outputs(node, NULL); + scene_node_update(node, NULL); } void wlr_scene_node_place_above(struct wlr_scene_node *node, @@ -681,9 +734,7 @@ void wlr_scene_node_place_above(struct wlr_scene_node *node, wl_list_remove(&node->link); wl_list_insert(&sibling->link, &node->link); - - scene_node_damage_whole(node); - scene_node_damage_whole(sibling); + scene_node_update(node, NULL); } void wlr_scene_node_place_below(struct wlr_scene_node *node, @@ -697,9 +748,7 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node, wl_list_remove(&node->link); wl_list_insert(sibling->link.prev, &node->link); - - scene_node_damage_whole(node); - scene_node_damage_whole(sibling); + scene_node_update(node, NULL); } void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) { @@ -734,15 +783,17 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node, assert(&ancestor->node != node); } - scene_node_damage_whole(node); + int x, y; + pixman_region32_t visible; + pixman_region32_init(&visible); + if (wlr_scene_node_coords(node, &x, &y)) { + scene_node_visibility(node, &visible); + } wl_list_remove(&node->link); node->parent = new_parent; wl_list_insert(new_parent->children.prev, &node->link); - - scene_node_damage_whole(node); - - scene_node_update_outputs(node, NULL); + scene_node_update(node, &visible); } bool wlr_scene_node_coords(struct wlr_scene_node *node, @@ -1026,13 +1077,28 @@ static const struct wlr_addon_interface output_addon_impl = { .destroy = scene_output_handle_destroy, }; +static void scene_node_output_update(struct wlr_scene_node *node, + struct wl_list *outputs, struct wlr_scene_output *ignore) { + if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_node_output_update(child, outputs, ignore); + } + return; + } + + update_node_update_outputs(node, outputs, ignore); +} + static void scene_output_update_geometry(struct wlr_scene_output *scene_output) { int width, height; wlr_output_transformed_resolution(scene_output->output, &width, &height); wlr_damage_ring_set_bounds(&scene_output->damage_ring, width, height); wlr_output_schedule_frame(scene_output->output); - scene_node_update_outputs(&scene_output->scene->tree.node, NULL); + scene_node_output_update(&scene_output->scene->tree.node, + &scene_output->scene->outputs, NULL); } static void scene_output_handle_commit(struct wl_listener *listener, void *data) { @@ -1131,7 +1197,8 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wlr_signal_emit_safe(&scene_output->events.destroy, NULL); - scene_node_update_outputs(&scene_output->scene->tree.node, scene_output); + scene_node_output_update(&scene_output->scene->tree.node, + &scene_output->scene->outputs, scene_output); struct highlight_region *damage, *tmp_damage; wl_list_for_each_safe(damage, tmp_damage, &scene_output->damage_highlight_regions, link) { From 6d62300324593ae123e04343cb949029a1bd4990 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 18:22:00 -0400 Subject: [PATCH 253/298] wlr_scene_set_buffer_with_damage: Only damage the visible parts of the node --- types/scene/wlr_scene.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 498fa878a..94d0c02c0 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -577,6 +577,14 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff pixman_region32_init(&output_damage); wlr_region_scale_xy(&output_damage, &trans_damage, output_scale * scale_x, output_scale * scale_y); + + pixman_region32_t cull_region; + pixman_region32_init(&cull_region); + wlr_region_scale(&cull_region, &scene_buffer->node.visible, output_scale); + pixman_region32_translate(&cull_region, -lx * output_scale, -ly * output_scale); + pixman_region32_intersect(&output_damage, &output_damage, &cull_region); + pixman_region32_fini(&cull_region); + pixman_region32_translate(&output_damage, (lx - scene_output->x) * output_scale, (ly - scene_output->y) * output_scale); From d16d341381e806d41e27a4cbcd249ea18708c2ef Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 00:58:04 -0400 Subject: [PATCH 254/298] wlr_scene: Only send frame done events for visible buffers --- types/scene/wlr_scene.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 94d0c02c0..f5af07e07 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -642,7 +642,9 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, struct timespec *now) { - wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); + if (pixman_region32_not_empty(&scene_buffer->node.visible)) { + wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); + } } static struct wlr_texture *scene_buffer_get_texture( From 14f4cfffbaac19595580c1a2b8a29b96c36ef4ee Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 19:53:17 -0400 Subject: [PATCH 255/298] wlr_scene: Don't render non visible parts of textures/rects We can also get rid of the intersection checks in the rendering functions because we are guaranteed to already be in the node do to the prior intersection checking of the node visibility. --- types/scene/wlr_scene.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index f5af07e07..ec71491a6 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -932,28 +932,21 @@ static void scissor_output(struct wlr_output *output, pixman_box32_t *rect) { } static void render_rect(struct wlr_output *output, - pixman_region32_t *output_damage, const float color[static 4], + pixman_region32_t *damage, const float color[static 4], const struct wlr_box *box, const float matrix[static 9]) { struct wlr_renderer *renderer = output->renderer; assert(renderer); - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_init_rect(&damage, box->x, box->y, box->width, box->height); - pixman_region32_intersect(&damage, &damage, output_damage); - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(output, &rects[i]); wlr_render_rect(renderer, box, color, matrix); } - - pixman_region32_fini(&damage); } static void render_texture(struct wlr_output *output, - pixman_region32_t *output_damage, struct wlr_texture *texture, + pixman_region32_t *damage, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9]) { struct wlr_renderer *renderer = output->renderer; @@ -966,20 +959,12 @@ static void render_texture(struct wlr_output *output, src_box = &default_src_box; } - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_init_rect(&damage, dst_box->x, dst_box->y, - dst_box->width, dst_box->height); - pixman_region32_intersect(&damage, &damage, output_damage); - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(output, &rects[i]); wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, 1.0); } - - pixman_region32_fini(&damage); } struct render_data { @@ -992,7 +977,17 @@ static void render_node_iterator(struct wlr_scene_node *node, struct render_data *data = _data; struct wlr_scene_output *scene_output = data->scene_output; struct wlr_output *output = scene_output->output; - pixman_region32_t *output_damage = data->damage; + + pixman_region32_t render_region; + pixman_region32_init(&render_region); + pixman_region32_copy(&render_region, &node->visible); + pixman_region32_translate(&render_region, -scene_output->x, -scene_output->y); + wlr_region_scale(&render_region, &render_region, output->scale); + pixman_region32_intersect(&render_region, &render_region, data->damage); + if (!pixman_region32_not_empty(&render_region)) { + pixman_region32_fini(&render_region); + return; + } struct wlr_box dst_box = { .x = x, @@ -1011,7 +1006,7 @@ static void render_node_iterator(struct wlr_scene_node *node, case WLR_SCENE_NODE_RECT:; struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); - render_rect(output, output_damage, scene_rect->color, &dst_box, + render_rect(output, &render_region, scene_rect->color, &dst_box, output->transform_matrix); break; case WLR_SCENE_NODE_BUFFER:; @@ -1030,12 +1025,14 @@ static void render_node_iterator(struct wlr_scene_node *node, wlr_matrix_project_box(matrix, &dst_box, transform, 0.0, output->transform_matrix); - render_texture(output, output_damage, texture, &scene_buffer->src_box, + render_texture(output, &render_region, texture, &scene_buffer->src_box, &dst_box, matrix); wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); break; } + + pixman_region32_fini(&render_region); } static void scene_node_for_each_node(struct wlr_scene_node *node, From 0a9a941ba329d10c08a6f638a0b22b60b7c92d0f Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 14 Aug 2022 02:17:09 -0400 Subject: [PATCH 256/298] wlr_scene: Rewrite direct scan out logic to rely on visibility Also make the regular rendering logic use the introduced render list. --- include/wlr/types/wlr_scene.h | 7 + types/scene/wlr_scene.c | 251 ++++++++++++++++++++++------------ 2 files changed, 167 insertions(+), 91 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index da0a794ab..efdd6061b 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -158,6 +158,11 @@ struct wlr_scene_buffer { enum wl_output_transform transform; }; +struct wlr_scene_output_render_list { + struct wlr_scene_node **data; + size_t capacity; +}; + /** A viewport for an output in the scene-graph */ struct wlr_scene_output { struct wlr_output *output; @@ -184,6 +189,8 @@ struct wlr_scene_output { struct wl_listener output_needs_frame; struct wl_list damage_highlight_regions; + + struct wlr_scene_output_render_list render_list; }; /** A layer shell scene helper */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index ec71491a6..e56054726 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -16,6 +16,7 @@ #include "util/time.h" #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 +#define RENDER_LIST_MIN_ALLOCATION 8 static struct wlr_scene_tree *scene_tree_from_node(struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_TREE); @@ -967,15 +968,13 @@ static void render_texture(struct wlr_output *output, } } -struct render_data { - struct wlr_scene_output *scene_output; - pixman_region32_t *damage; -}; +static void scene_node_render(struct wlr_scene_node *node, + struct wlr_scene_output *scene_output, pixman_region32_t *damage) { + int x, y; + wlr_scene_node_coords(node, &x, &y); + x -= scene_output->x; + y -= scene_output->y; -static void render_node_iterator(struct wlr_scene_node *node, - int x, int y, void *_data) { - struct render_data *data = _data; - struct wlr_scene_output *scene_output = data->scene_output; struct wlr_output *output = scene_output->output; pixman_region32_t render_region; @@ -983,7 +982,7 @@ static void render_node_iterator(struct wlr_scene_node *node, pixman_region32_copy(&render_region, &node->visible); pixman_region32_translate(&render_region, -scene_output->x, -scene_output->y); wlr_region_scale(&render_region, &render_region, output->scale); - pixman_region32_intersect(&render_region, &render_region, data->damage); + pixman_region32_intersect(&render_region, &render_region, damage); if (!pixman_region32_not_empty(&render_region)) { pixman_region32_fini(&render_region); return; @@ -1035,27 +1034,6 @@ static void render_node_iterator(struct wlr_scene_node *node, pixman_region32_fini(&render_region); } -static void scene_node_for_each_node(struct wlr_scene_node *node, - int lx, int ly, wlr_scene_node_iterator_func_t user_iterator, - void *user_data) { - if (!node->enabled) { - return; - } - - lx += node->x; - ly += node->y; - - user_iterator(node, lx, ly, user_data); - - if (node->type == WLR_SCENE_NODE_TREE) { - struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); - struct wlr_scene_node *child; - wl_list_for_each(child, &scene_tree->children, link) { - scene_node_for_each_node(child, lx, ly, user_iterator, user_data); - } - } -} - static void scene_handle_presentation_destroy(struct wl_listener *listener, void *data) { struct wlr_scene *scene = @@ -1220,6 +1198,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wl_list_remove(&scene_output->output_damage.link); wl_list_remove(&scene_output->output_needs_frame.link); + free(scene_output->render_list.data); free(scene_output); } @@ -1247,37 +1226,90 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, scene_output_update_geometry(scene_output); } -struct check_scanout_data { - // in - struct wlr_box viewport_box; - // out - struct wlr_scene_node *node; - size_t n; -}; +static bool scene_node_invisible(struct wlr_scene_node *node) { + if (node->type == WLR_SCENE_NODE_TREE) { + return true; + } else if (node->type == WLR_SCENE_NODE_RECT) { + float *clear = (float[4]){ 0.f, 0.f, 0.f, 0.f }; + struct wlr_scene_rect *rect = scene_rect_from_node(node); -static void check_scanout_iterator(struct wlr_scene_node *node, - int x, int y, void *_data) { - struct check_scanout_data *data = _data; + return memcmp(rect->color, clear, sizeof(float) * 4) == 0; + } else if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); - struct wlr_box node_box = { .x = x, .y = y }; - scene_node_get_size(node, &node_box.width, &node_box.height); - - struct wlr_box intersection; - if (!wlr_box_intersection(&intersection, &data->viewport_box, &node_box)) { - return; + return buffer->buffer == NULL; } - data->n++; + return false; +} - if (data->viewport_box.x == node_box.x && - data->viewport_box.y == node_box.y && - data->viewport_box.width == node_box.width && - data->viewport_box.height == node_box.height) { - data->node = node; +static size_t max(size_t fst, size_t snd) { + if (fst > snd) { + return fst; + } else { + return snd; } } -static bool scene_output_scanout(struct wlr_scene_output *scene_output) { +struct render_list_constructor_data { + struct wlr_box box; + struct wlr_scene_output_render_list *render_list; + size_t size; +}; + +static bool construct_render_list_iterator(struct wlr_scene_node *node, + int lx, int ly, void *_data) { + struct render_list_constructor_data *data = _data; + + if (scene_node_invisible(node)) { + return false; + } + + // while rendering, the background should always be black. + // If we see a black rect, we can ignore rendering everything under the rect + // and even the rect itself. + if (node->type == WLR_SCENE_NODE_RECT) { + struct wlr_scene_rect *rect = scene_rect_from_node(node); + float *black = (float[4]){ 1.f, 1.f, 1.f, 1.f }; + + if (memcmp(rect->color, black, sizeof(float) * 4) == 0) { + return false; + } + } + + pixman_region32_t intersection; + pixman_region32_init(&intersection); + pixman_region32_intersect_rect(&intersection, &node->visible, + data->box.x, data->box.y, + data->box.width, data->box.height); + if (!pixman_region32_not_empty(&intersection)) { + pixman_region32_fini(&intersection); + return false; + } + + pixman_region32_fini(&intersection); + + if (data->size == data->render_list->capacity) { + size_t alloc_size = + max(data->render_list->capacity * 2, RENDER_LIST_MIN_ALLOCATION); + void *alloc = realloc(data->render_list->data, alloc_size + * sizeof(struct wlr_scene_node *)); + + if (alloc) { + data->render_list->data = alloc; + data->render_list->capacity = alloc_size; + } + } + + if (data->size < data->render_list->capacity) { + data->render_list->data[data->size++] = node; + } + + return false; +} + +static bool scene_node_try_direct_scanout(struct wlr_scene_node *node, + struct wlr_scene_output *scene_output, struct wlr_box *box) { if (!scene_output->scene->direct_scanout) { return false; } @@ -1289,50 +1321,64 @@ static bool scene_output_scanout(struct wlr_scene_output *scene_output) { return false; } + if (node->type != WLR_SCENE_NODE_BUFFER) { + return false; + } + + struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); struct wlr_output *output = scene_output->output; - struct wlr_box viewport_box = { .x = scene_output->x, .y = scene_output->y }; - wlr_output_effective_resolution(output, - &viewport_box.width, &viewport_box.height); + struct wlr_fbox default_box = {0}; + if (buffer->transform & WL_OUTPUT_TRANSFORM_90) { + default_box.width = buffer->buffer->height; + default_box.height = buffer->buffer->width; + } else { + default_box.width = buffer->buffer->width; + default_box.height = buffer->buffer->height; + } - struct check_scanout_data check_scanout_data = { - .viewport_box = viewport_box, - }; - scene_node_for_each_node(&scene_output->scene->tree.node, 0, 0, - check_scanout_iterator, &check_scanout_data); - if (check_scanout_data.n != 1 || check_scanout_data.node == NULL) { + if (!wlr_fbox_empty(&buffer->src_box) && + memcmp(&buffer->src_box, &default_box, sizeof(default_box)) != 0) { return false; } - struct wlr_scene_node *node = check_scanout_data.node; - struct wlr_buffer *buffer; - switch (node->type) { - case WLR_SCENE_NODE_BUFFER:; - struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (scene_buffer->buffer == NULL || - !wlr_fbox_empty(&scene_buffer->src_box) || - scene_buffer->transform != output->transform) { - return false; - } - buffer = scene_buffer->buffer; - break; - default: + if (buffer->transform != output->transform) { return false; } - wlr_output_attach_buffer(output, buffer); + struct wlr_box node_box; + wlr_scene_node_coords(node, &node_box.x, &node_box.y); + scene_node_get_size(node, &node_box.width, &node_box.height); + + if (node_box.x != box->x || + node_box.y != box->y || + node_box.width != box->width || + node_box.height != box->height) { + return false; + } + + wlr_output_attach_buffer(output, buffer->buffer); if (!wlr_output_test(output)) { wlr_output_rollback(output); return false; } - if (node->type == WLR_SCENE_NODE_BUFFER) { - struct wlr_scene_buffer *scene_buffer = - wlr_scene_buffer_from_node(node); - wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); + return wlr_output_commit(output); +} + +static void compact_render_list(struct wlr_scene_output_render_list *list, size_t size) { + assert(size <= list->capacity); + + size_t alloc_size = max(RENDER_LIST_MIN_ALLOCATION, size); + if (alloc_size == list->capacity) { + return; } - return wlr_output_commit(output); + void *alloc = realloc(list->data, alloc_size * sizeof(struct wlr_scene_node *)); + if (alloc) { + list->data = alloc; + list->capacity = alloc_size; + } } bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { @@ -1343,15 +1389,40 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct wlr_renderer *renderer = output->renderer; assert(renderer != NULL); - bool scanout = scene_output_scanout(scene_output); - if (scanout != scene_output->prev_scanout) { + struct render_list_constructor_data list_con = { + .box = { .x = scene_output->x, .y = scene_output->y }, + .render_list = &scene_output->render_list, + .size = 0, + }; + wlr_output_effective_resolution(output, + &list_con.box.width, &list_con.box.height); + + scene_nodes_in_box(&scene_output->scene->tree.node, &list_con.box, + construct_render_list_iterator, &list_con); + compact_render_list(list_con.render_list, list_con.size); + + // if there is only one thing to render let's see if that thing can be + // directly scanned out + bool scanout = false; + if (list_con.size == 1) { + struct wlr_scene_node *node = list_con.render_list->data[0]; + scanout = scene_node_try_direct_scanout(node, scene_output, &list_con.box); + } + + if (scene_output->prev_scanout != scanout) { + scene_output->prev_scanout = scanout; wlr_log(WLR_DEBUG, "Direct scan-out %s", scanout ? "enabled" : "disabled"); // When exiting direct scan-out, damage everything wlr_damage_ring_add_whole(&scene_output->damage_ring); } - scene_output->prev_scanout = scanout; + if (scanout) { + struct wlr_scene_node *node = list_con.render_list->data[0]; + + assert(node->type == WLR_SCENE_NODE_BUFFER); + struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); + wlr_signal_emit_safe(&buffer->events.output_present, scene_output); return true; } @@ -1423,13 +1494,11 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_renderer_clear(renderer, (float[4]){ 0.0, 0.0, 0.0, 1.0 }); } - struct render_data data = { - .scene_output = scene_output, - .damage = &damage, - }; - scene_node_for_each_node(&scene_output->scene->tree.node, - -scene_output->x, -scene_output->y, - render_node_iterator, &data); + for (int i = list_con.size - 1; i >= 0; i--) { + struct wlr_scene_node *node = list_con.render_list->data[i]; + scene_node_render(node, scene_output, &damage); + } + wlr_renderer_scissor(renderer, NULL); if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { From 18417026be9b9ac0f269c99fa3bfd49d7cb91330 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 23:26:12 -0400 Subject: [PATCH 257/298] wlr_scene: Introduce buffer opaque region metadata --- include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index efdd6061b..d6b89156c 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -156,6 +156,7 @@ struct wlr_scene_buffer { struct wlr_fbox src_box; int dst_width, dst_height; enum wl_output_transform transform; + pixman_region32_t opaque_region; }; struct wlr_scene_output_render_list { @@ -346,6 +347,13 @@ void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buffer, struct wlr_buffer *buffer, pixman_region32_t *region); +/** + * Sets the buffer's opaque region. This is an optimization hint used to + * determine if buffers which reside under this one need to be rendered or not. + */ +void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer, + pixman_region32_t *region); + /** * Set the source rectangle describing the region of the buffer which will be * sampled to render this node. This allows cropping the buffer. diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index e56054726..36a12a0b1 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -103,6 +103,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { wlr_texture_destroy(scene_buffer->texture); wlr_buffer_unlock(scene_buffer->buffer); + pixman_region32_fini(&scene_buffer->opaque_region); } else if (node->type == WLR_SCENE_NODE_TREE) { struct wlr_scene_tree *scene_tree = scene_tree_from_node(node); @@ -502,6 +503,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, wl_signal_init(&scene_buffer->events.output_leave); wl_signal_init(&scene_buffer->events.output_present); wl_signal_init(&scene_buffer->events.frame_done); + pixman_region32_init(&scene_buffer->opaque_region); scene_node_update(&scene_buffer->node, NULL); @@ -603,6 +605,16 @@ void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer, wlr_scene_buffer_set_buffer_with_damage(scene_buffer, buffer, NULL); } +void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer, + pixman_region32_t *region) { + if (pixman_region32_equal(&scene_buffer->opaque_region, region)) { + return; + } + + pixman_region32_copy(&scene_buffer->opaque_region, region); + scene_node_update(&scene_buffer->node, NULL); +} + void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, const struct wlr_fbox *box) { struct wlr_fbox *cur = &scene_buffer->src_box; From 342830e99c3e88c6189a8533051485d9b682a814 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 19 May 2022 22:32:41 -0400 Subject: [PATCH 258/298] wlr_scene/surface: Hook through opaque metadata --- types/scene/surface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/types/scene/surface.c b/types/scene/surface.c index d3a0b035f..b122d210d 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -59,6 +59,8 @@ static void set_buffer_with_surface_state(struct wlr_scene_buffer *scene_buffer, struct wlr_surface *surface) { struct wlr_surface_state *state = &surface->current; + wlr_scene_buffer_set_opaque_region(scene_buffer, &surface->opaque_region); + struct wlr_fbox src_box; wlr_surface_get_buffer_source_box(surface, &src_box); wlr_scene_buffer_set_source_box(scene_buffer, &src_box); From ce57485e6a37e8b7d1b1cccc02d8d66ad60fe2d9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 18:33:40 -0400 Subject: [PATCH 259/298] wlr_scene: Calculate output intersections based on node visibility This has a few benefits one of them crucial for proper operation: - The primary output will be based on the largest area that is actually visible to the user. Presentation and frame done events are based on this state. This is important to do since we cull frame done events. If we happen to be in a situation where a surface sits mostly on output A and some on output B but is completely obstructed by for instance a fullscreen surface on output A we will erroneously send frame_done events based on output A. If we base things as they are in reality (visibility) the primary output will instead be output B and things will work properly. - The primary output will be NULL if the surface is completely hidden. Due to quirks with wayland, on a surface commit, frame done events are required to be sent. Therefore, a new frame will be submitted for rendering on the primary output. We can improve adaptive sync on completely hidden but enabled surfaces if we null out the primary output in this state. - The client will be more likely to choose better metadata to use for rendering to an output's optimal rendering characteristics. --- types/scene/wlr_scene.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 36a12a0b1..627d7e723 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -247,6 +247,18 @@ struct scene_update_data { struct wl_list *outputs; }; +static uint32_t region_area(pixman_region32_t *region) { + uint32_t area = 0; + + int nrects; + pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects); + for (int i = 0; i < nrects; ++i) { + area += (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1); + } + + return area; +} + static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) { if (!pixman_region32_not_empty(damage)) { return; @@ -276,10 +288,6 @@ static void update_node_update_outputs(struct wlr_scene_node *node, struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - struct wlr_box buffer_box; - wlr_scene_node_coords(node, &buffer_box.x, &buffer_box.y); - scene_node_get_size(node, &buffer_box.width, &buffer_box.height); - int largest_overlap = 0; scene_buffer->primary_output = NULL; @@ -304,11 +312,13 @@ static void update_node_update_outputs(struct wlr_scene_node *node, wlr_output_effective_resolution(scene_output->output, &output_box.width, &output_box.height); - struct wlr_box intersection; - bool intersects = wlr_box_intersection(&intersection, &buffer_box, &output_box); + pixman_region32_t intersection; + pixman_region32_init(&intersection); + pixman_region32_intersect_rect(&intersection, &node->visible, + output_box.x, output_box.y, output_box.width, output_box.height); - if (intersects) { - int overlap = intersection.width * intersection.height; + if (pixman_region32_not_empty(&intersection)) { + int overlap = region_area(&intersection); if (overlap > largest_overlap) { largest_overlap = overlap; scene_buffer->primary_output = scene_output; @@ -316,6 +326,8 @@ static void update_node_update_outputs(struct wlr_scene_node *node, active_outputs |= 1ull << scene_output->index; } + + pixman_region32_fini(&intersection); } uint64_t old_active = scene_buffer->active_outputs; From 919e67da7d3a32a294afe26dbf7a16c6d4c3af4c Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 25 Jun 2022 18:34:26 -0400 Subject: [PATCH 260/298] wlr_scene: Account for occlusion by other scene nodes when calculating visibility --- docs/env_vars.md | 3 ++ include/wlr/types/wlr_scene.h | 1 + types/scene/wlr_scene.c | 59 +++++++++++++++++++++++++++++++++-- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/docs/env_vars.md b/docs/env_vars.md index e5d5d62b8..624727835 100644 --- a/docs/env_vars.md +++ b/docs/env_vars.md @@ -51,6 +51,9 @@ wlroots reads these environment variables tasks for compositors that use scenes (available options: none, rerender, highlight) * *WLR_SCENE_DISABLE_DIRECT_SCANOUT*: disables direct scan-out for debugging. +* *WLR_SCENE_DISABLE_VISIBILITY*: If set to 1, the visibility of all scene nodes + will be considered to be the full node. Intelligent visibility canculations will + be disabled. # Generic diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index d6b89156c..93695b6fc 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -98,6 +98,7 @@ struct wlr_scene { enum wlr_scene_debug_damage_option debug_damage_option; bool direct_scanout; + bool calculate_visibility; }; /** A scene-graph node displaying a single surface. */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 627d7e723..9e68e6cda 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -11,6 +11,7 @@ #include #include #include +#include "types/wlr_buffer.h" #include "types/wlr_scene.h" #include "util/signal.h" #include "util/time.h" @@ -180,6 +181,20 @@ struct wlr_scene *wlr_scene_create(void) { scene->direct_scanout = true; } + char *visibility_disabled = getenv("WLR_SCENE_DISABLE_VISIBILITY"); + if (visibility_disabled) { + wlr_log(WLR_INFO, "Loading WLR_SCENE_DISABLE_VISIBILITY option: %s", visibility_disabled); + } + + if (!visibility_disabled || strcmp(visibility_disabled, "0") == 0) { + scene->calculate_visibility = true; + } else if (strcmp(visibility_disabled, "1") == 0) { + scene->calculate_visibility = false; + } else { + wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DISABLE_VISIBILITY option: %s", visibility_disabled); + scene->calculate_visibility = true; + } + return scene; } @@ -241,10 +256,41 @@ static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, return _scene_nodes_in_box(node, box, iterator, user_data, x, y); } +static void scene_node_cull_hidden(struct wlr_scene_node *node, int x, int y, + pixman_region32_t *visible) { + if (node->type == WLR_SCENE_NODE_RECT) { + struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); + if (scene_rect->color[3] != 1) { + return; + } + } else if (node->type == WLR_SCENE_NODE_BUFFER) { + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + + if (!scene_buffer->buffer) { + return; + } + + if (!buffer_is_opaque(scene_buffer->buffer)) { + pixman_region32_translate(visible, -x, -y); + pixman_region32_subtract(visible, visible, &scene_buffer->opaque_region); + pixman_region32_translate(visible, x, y); + return; + } + } + + int width, height; + scene_node_get_size(node, &width, &height); + pixman_region32_t opaque; + pixman_region32_init_rect(&opaque, x, y, width, height); + pixman_region32_subtract(visible, visible, &opaque); + pixman_region32_fini(&opaque); +} + struct scene_update_data { pixman_region32_t *visible; pixman_region32_t *update_region; struct wl_list *outputs; + bool calculate_visibility; }; static uint32_t region_area(pixman_region32_t *region) { @@ -353,8 +399,16 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node, struct wlr_box box = { .x = lx, .y = ly }; scene_node_get_size(node, &box.width, &box.height); - pixman_region32_fini(&node->visible); - pixman_region32_init_rect(&node->visible, lx, ly, box.width, box.height); + if (data->calculate_visibility) { + pixman_region32_subtract(&node->visible, &node->visible, data->update_region); + pixman_region32_union(&node->visible, &node->visible, data->visible); + pixman_region32_intersect_rect(&node->visible, &node->visible, + lx, ly, box.width, box.height); + scene_node_cull_hidden(node, lx, ly, data->visible); + } else { + pixman_region32_fini(&node->visible); + pixman_region32_init_rect(&node->visible, lx, ly, box.width, box.height); + } update_node_update_outputs(node, data->outputs, NULL); @@ -409,6 +463,7 @@ static void scene_update_region(struct wlr_scene *scene, .visible = &visible, .update_region = update_region, .outputs = &scene->outputs, + .calculate_visibility = scene->calculate_visibility, }; struct pixman_box32 *region_box = pixman_region32_extents(update_region); From 59675347e6c1ac86ec750ea69cddaf0c873f6437 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 21 May 2022 11:37:21 -0400 Subject: [PATCH 261/298] wlr_scene: Remove unused typedef --- include/wlr/types/wlr_scene.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 93695b6fc..d92df7db1 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -32,9 +32,6 @@ struct wlr_layer_surface_v1; struct wlr_scene_node; struct wlr_scene_buffer; -typedef void (*wlr_scene_node_iterator_func_t)(struct wlr_scene_node *node, - int sx, int sy, void *data); - typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)( struct wlr_scene_buffer *buffer, int sx, int sy); From 9f3bd64a332c1bacee57d394bdaf0b4d06153ab0 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 15 Aug 2022 06:14:28 -0400 Subject: [PATCH 262/298] util/box: Introduce wlr_box_equal --- include/wlr/util/box.h | 9 +++++++++ util/box.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/include/wlr/util/box.h b/include/wlr/util/box.h index 8516688d1..e01b351ed 100644 --- a/include/wlr/util/box.h +++ b/include/wlr/util/box.h @@ -92,4 +92,13 @@ bool wlr_fbox_empty(const struct wlr_fbox *box); void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box, enum wl_output_transform transform, double width, double height); +#ifdef WLR_USE_UNSTABLE + +/** + * Returns true if the two boxes are equal, false otherwise. + */ +bool wlr_box_equal(const struct wlr_box *a, const struct wlr_box *b); + +#endif + #endif diff --git a/util/box.c b/util/box.c index a9edc144b..cddff76e0 100644 --- a/util/box.c +++ b/util/box.c @@ -171,3 +171,12 @@ void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box, break; } } + +#ifdef WLR_USE_UNSTABLE + +bool wlr_box_equal(const struct wlr_box *a, const struct wlr_box *b) { + return a->x == b->x && a->y == b->y && + a->width == b->width && a->height == b->height; +} + +#endif From 1d08ef234e6fcb6cdd2ca128f0259497aaaaddf8 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 15 Aug 2022 06:04:42 -0400 Subject: [PATCH 263/298] util/box: Introduce wlr_fbox_equal --- include/wlr/util/box.h | 5 +++++ util/box.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/include/wlr/util/box.h b/include/wlr/util/box.h index e01b351ed..84df50a6f 100644 --- a/include/wlr/util/box.h +++ b/include/wlr/util/box.h @@ -99,6 +99,11 @@ void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box, */ bool wlr_box_equal(const struct wlr_box *a, const struct wlr_box *b); +/** + * Returns true if the two boxes are equal, false otherwise. + */ +bool wlr_fbox_equal(const struct wlr_fbox *a, const struct wlr_fbox *b); + #endif #endif diff --git a/util/box.c b/util/box.c index cddff76e0..d7d226179 100644 --- a/util/box.c +++ b/util/box.c @@ -179,4 +179,9 @@ bool wlr_box_equal(const struct wlr_box *a, const struct wlr_box *b) { a->width == b->width && a->height == b->height; } +bool wlr_fbox_equal(const struct wlr_fbox *a, const struct wlr_fbox *b) { + return a->x == b->x && a->y == b->y && + a->width == b->width && a->height == b->height; +} + #endif From bcf7a793575ead7a8e68401d5b5808d5337ebfe1 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 15 Aug 2022 06:03:54 -0400 Subject: [PATCH 264/298] wlr_scene: Use wlr_fbox_equals --- types/scene/wlr_scene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 9e68e6cda..b2e7d71ad 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -686,7 +686,7 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer, const struct wlr_fbox *box) { struct wlr_fbox *cur = &scene_buffer->src_box; if ((wlr_fbox_empty(box) && wlr_fbox_empty(cur)) || - (box != NULL && memcmp(cur, box, sizeof(*box)) == 0)) { + (box != NULL && wlr_fbox_equal(cur, box))) { return; } @@ -1417,7 +1417,7 @@ static bool scene_node_try_direct_scanout(struct wlr_scene_node *node, } if (!wlr_fbox_empty(&buffer->src_box) && - memcmp(&buffer->src_box, &default_box, sizeof(default_box)) != 0) { + !wlr_fbox_equal(&buffer->src_box, &default_box)) { return false; } From bea4bd43e3a46af717f211f0a8e581a72cea7cb9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 15 Aug 2022 07:37:09 -0400 Subject: [PATCH 265/298] wlr_scene: Use wlr_box_equal --- types/scene/wlr_scene.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index b2e7d71ad..b522f3779 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1429,10 +1429,7 @@ static bool scene_node_try_direct_scanout(struct wlr_scene_node *node, wlr_scene_node_coords(node, &node_box.x, &node_box.y); scene_node_get_size(node, &node_box.width, &node_box.height); - if (node_box.x != box->x || - node_box.y != box->y || - node_box.width != box->width || - node_box.height != box->height) { + if (!wlr_box_equal(box, &node_box)) { return false; } From 3621c14b8253b2417938e598205a1d03a8d154d3 Mon Sep 17 00:00:00 2001 From: yiqiang Date: Tue, 16 Aug 2022 10:46:21 +0800 Subject: [PATCH 266/298] wlr_scene: fix color value when filtering black boxes Signed-off-by: yiqiang --- types/scene/wlr_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index b522f3779..d2da8bd45 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1349,7 +1349,7 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node, // and even the rect itself. if (node->type == WLR_SCENE_NODE_RECT) { struct wlr_scene_rect *rect = scene_rect_from_node(node); - float *black = (float[4]){ 1.f, 1.f, 1.f, 1.f }; + float *black = (float[4]){ 0.f, 0.f, 0.f, 1.f }; if (memcmp(rect->color, black, sizeof(float) * 4) == 0) { return false; From 013f121f455efcc1e68e98c60c74aadfb51fd98e Mon Sep 17 00:00:00 2001 From: Simon Zeni Date: Thu, 28 Jul 2022 06:39:48 -0400 Subject: [PATCH 267/298] build: remove libkms option and disable tests for libdrm fallback --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index d04d3c167..58a64a0b3 100644 --- a/meson.build +++ b/meson.build @@ -110,7 +110,6 @@ drm = dependency('libdrm', version: '>=2.4.112', fallback: 'libdrm', default_options: [ - 'libkms=false', 'intel=false', 'radeon=false', 'amdgpu=false', @@ -125,6 +124,7 @@ drm = dependency('libdrm', 'cairo-tests=false', 'man-pages=false', 'valgrind=false', + 'tests=false', ], ) xkbcommon = dependency('xkbcommon') From ef4baea0e2f799c7bdd2e077dac4174fa31e85df Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 18 Aug 2022 07:16:16 -0400 Subject: [PATCH 268/298] Use wl_signal_emit_mutable --- backend/backend.c | 3 +- backend/drm/backend.c | 1 - backend/drm/drm.c | 5 +- backend/headless/backend.c | 3 +- backend/headless/output.c | 3 +- backend/libinput/backend.c | 1 - backend/libinput/events.c | 13 +++-- backend/libinput/pointer.c | 37 +++++++-------- backend/libinput/switch.c | 3 +- backend/libinput/tablet_pad.c | 7 ++- backend/libinput/tablet_tool.c | 11 ++--- backend/libinput/touch.c | 11 ++--- backend/multi/backend.c | 9 ++-- backend/session/session.c | 13 +++-- backend/wayland/backend.c | 1 - backend/wayland/output.c | 3 +- backend/wayland/pointer.c | 31 ++++++------ backend/wayland/seat.c | 13 +++-- backend/wayland/tablet_v2.c | 29 ++++++------ backend/x11/backend.c | 3 +- backend/x11/input_device.c | 25 +++++----- backend/x11/output.c | 7 ++- render/allocator/allocator.c | 3 +- render/gles2/texture.c | 1 - render/wlr_renderer.c | 3 +- types/data_device/wlr_data_device.c | 9 ++-- types/data_device/wlr_data_offer.c | 1 - types/data_device/wlr_data_source.c | 3 +- types/data_device/wlr_drag.c | 19 ++++---- types/output/cursor.c | 3 +- types/output/output.c | 23 +++++---- types/scene/wlr_scene.c | 17 ++++--- types/seat/wlr_seat.c | 5 +- types/seat/wlr_seat_keyboard.c | 7 ++- types/seat/wlr_seat_pointer.c | 9 ++-- types/seat/wlr_seat_touch.c | 7 ++- types/tablet_v2/wlr_tablet_v2.c | 3 +- types/tablet_v2/wlr_tablet_v2_pad.c | 7 ++- types/tablet_v2/wlr_tablet_v2_tool.c | 3 +- types/wlr_buffer.c | 5 +- types/wlr_compositor.c | 13 +++-- types/wlr_cursor.c | 45 +++++++++--------- types/wlr_damage_ring.c | 1 - types/wlr_data_control_v1.c | 5 +- types/wlr_drm.c | 3 +- types/wlr_drm_lease_v1.c | 3 +- types/wlr_export_dmabuf_v1.c | 3 +- types/wlr_foreign_toplevel_management_v1.c | 17 ++++--- types/wlr_fullscreen_shell_v1.c | 5 +- types/wlr_gamma_control_v1.c | 3 +- types/wlr_idle.c | 11 ++--- types/wlr_idle_inhibit_v1.c | 7 ++- types/wlr_input_device.c | 3 +- types/wlr_input_inhibitor.c | 7 ++- types/wlr_input_method_v2.c | 21 ++++----- types/wlr_keyboard.c | 11 ++--- types/wlr_keyboard_group.c | 5 +- types/wlr_keyboard_shortcuts_inhibit_v1.c | 7 ++- types/wlr_layer_shell_v1.c | 13 +++-- types/wlr_linux_dmabuf_v1.c | 3 +- types/wlr_output_damage.c | 5 +- types/wlr_output_layout.c | 11 ++--- types/wlr_output_management_v1.c | 7 ++- types/wlr_output_power_management_v1.c | 5 +- types/wlr_pointer_constraints_v1.c | 7 ++- types/wlr_pointer_gestures_v1.c | 1 - types/wlr_presentation_time.c | 3 +- types/wlr_primary_selection.c | 9 ++-- types/wlr_primary_selection_v1.c | 3 +- types/wlr_relative_pointer_v1.c | 7 ++- types/wlr_screencopy_v1.c | 3 +- types/wlr_server_decoration.c | 9 ++-- types/wlr_session_lock_v1.c | 15 +++--- types/wlr_subcompositor.c | 9 ++-- types/wlr_text_input_v3.c | 13 +++-- types/wlr_viewporter.c | 3 +- types/wlr_virtual_keyboard_v1.c | 5 +- types/wlr_virtual_pointer_v1.c | 15 +++--- types/wlr_xdg_activation_v1.c | 7 ++- types/wlr_xdg_decoration_v1.c | 13 +++-- types/wlr_xdg_foreign_registry.c | 5 +- types/wlr_xdg_foreign_v1.c | 3 +- types/wlr_xdg_foreign_v2.c | 3 +- types/wlr_xdg_output_v1.c | 3 +- types/xdg_shell/wlr_xdg_popup.c | 5 +- types/xdg_shell/wlr_xdg_shell.c | 5 +- types/xdg_shell/wlr_xdg_surface.c | 15 +++--- types/xdg_shell/wlr_xdg_toplevel.c | 23 +++++---- xwayland/server.c | 5 +- xwayland/xwayland.c | 3 +- xwayland/xwm.c | 55 +++++++++++----------- 91 files changed, 365 insertions(+), 456 deletions(-) diff --git a/backend/backend.c b/backend/backend.c index ac6e21653..32ddca97b 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -17,7 +17,6 @@ #include "backend/backend.h" #include "backend/multi.h" #include "render/allocator/allocator.h" -#include "util/signal.h" #if WLR_HAS_DRM_BACKEND #include @@ -44,7 +43,7 @@ void wlr_backend_init(struct wlr_backend *backend, } void wlr_backend_finish(struct wlr_backend *backend) { - wlr_signal_emit_safe(&backend->events.destroy, backend); + wl_signal_emit_mutable(&backend->events.destroy, backend); } bool wlr_backend_start(struct wlr_backend *backend) { diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 267bbfb29..e303bc8f0 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -13,7 +13,6 @@ #include #include #include "backend/drm/drm.h" -#include "util/signal.h" struct wlr_drm_backend *get_drm_backend_from_backend( struct wlr_backend *wlr_backend) { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 432f0427b..9acb41757 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -29,7 +29,6 @@ #include "render/drm_format_set.h" #include "render/swapchain.h" #include "render/wlr_renderer.h" -#include "util/signal.h" // Output state which needs a KMS commit to be applied static const uint32_t COMMIT_OUTPUT_STATE = @@ -1411,7 +1410,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm, struct wlr_drm_connector *conn = new_outputs[i]; wlr_drm_conn_log(conn, WLR_INFO, "Requesting modeset"); - wlr_signal_emit_safe(&drm->backend.events.new_output, + wl_signal_emit_mutable(&drm->backend.events.new_output, &conn->output); } } @@ -1664,7 +1663,7 @@ void wlr_drm_lease_terminate(struct wlr_drm_lease *lease) { void drm_lease_destroy(struct wlr_drm_lease *lease) { struct wlr_drm_backend *drm = lease->backend; - wlr_signal_emit_safe(&lease->events.destroy, NULL); + wl_signal_emit_mutable(&lease->events.destroy, NULL); struct wlr_drm_connector *conn; wl_list_for_each(conn, &drm->outputs, link) { diff --git a/backend/headless/backend.c b/backend/headless/backend.c index b14dda4a9..34536765e 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -3,7 +3,6 @@ #include #include #include "backend/headless.h" -#include "util/signal.h" struct wlr_headless_backend *headless_backend_from_backend( struct wlr_backend *wlr_backend) { @@ -20,7 +19,7 @@ static bool backend_start(struct wlr_backend *wlr_backend) { wl_list_for_each(output, &backend->outputs, link) { wl_event_source_timer_update(output->frame_timer, output->frame_delay); wlr_output_update_enabled(&output->wlr_output, true); - wlr_signal_emit_safe(&backend->backend.events.new_output, + wl_signal_emit_mutable(&backend->backend.events.new_output, &output->wlr_output); } diff --git a/backend/headless/output.c b/backend/headless/output.c index 2ce15a16c..5350747f8 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -4,7 +4,6 @@ #include #include #include "backend/headless.h" -#include "util/signal.h" static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | @@ -134,7 +133,7 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend, if (backend->started) { wl_event_source_timer_update(output->frame_timer, output->frame_delay); wlr_output_update_enabled(wlr_output, true); - wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output); + wl_signal_emit_mutable(&backend->backend.events.new_output, wlr_output); } return wlr_output; diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index f47121dbe..02c2f64b1 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -6,7 +6,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" static struct wlr_libinput_backend *get_libinput_backend_from_backend( struct wlr_backend *wlr_backend) { diff --git a/backend/libinput/events.c b/backend/libinput/events.c index c5d9c67a3..cbbf75370 100644 --- a/backend/libinput/events.c +++ b/backend/libinput/events.c @@ -11,7 +11,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) { if (dev->keyboard.impl) { @@ -87,7 +86,7 @@ static void handle_device_added(struct wlr_libinput_backend *backend, libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) { init_device_keyboard(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->keyboard.base); } @@ -95,35 +94,35 @@ static void handle_device_added(struct wlr_libinput_backend *backend, libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) { init_device_pointer(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->pointer.base); } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_SWITCH)) { init_device_switch(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->switch_device.base); } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) { init_device_touch(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->touch.base); } if (libinput_device_has_capability(libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) { init_device_tablet(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->tablet.base); } if (libinput_device_has_capability( libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) { init_device_tablet_pad(dev); - wlr_signal_emit_safe(&backend->backend.events.new_input, + wl_signal_emit_mutable(&backend->backend.events.new_input, &dev->tablet_pad.base); } diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 841d3dfca..48f8ae128 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -2,7 +2,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" const struct wlr_pointer_impl libinput_pointer_impl = { .name = "libinput-pointer", @@ -37,8 +36,8 @@ void handle_pointer_motion(struct libinput_event *event, wlr_event.delta_y = libinput_event_pointer_get_dy(pevent); wlr_event.unaccel_dx = libinput_event_pointer_get_dx_unaccelerated(pevent); wlr_event.unaccel_dy = libinput_event_pointer_get_dy_unaccelerated(pevent); - wlr_signal_emit_safe(&pointer->events.motion, &wlr_event); - wlr_signal_emit_safe(&pointer->events.frame, pointer); + wl_signal_emit_mutable(&pointer->events.motion, &wlr_event); + wl_signal_emit_mutable(&pointer->events.frame, pointer); } void handle_pointer_motion_abs(struct libinput_event *event, @@ -51,8 +50,8 @@ void handle_pointer_motion_abs(struct libinput_event *event, usec_to_msec(libinput_event_pointer_get_time_usec(pevent)); wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1); wlr_event.y = libinput_event_pointer_get_absolute_y_transformed(pevent, 1); - wlr_signal_emit_safe(&pointer->events.motion_absolute, &wlr_event); - wlr_signal_emit_safe(&pointer->events.frame, pointer); + wl_signal_emit_mutable(&pointer->events.motion_absolute, &wlr_event); + wl_signal_emit_mutable(&pointer->events.frame, pointer); } void handle_pointer_button(struct libinput_event *event, @@ -72,8 +71,8 @@ void handle_pointer_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_RELEASED; break; } - wlr_signal_emit_safe(&pointer->events.button, &wlr_event); - wlr_signal_emit_safe(&pointer->events.frame, pointer); + wl_signal_emit_mutable(&pointer->events.button, &wlr_event); + wl_signal_emit_mutable(&pointer->events.frame, pointer); } void handle_pointer_axis(struct libinput_event *event, @@ -120,9 +119,9 @@ void handle_pointer_axis(struct libinput_event *event, wlr_event.delta_discrete = libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); wlr_event.delta_discrete *= WLR_POINTER_AXIS_DISCRETE_STEP; - wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); + wl_signal_emit_mutable(&pointer->events.axis, &wlr_event); } - wlr_signal_emit_safe(&pointer->events.frame, pointer); + wl_signal_emit_mutable(&pointer->events.frame, pointer); } #if LIBINPUT_HAS_SCROLL_VALUE120 @@ -158,9 +157,9 @@ void handle_pointer_axis_value120(struct libinput_event *event, wlr_event.delta_discrete = libinput_event_pointer_get_scroll_value_v120(pevent, axes[i]); } - wlr_signal_emit_safe(&pointer->events.axis, &wlr_event); + wl_signal_emit_mutable(&pointer->events.axis, &wlr_event); } - wlr_signal_emit_safe(&pointer->events.frame, pointer); + wl_signal_emit_mutable(&pointer->events.frame, pointer); } #endif @@ -174,7 +173,7 @@ void handle_pointer_swipe_begin(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&pointer->events.swipe_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->events.swipe_begin, &wlr_event); } void handle_pointer_swipe_update(struct libinput_event *event, @@ -189,7 +188,7 @@ void handle_pointer_swipe_update(struct libinput_event *event, .dx = libinput_event_gesture_get_dx(gevent), .dy = libinput_event_gesture_get_dy(gevent), }; - wlr_signal_emit_safe(&pointer->events.swipe_update, &wlr_event); + wl_signal_emit_mutable(&pointer->events.swipe_update, &wlr_event); } void handle_pointer_swipe_end(struct libinput_event *event, @@ -202,7 +201,7 @@ void handle_pointer_swipe_end(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&pointer->events.swipe_end, &wlr_event); + wl_signal_emit_mutable(&pointer->events.swipe_end, &wlr_event); } void handle_pointer_pinch_begin(struct libinput_event *event, @@ -215,7 +214,7 @@ void handle_pointer_pinch_begin(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&pointer->events.pinch_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->events.pinch_begin, &wlr_event); } void handle_pointer_pinch_update(struct libinput_event *event, @@ -232,7 +231,7 @@ void handle_pointer_pinch_update(struct libinput_event *event, .scale = libinput_event_gesture_get_scale(gevent), .rotation = libinput_event_gesture_get_angle_delta(gevent), }; - wlr_signal_emit_safe(&pointer->events.pinch_update, &wlr_event); + wl_signal_emit_mutable(&pointer->events.pinch_update, &wlr_event); } void handle_pointer_pinch_end(struct libinput_event *event, @@ -245,7 +244,7 @@ void handle_pointer_pinch_end(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&pointer->events.pinch_end, &wlr_event); + wl_signal_emit_mutable(&pointer->events.pinch_end, &wlr_event); } void handle_pointer_hold_begin(struct libinput_event *event, @@ -258,7 +257,7 @@ void handle_pointer_hold_begin(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .fingers = libinput_event_gesture_get_finger_count(gevent), }; - wlr_signal_emit_safe(&pointer->events.hold_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->events.hold_begin, &wlr_event); } void handle_pointer_hold_end(struct libinput_event *event, @@ -271,5 +270,5 @@ void handle_pointer_hold_end(struct libinput_event *event, usec_to_msec(libinput_event_gesture_get_time_usec(gevent)), .cancelled = libinput_event_gesture_get_cancelled(gevent), }; - wlr_signal_emit_safe(&pointer->events.hold_end, &wlr_event); + wl_signal_emit_mutable(&pointer->events.hold_end, &wlr_event); } diff --git a/backend/libinput/switch.c b/backend/libinput/switch.c index 2e89ed59a..e8c68befa 100644 --- a/backend/libinput/switch.c +++ b/backend/libinput/switch.c @@ -2,7 +2,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" const struct wlr_switch_impl libinput_switch_impl = { .name = "libinput-switch", @@ -48,5 +47,5 @@ void handle_switch_toggle(struct libinput_event *event, } wlr_event.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)); - wlr_signal_emit_safe(&wlr_switch->events.toggle, &wlr_event); + wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event); } diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c index 083711ef0..078f7ca12 100644 --- a/backend/libinput/tablet_pad.c +++ b/backend/libinput/tablet_pad.c @@ -6,7 +6,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = { .name = "libinput-tablet-pad", @@ -160,7 +159,7 @@ void handle_tablet_pad_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_RELEASED; break; } - wlr_signal_emit_safe(&tablet_pad->events.button, &wlr_event); + wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event); } void handle_tablet_pad_ring(struct libinput_event *event, @@ -181,7 +180,7 @@ void handle_tablet_pad_ring(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_RING_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&tablet_pad->events.ring, &wlr_event); + wl_signal_emit_mutable(&tablet_pad->events.ring, &wlr_event); } void handle_tablet_pad_strip(struct libinput_event *event, @@ -202,5 +201,5 @@ void handle_tablet_pad_strip(struct libinput_event *event, wlr_event.source = WLR_TABLET_PAD_STRIP_SOURCE_FINGER; break; } - wlr_signal_emit_safe(&tablet_pad->events.strip, &wlr_event); + wl_signal_emit_mutable(&tablet_pad->events.strip, &wlr_event); } diff --git a/backend/libinput/tablet_tool.c b/backend/libinput/tablet_tool.c index 31cd18b8c..d049d16ee 100644 --- a/backend/libinput/tablet_tool.c +++ b/backend/libinput/tablet_tool.c @@ -6,7 +6,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" struct tablet_tool { struct wlr_tablet_tool wlr_tool; @@ -36,7 +35,7 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) { } static void tool_destroy(struct tablet_tool *tool) { - wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); + wl_signal_emit_mutable(&tool->wlr_tool.events.destroy, &tool->wlr_tool); libinput_tablet_tool_unref(tool->handle); libinput_tablet_tool_set_user_data(tool->handle, NULL); wl_list_remove(&tool->link); @@ -173,7 +172,7 @@ void handle_tablet_tool_axis(struct libinput_event *event, wlr_event.updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL; wlr_event.wheel_delta = libinput_event_tablet_tool_get_wheel_delta(tevent); } - wlr_signal_emit_safe(&wlr_tablet->events.axis, &wlr_event); + wl_signal_emit_mutable(&wlr_tablet->events.axis, &wlr_event); } void handle_tablet_tool_proximity(struct libinput_event *event, @@ -200,7 +199,7 @@ void handle_tablet_tool_proximity(struct libinput_event *event, wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN; break; } - wlr_signal_emit_safe(&wlr_tablet->events.proximity, &wlr_event); + wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event); if (libinput_event_tablet_tool_get_proximity_state(tevent) == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) { @@ -242,7 +241,7 @@ void handle_tablet_tool_tip(struct libinput_event *event, wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN; break; } - wlr_signal_emit_safe(&wlr_tablet->events.tip, &wlr_event); + wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event); } void handle_tablet_tool_button(struct libinput_event *event, @@ -268,5 +267,5 @@ void handle_tablet_tool_button(struct libinput_event *event, wlr_event.state = WLR_BUTTON_PRESSED; break; } - wlr_signal_emit_safe(&wlr_tablet->events.button, &wlr_event); + wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event); } diff --git a/backend/libinput/touch.c b/backend/libinput/touch.c index 1475a03e8..3316754ef 100644 --- a/backend/libinput/touch.c +++ b/backend/libinput/touch.c @@ -2,7 +2,6 @@ #include #include #include "backend/libinput.h" -#include "util/signal.h" const struct wlr_touch_impl libinput_touch_impl = { .name = "libinput-touch", @@ -39,7 +38,7 @@ void handle_touch_down(struct libinput_event *event, wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1); wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1); - wlr_signal_emit_safe(&touch->events.down, &wlr_event); + wl_signal_emit_mutable(&touch->events.down, &wlr_event); } void handle_touch_up(struct libinput_event *event, @@ -51,7 +50,7 @@ void handle_touch_up(struct libinput_event *event, wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); - wlr_signal_emit_safe(&touch->events.up, &wlr_event); + wl_signal_emit_mutable(&touch->events.up, &wlr_event); } void handle_touch_motion(struct libinput_event *event, @@ -65,7 +64,7 @@ void handle_touch_motion(struct libinput_event *event, wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1); wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1); - wlr_signal_emit_safe(&touch->events.motion, &wlr_event); + wl_signal_emit_mutable(&touch->events.motion, &wlr_event); } void handle_touch_cancel(struct libinput_event *event, @@ -77,10 +76,10 @@ void handle_touch_cancel(struct libinput_event *event, wlr_event.time_msec = usec_to_msec(libinput_event_touch_get_time_usec(tevent)); wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent); - wlr_signal_emit_safe(&touch->events.cancel, &wlr_event); + wl_signal_emit_mutable(&touch->events.cancel, &wlr_event); } void handle_touch_frame(struct libinput_event *event, struct wlr_touch *touch) { - wlr_signal_emit_safe(&touch->events.frame, NULL); + wl_signal_emit_mutable(&touch->events.frame, NULL); } diff --git a/backend/multi/backend.c b/backend/multi/backend.c index b06bc4865..f392db318 100644 --- a/backend/multi/backend.c +++ b/backend/multi/backend.c @@ -9,7 +9,6 @@ #include #include "backend/backend.h" #include "backend/multi.h" -#include "util/signal.h" struct subbackend_state { struct wlr_backend *backend; @@ -161,13 +160,13 @@ bool wlr_backend_is_multi(struct wlr_backend *b) { static void new_input_reemit(struct wl_listener *listener, void *data) { struct subbackend_state *state = wl_container_of(listener, state, new_input); - wlr_signal_emit_safe(&state->container->events.new_input, data); + wl_signal_emit_mutable(&state->container->events.new_input, data); } static void new_output_reemit(struct wl_listener *listener, void *data) { struct subbackend_state *state = wl_container_of(listener, state, new_output); - wlr_signal_emit_safe(&state->container->events.new_output, data); + wl_signal_emit_mutable(&state->container->events.new_output, data); } static void handle_subbackend_destroy(struct wl_listener *listener, @@ -218,7 +217,7 @@ bool wlr_multi_backend_add(struct wlr_backend *_multi, wl_signal_add(&backend->events.new_output, &sub->new_output); sub->new_output.notify = new_output_reemit; - wlr_signal_emit_safe(&multi->events.backend_add, backend); + wl_signal_emit_mutable(&multi->events.backend_add, backend); return true; } @@ -230,7 +229,7 @@ void wlr_multi_backend_remove(struct wlr_backend *_multi, multi_backend_get_subbackend(multi, backend); if (sub) { - wlr_signal_emit_safe(&multi->events.backend_remove, backend); + wl_signal_emit_mutable(&multi->events.backend_remove, backend); subbackend_state_destroy(sub); } } diff --git a/backend/session/session.c b/backend/session/session.c index 7d6d080da..fcd25fec1 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -17,7 +17,6 @@ #include #include #include "backend/session/session.h" -#include "util/signal.h" #include @@ -26,13 +25,13 @@ static void handle_enable_seat(struct libseat *seat, void *data) { struct wlr_session *session = data; session->active = true; - wlr_signal_emit_safe(&session->events.active, NULL); + wl_signal_emit_mutable(&session->events.active, NULL); } static void handle_disable_seat(struct libseat *seat, void *data) { struct wlr_session *session = data; session->active = false; - wlr_signal_emit_safe(&session->events.active, NULL); + wl_signal_emit_mutable(&session->events.active, NULL); libseat_disable_seat(session->seat_handle); } @@ -198,7 +197,7 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) { struct wlr_session_add_event event = { .path = devnode, }; - wlr_signal_emit_safe(&session->events.add_drm_card, &event); + wl_signal_emit_mutable(&session->events.add_drm_card, &event); } else if (strcmp(action, "change") == 0 || strcmp(action, "remove") == 0) { dev_t devnum = udev_device_get_devnum(udev_dev); struct wlr_device *dev; @@ -211,10 +210,10 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) { wlr_log(WLR_DEBUG, "DRM device %s changed", sysname); struct wlr_device_change_event event = {0}; read_udev_change_event(&event, udev_dev); - wlr_signal_emit_safe(&dev->events.change, &event); + wl_signal_emit_mutable(&dev->events.change, &event); } else if (strcmp(action, "remove") == 0) { wlr_log(WLR_DEBUG, "DRM device %s removed", sysname); - wlr_signal_emit_safe(&dev->events.remove, NULL); + wl_signal_emit_mutable(&dev->events.remove, NULL); } else { assert(0); } @@ -298,7 +297,7 @@ void wlr_session_destroy(struct wlr_session *session) { return; } - wlr_signal_emit_safe(&session->events.destroy, session); + wl_signal_emit_mutable(&session->events.destroy, session); wl_list_remove(&session->display_destroy.link); wl_event_source_remove(session->udev_event); diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 2980324f6..9cf4ed5ed 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -19,7 +19,6 @@ #include "backend/wayland.h" #include "render/drm_format_set.h" #include "render/pixel_format.h" -#include "util/signal.h" #include "drm-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" diff --git a/backend/wayland/output.c b/backend/wayland/output.c index baa25bc37..36b3911b1 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -19,7 +19,6 @@ #include "render/pixel_format.h" #include "render/swapchain.h" #include "render/wlr_renderer.h" -#include "util/signal.h" #include "linux-dmabuf-unstable-v1-client-protocol.h" #include "presentation-time-client-protocol.h" @@ -579,7 +578,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { wl_list_insert(&backend->outputs, &output->link); wlr_output_update_enabled(wlr_output, true); - wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output); + wl_signal_emit_mutable(&backend->backend.events.new_output, wlr_output); struct wlr_wl_seat *seat; wl_list_for_each(seat, &backend->seats, link) { diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index b2f85459c..4ce233e52 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -7,7 +7,6 @@ #include #include "backend/wayland.h" -#include "util/signal.h" #include "pointer-gestures-unstable-v1-client-protocol.h" #include "relative-pointer-unstable-v1-client-protocol.h" @@ -94,7 +93,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, .x = wl_fixed_to_double(sx) / wlr_output->width, .y = wl_fixed_to_double(sy) / wlr_output->height, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.motion_absolute, &event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion_absolute, &event); } static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, @@ -111,7 +110,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, .state = state, .time_msec = time, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.button, &event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.button, &event); } static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, @@ -130,7 +129,7 @@ static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, .time_msec = time, .source = pointer->axis_source, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.axis, &event); pointer->axis_discrete = 0; } @@ -142,7 +141,7 @@ static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) { return; } - wlr_signal_emit_safe(&pointer->wlr_pointer.events.frame, + wl_signal_emit_mutable(&pointer->wlr_pointer.events.frame, &pointer->wlr_pointer); } @@ -173,7 +172,7 @@ static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, .time_msec = time, .source = pointer->axis_source, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.axis, &event); } static void pointer_handle_axis_discrete(void *data, @@ -228,7 +227,7 @@ static void gesture_swipe_begin(void *data, .time_msec = time, .fingers = fingers, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_begin, &wlr_event); } static void gesture_swipe_update(void *data, @@ -247,7 +246,7 @@ static void gesture_swipe_update(void *data, .dx = wl_fixed_to_double(dx), .dy = wl_fixed_to_double(dy), }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_update, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_update, &wlr_event); } static void gesture_swipe_end(void *data, @@ -264,7 +263,7 @@ static void gesture_swipe_end(void *data, .time_msec = time, .cancelled = cancelled, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.swipe_end, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_end, &wlr_event); } static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_impl = { @@ -291,7 +290,7 @@ static void gesture_pinch_begin(void *data, .fingers = pointer->fingers, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_begin, &wlr_event); } static void gesture_pinch_update(void *data, @@ -313,7 +312,7 @@ static void gesture_pinch_update(void *data, .scale = wl_fixed_to_double(scale), .rotation = wl_fixed_to_double(rotation), }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_update, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_update, &wlr_event); } static void gesture_pinch_end(void *data, @@ -330,7 +329,7 @@ static void gesture_pinch_end(void *data, .time_msec = time, .cancelled = cancelled, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.pinch_end, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_end, &wlr_event); } static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_impl = { @@ -356,7 +355,7 @@ static void gesture_hold_begin(void *data, .time_msec = time, .fingers = fingers, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.hold_begin, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.hold_begin, &wlr_event); } static void gesture_hold_end(void *data, @@ -373,7 +372,7 @@ static void gesture_hold_end(void *data, .time_msec = time, .cancelled = cancelled, }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.hold_end, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.hold_end, &wlr_event); } static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_impl = { @@ -401,7 +400,7 @@ static void relative_pointer_handle_relative_motion(void *data, .unaccel_dx = wl_fixed_to_double(dx_unaccel), .unaccel_dy = wl_fixed_to_double(dy_unaccel), }; - wlr_signal_emit_safe(&pointer->wlr_pointer.events.motion, &wlr_event); + wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion, &wlr_event); } static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { @@ -463,7 +462,7 @@ void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy); pointer->output_destroy.notify = pointer_output_destroy; - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + wl_signal_emit_mutable(&seat->backend->backend.events.new_input, &pointer->wlr_pointer.base); wl_list_insert(&seat->pointers, &pointer->link); diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 655f9dad1..b81fe2193 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -18,7 +18,6 @@ #include #include "backend/wayland.h" -#include "util/signal.h" #include "util/time.h" static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, @@ -113,7 +112,7 @@ void init_seat_keyboard(struct wlr_wl_seat *seat) { wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, &seat->wlr_keyboard); - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + wl_signal_emit_mutable(&seat->backend->backend.events.new_input, &seat->wlr_keyboard.base); } @@ -148,7 +147,7 @@ static void touch_handle_down(void *data, struct wl_touch *wl_touch, .touch_id = id, }; touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); - wlr_signal_emit_safe(&touch->events.down, &event); + wl_signal_emit_mutable(&touch->events.down, &event); } static void touch_handle_up(void *data, struct wl_touch *wl_touch, @@ -161,7 +160,7 @@ static void touch_handle_up(void *data, struct wl_touch *wl_touch, .time_msec = time, .touch_id = id, }; - wlr_signal_emit_safe(&touch->events.up, &event); + wl_signal_emit_mutable(&touch->events.up, &event); } static void touch_handle_motion(void *data, struct wl_touch *wl_touch, @@ -176,12 +175,12 @@ static void touch_handle_motion(void *data, struct wl_touch *wl_touch, }; touch_coordinates_to_absolute(seat, x, y, &event.x, &event.y); - wlr_signal_emit_safe(&touch->events.motion, &event); + wl_signal_emit_mutable(&touch->events.motion, &event); } static void touch_handle_frame(void *data, struct wl_touch *wl_touch) { struct wlr_wl_seat *seat = data; - wlr_signal_emit_safe(&seat->wlr_touch.events.frame, NULL); + wl_signal_emit_mutable(&seat->wlr_touch.events.frame, NULL); } static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) { @@ -228,7 +227,7 @@ void init_seat_touch(struct wlr_wl_seat *seat) { } wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + wl_signal_emit_mutable(&seat->backend->backend.events.new_input, &seat->wlr_touch.base); } diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index bedaabf20..d1aeecd27 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -9,7 +9,6 @@ #include #include "backend/wayland.h" -#include "util/signal.h" #include "util/time.h" #include "tablet-unstable-v2-client-protocol.h" @@ -108,11 +107,11 @@ static void handle_tablet_pad_ring_frame(void *data, }; if (ring->angle >= 0) { - wlr_signal_emit_safe(&ring->group->pad->events.ring, &evt); + wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt); } if (ring->stopped) { evt.position = -1; - wlr_signal_emit_safe(&ring->group->pad->events.ring, &evt); + wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt); } ring->angle = -1; @@ -161,11 +160,11 @@ static void handle_tablet_pad_strip_frame(void *data, }; if (strip->position >= 0) { - wlr_signal_emit_safe(&strip->group->pad->events.strip, &evt); + wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt); } if (strip->stopped) { evt.position = -1; - wlr_signal_emit_safe(&strip->group->pad->events.strip, &evt); + wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt); } strip->position = -1; @@ -345,13 +344,13 @@ static void handle_tablet_pad_button(void *data, .group = 0, }; - wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.button, &evt); + wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.button, &evt); } static void handle_tablet_pad_done(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { struct wlr_wl_seat *seat = data; - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + wl_signal_emit_mutable(&seat->backend->backend.events.new_input, &seat->wlr_tablet_pad.base); } @@ -362,7 +361,7 @@ static void handle_tablet_pad_enter(void *data, struct wlr_wl_seat *seat = data; assert(seat->zwp_tablet_v2 == tablet_p); - wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.attach_tablet, + wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.attach_tablet, &seat->wlr_tablet_tool); } @@ -591,7 +590,7 @@ static void handle_tablet_tool_button(void *data, WLR_BUTTON_RELEASED : WLR_BUTTON_PRESSED, }; - wlr_signal_emit_safe(&tablet->events.button, &evt); + wl_signal_emit_mutable(&tablet->events.button, &evt); } static void clear_tablet_tool_values(struct tablet_tool *tool) { @@ -629,7 +628,7 @@ static void handle_tablet_tool_frame(void *data, .state = WLR_TABLET_TOOL_PROXIMITY_IN, }; - wlr_signal_emit_safe(&tablet->events.proximity, &evt); + wl_signal_emit_mutable(&tablet->events.proximity, &evt); } { @@ -686,7 +685,7 @@ static void handle_tablet_tool_frame(void *data, } if (evt.updated_axes) { - wlr_signal_emit_safe(&tablet->events.axis, &evt); + wl_signal_emit_mutable(&tablet->events.axis, &evt); } } @@ -705,7 +704,7 @@ static void handle_tablet_tool_frame(void *data, .state = WLR_TABLET_TOOL_TIP_DOWN, }; - wlr_signal_emit_safe(&tablet->events.tip, &evt); + wl_signal_emit_mutable(&tablet->events.tip, &evt); } if (tool->is_up) { @@ -718,7 +717,7 @@ static void handle_tablet_tool_frame(void *data, .state = WLR_TABLET_TOOL_TIP_UP, }; - wlr_signal_emit_safe(&tablet->events.tip, &evt); + wl_signal_emit_mutable(&tablet->events.tip, &evt); } if (tool->is_out) { @@ -731,7 +730,7 @@ static void handle_tablet_tool_frame(void *data, .state = WLR_TABLET_TOOL_PROXIMITY_OUT, }; - wlr_signal_emit_safe(&tablet->events.proximity, &evt); + wl_signal_emit_mutable(&tablet->events.proximity, &evt); } clear_values: @@ -829,7 +828,7 @@ static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { struct wlr_wl_seat *seat = data; - wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + wl_signal_emit_mutable(&seat->backend->backend.events.new_input, &seat->wlr_tablet.base); } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index dbbd74e89..1bb94410e 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -30,7 +30,6 @@ #include "backend/x11.h" #include "render/drm_format_set.h" -#include "util/signal.h" // See dri2_format_for_depth in mesa const struct wlr_x11_format formats[] = { @@ -164,7 +163,7 @@ static bool backend_start(struct wlr_backend *backend) { wlr_log(WLR_INFO, "Starting X11 backend"); - wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard.base); + wl_signal_emit_mutable(&x11->backend.events.new_input, &x11->keyboard.base); for (size_t i = 0; i < x11->requested_outputs; ++i) { wlr_x11_output_create(&x11->backend); diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 41168222d..603316f11 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -16,7 +16,6 @@ #include #include "backend/x11.h" -#include "util/signal.h" static void send_key_event(struct wlr_x11_backend *x11, uint32_t key, enum wl_keyboard_key_state st, xcb_timestamp_t time) { @@ -37,8 +36,8 @@ static void send_button_event(struct wlr_x11_output *output, uint32_t key, .button = key, .state = st, }; - wlr_signal_emit_safe(&output->pointer.events.button, &ev); - wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer); + wl_signal_emit_mutable(&output->pointer.events.button, &ev); + wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer); } static void send_axis_event(struct wlr_x11_output *output, int32_t delta, @@ -52,8 +51,8 @@ static void send_axis_event(struct wlr_x11_output *output, int32_t delta, .delta = delta * 15, .delta_discrete = delta, }; - wlr_signal_emit_safe(&output->pointer.events.axis, &ev); - wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer); + wl_signal_emit_mutable(&output->pointer.events.axis, &ev); + wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer); } static void send_pointer_position_event(struct wlr_x11_output *output, @@ -64,8 +63,8 @@ static void send_pointer_position_event(struct wlr_x11_output *output, .x = (double)x / output->wlr_output.width, .y = (double)y / output->wlr_output.height, }; - wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &ev); - wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer); + wl_signal_emit_mutable(&output->pointer.events.motion_absolute, &ev); + wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer); } static void send_touch_down_event(struct wlr_x11_output *output, @@ -77,8 +76,8 @@ static void send_touch_down_event(struct wlr_x11_output *output, .y = (double)y / output->wlr_output.height, .touch_id = touch_id, }; - wlr_signal_emit_safe(&output->touch.events.down, &ev); - wlr_signal_emit_safe(&output->touch.events.frame, NULL); + wl_signal_emit_mutable(&output->touch.events.down, &ev); + wl_signal_emit_mutable(&output->touch.events.frame, NULL); } static void send_touch_motion_event(struct wlr_x11_output *output, @@ -90,8 +89,8 @@ static void send_touch_motion_event(struct wlr_x11_output *output, .y = (double)y / output->wlr_output.height, .touch_id = touch_id, }; - wlr_signal_emit_safe(&output->touch.events.motion, &ev); - wlr_signal_emit_safe(&output->touch.events.frame, NULL); + wl_signal_emit_mutable(&output->touch.events.motion, &ev); + wl_signal_emit_mutable(&output->touch.events.frame, NULL); } static void send_touch_up_event(struct wlr_x11_output *output, @@ -101,8 +100,8 @@ static void send_touch_up_event(struct wlr_x11_output *output, .time_msec = time, .touch_id = touch_id, }; - wlr_signal_emit_safe(&output->touch.events.up, &ev); - wlr_signal_emit_safe(&output->touch.events.frame, NULL); + wl_signal_emit_mutable(&output->touch.events.up, &ev); + wl_signal_emit_mutable(&output->touch.events.frame, NULL); } static struct wlr_x11_touchpoint *get_touchpoint_from_x11_touch_id( diff --git a/backend/x11/output.c b/backend/x11/output.c index 3a599023d..f56129ab7 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -21,7 +21,6 @@ #include #include "backend/x11.h" -#include "util/signal.h" #include "util/time.h" static const uint32_t SUPPORTED_OUTPUT_STATE = @@ -590,9 +589,9 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { output->touch.output_name = strdup(wlr_output->name); wl_list_init(&output->touchpoints); - wlr_signal_emit_safe(&x11->backend.events.new_output, wlr_output); - wlr_signal_emit_safe(&x11->backend.events.new_input, &output->pointer.base); - wlr_signal_emit_safe(&x11->backend.events.new_input, &output->touch.base); + wl_signal_emit_mutable(&x11->backend.events.new_output, wlr_output); + wl_signal_emit_mutable(&x11->backend.events.new_input, &output->pointer.base); + wl_signal_emit_mutable(&x11->backend.events.new_input, &output->touch.base); // Start the rendering loop by requesting the compositor to render a frame wlr_output_schedule_frame(wlr_output); diff --git a/render/allocator/allocator.c b/render/allocator/allocator.c index 00dadd295..b380584c7 100644 --- a/render/allocator/allocator.c +++ b/render/allocator/allocator.c @@ -14,7 +14,6 @@ #include "render/allocator/drm_dumb.h" #include "render/allocator/shm.h" #include "render/wlr_renderer.h" -#include "util/signal.h" #if WLR_HAS_GBM_ALLOCATOR #include "render/allocator/gbm.h" @@ -159,7 +158,7 @@ void wlr_allocator_destroy(struct wlr_allocator *alloc) { if (alloc == NULL) { return; } - wlr_signal_emit_safe(&alloc->events.destroy, NULL); + wl_signal_emit_mutable(&alloc->events.destroy, NULL); alloc->impl->destroy(alloc); } diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 8b4ce6739..776baf40a 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -15,7 +15,6 @@ #include "render/gles2.h" #include "render/pixel_format.h" #include "types/wlr_buffer.h" -#include "util/signal.h" static const struct wlr_texture_impl texture_impl; diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 478db7453..622f5f961 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -26,7 +26,6 @@ #endif // WLR_HAS_VULKAN_RENDERER #include "backend/backend.h" -#include "util/signal.h" #include "render/pixel_format.h" #include "render/wlr_renderer.h" @@ -53,7 +52,7 @@ void wlr_renderer_destroy(struct wlr_renderer *r) { assert(!r->rendering); - wlr_signal_emit_safe(&r->events.destroy, r); + wl_signal_emit_mutable(&r->events.destroy, r); if (r->impl && r->impl->destroy) { r->impl->destroy(r); diff --git a/types/data_device/wlr_data_device.c b/types/data_device/wlr_data_device.c index ceaf80e72..7e6747905 100644 --- a/types/data_device/wlr_data_device.c +++ b/types/data_device/wlr_data_device.c @@ -9,7 +9,6 @@ #include #include #include "types/wlr_data_device.h" -#include "util/signal.h" #define DATA_DEVICE_MANAGER_VERSION 3 @@ -162,7 +161,7 @@ void wlr_seat_request_set_selection(struct wlr_seat *seat, .source = source, .serial = serial, }; - wlr_signal_emit_safe(&seat->events.request_set_selection, &event); + wl_signal_emit_mutable(&seat->events.request_set_selection, &event); } static void seat_handle_selection_source_destroy( @@ -179,7 +178,7 @@ static void seat_handle_selection_source_destroy( seat_client_send_selection(focused_client); } - wlr_signal_emit_safe(&seat->events.set_selection, seat); + wl_signal_emit_mutable(&seat->events.set_selection, seat); } void wlr_seat_set_selection(struct wlr_seat *seat, @@ -211,7 +210,7 @@ void wlr_seat_set_selection(struct wlr_seat *seat, seat_client_send_selection(focused_client); } - wlr_signal_emit_safe(&seat->events.set_selection, seat); + wl_signal_emit_mutable(&seat->events.set_selection, seat); } @@ -280,7 +279,7 @@ static void data_device_manager_bind(struct wl_client *client, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_data_device_manager *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/data_device/wlr_data_offer.c b/types/data_device/wlr_data_offer.c index ce28c6d6e..67552b470 100644 --- a/types/data_device/wlr_data_offer.c +++ b/types/data_device/wlr_data_offer.c @@ -8,7 +8,6 @@ #include #include #include "types/wlr_data_device.h" -#include "util/signal.h" static const struct wl_data_offer_interface data_offer_impl; diff --git a/types/data_device/wlr_data_source.c b/types/data_device/wlr_data_source.c index b07c44873..dc9725fb1 100644 --- a/types/data_device/wlr_data_source.c +++ b/types/data_device/wlr_data_source.c @@ -9,7 +9,6 @@ #include #include #include "types/wlr_data_device.h" -#include "util/signal.h" void wlr_data_source_init(struct wlr_data_source *source, const struct wlr_data_source_impl *impl) { @@ -40,7 +39,7 @@ void wlr_data_source_destroy(struct wlr_data_source *source) { return; } - wlr_signal_emit_safe(&source->events.destroy, source); + wl_signal_emit_mutable(&source->events.destroy, source); char **p; wl_array_for_each(p, &source->mime_types) { diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index 0843870dc..9b48df324 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -9,7 +9,6 @@ #include #include #include "types/wlr_data_device.h" -#include "util/signal.h" static void drag_handle_seat_client_destroy(struct wl_listener *listener, void *data) { @@ -104,16 +103,16 @@ static void drag_set_focus(struct wlr_drag *drag, wl_signal_add(&focus_client->events.destroy, &drag->seat_client_destroy); out: - wlr_signal_emit_safe(&drag->events.focus, drag); + wl_signal_emit_mutable(&drag->events.focus, drag); } static void drag_icon_set_mapped(struct wlr_drag_icon *icon, bool mapped) { if (mapped && !icon->mapped) { icon->mapped = true; - wlr_signal_emit_safe(&icon->events.map, icon); + wl_signal_emit_mutable(&icon->events.map, icon); } else if (!mapped && icon->mapped) { icon->mapped = false; - wlr_signal_emit_safe(&icon->events.unmap, icon); + wl_signal_emit_mutable(&icon->events.unmap, icon); } } @@ -151,7 +150,7 @@ static void drag_destroy(struct wlr_drag *drag) { // to ensure that the wl_data_device.leave is sent before emitting the // signal. This allows e.g. wl_pointer.enter to be sent in the destroy // signal handler. - wlr_signal_emit_safe(&drag->events.destroy, drag); + wl_signal_emit_mutable(&drag->events.destroy, drag); if (drag->source) { wl_list_remove(&drag->source_destroy.link); @@ -188,7 +187,7 @@ static void drag_handle_pointer_motion(struct wlr_seat_pointer_grab *grab, .sx = sx, .sy = sy, }; - wlr_signal_emit_safe(&drag->events.motion, &event); + wl_signal_emit_mutable(&drag->events.motion, &event); } } @@ -209,7 +208,7 @@ static void drag_drop(struct wlr_drag *drag, uint32_t time) { .drag = drag, .time = time, }; - wlr_signal_emit_safe(&drag->events.drop, &event); + wl_signal_emit_mutable(&drag->events.drop, &event); } static uint32_t drag_handle_pointer_button(struct wlr_seat_pointer_grab *grab, @@ -364,7 +363,7 @@ static void drag_icon_destroy(struct wlr_drag_icon *icon) { return; } drag_icon_set_mapped(icon, false); - wlr_signal_emit_safe(&icon->events.destroy, icon); + wl_signal_emit_mutable(&icon->events.destroy, icon); icon->surface->role_data = NULL; wl_list_remove(&icon->surface_destroy.link); free(icon); @@ -480,7 +479,7 @@ void wlr_seat_request_start_drag(struct wlr_seat *seat, struct wlr_drag *drag, .origin = origin, .serial = serial, }; - wlr_signal_emit_safe(&seat->events.request_start_drag, &event); + wl_signal_emit_mutable(&seat->events.request_start_drag, &event); } static void seat_handle_drag_source_destroy(struct wl_listener *listener, @@ -511,7 +510,7 @@ void wlr_seat_start_drag(struct wlr_seat *seat, struct wlr_drag *drag, wl_signal_add(&drag->source->events.destroy, &seat->drag_source_destroy); } - wlr_signal_emit_safe(&seat->events.start_drag, drag); + wl_signal_emit_mutable(&seat->events.start_drag, drag); } void wlr_seat_start_pointer_drag(struct wlr_seat *seat, struct wlr_drag *drag, diff --git a/types/output/cursor.c b/types/output/cursor.c index 85973ce93..89f41b772 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -10,7 +10,6 @@ #include "render/swapchain.h" #include "types/wlr_buffer.h" #include "types/wlr_output.h" -#include "util/signal.h" static bool output_set_hardware_cursor(struct wlr_output *output, struct wlr_buffer *buffer, int hotspot_x, int hotspot_y) { @@ -168,7 +167,7 @@ static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) { .output = cursor->output, .damage = &damage, }; - wlr_signal_emit_safe(&cursor->output->events.damage, &event); + wl_signal_emit_mutable(&cursor->output->events.damage, &event); pixman_region32_fini(&damage); } diff --git a/types/output/output.c b/types/output/output.c index b45576faa..549dabd16 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -11,7 +11,6 @@ #include "render/swapchain.h" #include "types/wlr_output.h" #include "util/global.h" -#include "util/signal.h" #define OUTPUT_VERSION 4 @@ -124,7 +123,7 @@ static void output_bind(struct wl_client *wl_client, void *data, .resource = resource, }; - wlr_signal_emit_safe(&output->events.bind, &evt); + wl_signal_emit_mutable(&output->events.bind, &evt); } void wlr_output_create_global(struct wlr_output *output) { @@ -187,7 +186,7 @@ void wlr_output_update_enabled(struct wlr_output *output, bool enabled) { } output->enabled = enabled; - wlr_signal_emit_safe(&output->events.enable, output); + wl_signal_emit_mutable(&output->events.enable, output); } static void output_update_matrix(struct wlr_output *output) { @@ -255,7 +254,7 @@ void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width, } wlr_output_schedule_done(output); - wlr_signal_emit_safe(&output->events.mode, output); + wl_signal_emit_mutable(&output->events.mode, output); } void wlr_output_set_transform(struct wlr_output *output, @@ -306,7 +305,7 @@ void wlr_output_set_description(struct wlr_output *output, const char *desc) { } wlr_output_schedule_done(output); - wlr_signal_emit_safe(&output->events.description, output); + wl_signal_emit_mutable(&output->events.description, output); } static void handle_display_destroy(struct wl_listener *listener, void *data) { @@ -389,7 +388,7 @@ void wlr_output_destroy(struct wlr_output *output) { wlr_output_destroy_global(output); output_clear_back_buffer(output); - wlr_signal_emit_safe(&output->events.destroy, output); + wl_signal_emit_mutable(&output->events.destroy, output); wlr_addon_set_finish(&output->addons); // The backend is responsible for free-ing the list of modes @@ -747,7 +746,7 @@ bool wlr_output_commit_state(struct wlr_output *output, .when = &now, .state = &pending, }; - wlr_signal_emit_safe(&output->events.precommit, &pre_event); + wl_signal_emit_mutable(&output->events.precommit, &pre_event); // output_clear_back_buffer detaches the buffer from the renderer. This is // important to do before calling impl->commit(), because this marks an @@ -837,7 +836,7 @@ bool wlr_output_commit_state(struct wlr_output *output, .when = &now, .buffer = (pending.committed & WLR_OUTPUT_STATE_BUFFER) ? pending.buffer : NULL, }; - wlr_signal_emit_safe(&output->events.commit, &event); + wl_signal_emit_mutable(&output->events.commit, &event); wlr_buffer_unlock(back_buffer); if (new_back_buffer) { @@ -876,7 +875,7 @@ void wlr_output_attach_buffer(struct wlr_output *output, void wlr_output_send_frame(struct wlr_output *output) { output->frame_pending = false; if (output->enabled) { - wlr_signal_emit_safe(&output->events.frame, output); + wl_signal_emit_mutable(&output->events.frame, output); } } @@ -922,7 +921,7 @@ void wlr_output_send_present(struct wlr_output *output, event->when = &now; } - wlr_signal_emit_safe(&output->events.present, event); + wl_signal_emit_mutable(&output->events.present, event); } void wlr_output_set_gamma(struct wlr_output *output, size_t size, @@ -954,7 +953,7 @@ void wlr_output_update_needs_frame(struct wlr_output *output) { return; } output->needs_frame = true; - wlr_signal_emit_safe(&output->events.needs_frame, output); + wl_signal_emit_mutable(&output->events.needs_frame, output); } void wlr_output_damage_whole(struct wlr_output *output) { @@ -968,7 +967,7 @@ void wlr_output_damage_whole(struct wlr_output *output) { .output = output, .damage = &damage, }; - wlr_signal_emit_safe(&output->events.damage, &event); + wl_signal_emit_mutable(&output->events.damage, &event); pixman_region32_fini(&damage); } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index d2da8bd45..27494248e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -13,7 +13,6 @@ #include #include "types/wlr_buffer.h" #include "types/wlr_scene.h" -#include "util/signal.h" #include "util/time.h" #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 @@ -83,7 +82,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { // We want to call the destroy listeners before we do anything else // in case the destroy signal would like to remove children before they // are recursively destroyed. - wlr_signal_emit_safe(&node->events.destroy, NULL); + wl_signal_emit_mutable(&node->events.destroy, NULL); wlr_scene_node_set_enabled(node, false); @@ -96,7 +95,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, &scene->outputs, link) { if (active & (1ull << scene_output->index)) { - wlr_signal_emit_safe(&scene_buffer->events.output_leave, + wl_signal_emit_mutable(&scene_buffer->events.output_leave, scene_output); } } @@ -385,9 +384,9 @@ static void update_node_update_outputs(struct wlr_scene_node *node, bool intersects_before = old_active & mask; if (intersects && !intersects_before) { - wlr_signal_emit_safe(&scene_buffer->events.output_enter, scene_output); + wl_signal_emit_mutable(&scene_buffer->events.output_enter, scene_output); } else if (!intersects && intersects_before) { - wlr_signal_emit_safe(&scene_buffer->events.output_leave, scene_output); + wl_signal_emit_mutable(&scene_buffer->events.output_leave, scene_output); } } } @@ -723,7 +722,7 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer, void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer, struct timespec *now) { if (pixman_region32_not_empty(&scene_buffer->node.visible)) { - wlr_signal_emit_safe(&scene_buffer->events.frame_done, now); + wl_signal_emit_mutable(&scene_buffer->events.frame_done, now); } } @@ -1106,7 +1105,7 @@ static void scene_node_render(struct wlr_scene_node *node, render_texture(output, &render_region, texture, &scene_buffer->src_box, &dst_box, matrix); - wlr_signal_emit_safe(&scene_buffer->events.output_present, scene_output); + wl_signal_emit_mutable(&scene_buffer->events.output_present, scene_output); break; } @@ -1259,7 +1258,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { return; } - wlr_signal_emit_safe(&scene_output->events.destroy, NULL); + wl_signal_emit_mutable(&scene_output->events.destroy, NULL); scene_node_output_update(&scene_output->scene->tree.node, &scene_output->scene->outputs, scene_output); @@ -1498,7 +1497,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { assert(node->type == WLR_SCENE_NODE_BUFFER); struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); - wlr_signal_emit_safe(&buffer->events.output_present, scene_output); + wl_signal_emit_mutable(&buffer->events.output_present, scene_output); return true; } diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index d7652c124..59b760ca5 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -11,7 +11,6 @@ #include #include "types/wlr_seat.h" #include "util/global.h" -#include "util/signal.h" #define SEAT_VERSION 8 @@ -67,7 +66,7 @@ static void seat_client_handle_resource_destroy( return; } - wlr_signal_emit_safe(&client->events.destroy, client); + wl_signal_emit_mutable(&client->events.destroy, client); if (client == client->seat->pointer_state.focused_client) { client->seat->pointer_state.focused_client = NULL; @@ -181,7 +180,7 @@ void wlr_seat_destroy(struct wlr_seat *seat) { wlr_seat_touch_point_clear_focus(seat, 0, point->touch_id); } - wlr_signal_emit_safe(&seat->events.destroy, seat); + wl_signal_emit_mutable(&seat->events.destroy, seat); wl_list_remove(&seat->display_destroy.link); diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c index e1f137831..186b8251a 100644 --- a/types/seat/wlr_seat_keyboard.c +++ b/types/seat/wlr_seat_keyboard.c @@ -8,7 +8,6 @@ #include #include "types/wlr_data_device.h" #include "types/wlr_seat.h" -#include "util/signal.h" static void default_keyboard_enter(struct wlr_seat_keyboard_grab *grab, struct wlr_surface *surface, uint32_t keycodes[], size_t num_keycodes, @@ -168,7 +167,7 @@ void wlr_seat_keyboard_start_grab(struct wlr_seat *wlr_seat, grab->seat = wlr_seat; wlr_seat->keyboard_state.grab = grab; - wlr_signal_emit_safe(&wlr_seat->events.keyboard_grab_begin, grab); + wl_signal_emit_mutable(&wlr_seat->events.keyboard_grab_begin, grab); } void wlr_seat_keyboard_end_grab(struct wlr_seat *wlr_seat) { @@ -176,7 +175,7 @@ void wlr_seat_keyboard_end_grab(struct wlr_seat *wlr_seat) { if (grab != wlr_seat->keyboard_state.default_grab) { wlr_seat->keyboard_state.grab = wlr_seat->keyboard_state.default_grab; - wlr_signal_emit_safe(&wlr_seat->events.keyboard_grab_end, grab); + wl_signal_emit_mutable(&wlr_seat->events.keyboard_grab_end, grab); if (grab->interface->cancel) { grab->interface->cancel(grab); } @@ -303,7 +302,7 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat, .old_surface = focused_surface, .new_surface = surface, }; - wlr_signal_emit_safe(&seat->keyboard_state.events.focus_change, &event); + wl_signal_emit_mutable(&seat->keyboard_state.events.focus_change, &event); } void wlr_seat_keyboard_notify_enter(struct wlr_seat *seat, diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 2b49b79fa..5a6cb2359 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -7,7 +7,6 @@ #include #include #include "types/wlr_seat.h" -#include "util/signal.h" #include "util/array.h" static void default_pointer_enter(struct wlr_seat_pointer_grab *grab, @@ -101,7 +100,7 @@ static void pointer_set_cursor(struct wl_client *client, .hotspot_x = hotspot_x, .hotspot_y = hotspot_y, }; - wlr_signal_emit_safe(&seat_client->seat->events.request_set_cursor, &event); + wl_signal_emit_mutable(&seat_client->seat->events.request_set_cursor, &event); } static void pointer_release(struct wl_client *client, @@ -211,7 +210,7 @@ void wlr_seat_pointer_enter(struct wlr_seat *wlr_seat, .sx = sx, .sy = sy, }; - wlr_signal_emit_safe(&wlr_seat->pointer_state.events.focus_change, &event); + wl_signal_emit_mutable(&wlr_seat->pointer_state.events.focus_change, &event); } void wlr_seat_pointer_clear_focus(struct wlr_seat *wlr_seat) { @@ -403,14 +402,14 @@ void wlr_seat_pointer_start_grab(struct wlr_seat *wlr_seat, grab->seat = wlr_seat; wlr_seat->pointer_state.grab = grab; - wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_begin, grab); + wl_signal_emit_mutable(&wlr_seat->events.pointer_grab_begin, grab); } void wlr_seat_pointer_end_grab(struct wlr_seat *wlr_seat) { struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab; if (grab != wlr_seat->pointer_state.default_grab) { wlr_seat->pointer_state.grab = wlr_seat->pointer_state.default_grab; - wlr_signal_emit_safe(&wlr_seat->events.pointer_grab_end, grab); + wl_signal_emit_mutable(&wlr_seat->events.pointer_grab_end, grab); if (grab->interface->cancel) { grab->interface->cancel(grab); } diff --git a/types/seat/wlr_seat_touch.c b/types/seat/wlr_seat_touch.c index abc17ae2c..9b533c07b 100644 --- a/types/seat/wlr_seat_touch.c +++ b/types/seat/wlr_seat_touch.c @@ -7,7 +7,6 @@ #include #include #include "types/wlr_seat.h" -#include "util/signal.h" static uint32_t default_touch_down(struct wlr_seat_touch_grab *grab, uint32_t time, struct wlr_touch_point *point) { @@ -84,7 +83,7 @@ void wlr_seat_touch_start_grab(struct wlr_seat *wlr_seat, grab->seat = wlr_seat; wlr_seat->touch_state.grab = grab; - wlr_signal_emit_safe(&wlr_seat->events.touch_grab_begin, grab); + wl_signal_emit_mutable(&wlr_seat->events.touch_grab_begin, grab); } void wlr_seat_touch_end_grab(struct wlr_seat *wlr_seat) { @@ -92,7 +91,7 @@ void wlr_seat_touch_end_grab(struct wlr_seat *wlr_seat) { if (grab != wlr_seat->touch_state.default_grab) { wlr_seat->touch_state.grab = wlr_seat->touch_state.default_grab; - wlr_signal_emit_safe(&wlr_seat->events.touch_grab_end, grab); + wl_signal_emit_mutable(&wlr_seat->events.touch_grab_end, grab); if (grab->interface->cancel) { grab->interface->cancel(grab); } @@ -108,7 +107,7 @@ static void touch_point_clear_focus(struct wlr_touch_point *point) { } static void touch_point_destroy(struct wlr_touch_point *point) { - wlr_signal_emit_safe(&point->events.destroy, point); + wl_signal_emit_mutable(&point->events.destroy, point); touch_point_clear_focus(point); wl_list_remove(&point->surface_destroy.link); diff --git a/types/tablet_v2/wlr_tablet_v2.c b/types/tablet_v2/wlr_tablet_v2.c index 3bd333119..63bce2f72 100644 --- a/types/tablet_v2/wlr_tablet_v2.c +++ b/types/tablet_v2/wlr_tablet_v2.c @@ -13,7 +13,6 @@ #include #include #include "tablet-unstable-v2-protocol.h" -#include "util/signal.h" #define TABLET_MANAGER_VERSION 1 @@ -275,7 +274,7 @@ static void tablet_v2_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_tablet_manager_v2 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->wl_global); free(manager); diff --git a/types/tablet_v2/wlr_tablet_v2_pad.c b/types/tablet_v2/wlr_tablet_v2_pad.c index a7ac9ef8f..1bdb4ab76 100644 --- a/types/tablet_v2/wlr_tablet_v2_pad.c +++ b/types/tablet_v2/wlr_tablet_v2_pad.c @@ -11,7 +11,6 @@ #include #include #include -#include "util/signal.h" #include "tablet-unstable-v2-protocol.h" static const struct wlr_tablet_pad_v2_grab_interface default_pad_grab_interface; @@ -52,7 +51,7 @@ static void handle_tablet_pad_ring_v2_set_feedback(struct wl_client *client, .index = aux->index }; - wlr_signal_emit_safe(&aux->pad->pad->events.ring_feedback, &evt); + wl_signal_emit_mutable(&aux->pad->pad->events.ring_feedback, &evt); } static void handle_tablet_pad_ring_v2_destroy(struct wl_client *client, @@ -90,7 +89,7 @@ static void handle_tablet_pad_strip_v2_set_feedback(struct wl_client *client, .index = aux->index }; - wlr_signal_emit_safe(&aux->pad->pad->events.strip_feedback, &evt); + wl_signal_emit_mutable(&aux->pad->pad->events.strip_feedback, &evt); } static void handle_tablet_pad_strip_v2_destroy(struct wl_client *client, @@ -117,7 +116,7 @@ static void handle_tablet_pad_v2_set_feedback( struct wl_client *client, .description = description, }; - wlr_signal_emit_safe(&pad->pad->events.button_feedback, &evt); + wl_signal_emit_mutable(&pad->pad->events.button_feedback, &evt); } static const struct zwp_tablet_pad_v2_interface tablet_pad_impl = { diff --git a/types/tablet_v2/wlr_tablet_v2_tool.c b/types/tablet_v2/wlr_tablet_v2_tool.c index e47e91033..a2d7778c9 100644 --- a/types/tablet_v2/wlr_tablet_v2_tool.c +++ b/types/tablet_v2/wlr_tablet_v2_tool.c @@ -11,7 +11,6 @@ #include #include #include "util/array.h" -#include "util/signal.h" #include "util/time.h" #include "tablet-unstable-v2-protocol.h" @@ -47,7 +46,7 @@ static void handle_tablet_tool_v2_set_cursor(struct wl_client *client, .seat_client = tool->seat->seat_client, }; - wlr_signal_emit_safe(&tool->tool->events.set_cursor, &evt); + wl_signal_emit_mutable(&tool->tool->events.set_cursor, &evt); } static void handle_tablet_tool_v2_destroy(struct wl_client *client, diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index b63ce88ad..90bc40a8c 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -9,7 +9,6 @@ #include #include "render/pixel_format.h" #include "types/wlr_buffer.h" -#include "util/signal.h" void wlr_buffer_init(struct wlr_buffer *buffer, const struct wlr_buffer_impl *impl, int width, int height) { @@ -34,7 +33,7 @@ static void buffer_consider_destroy(struct wlr_buffer *buffer) { assert(!buffer->accessing_data_ptr); - wlr_signal_emit_safe(&buffer->events.destroy, NULL); + wl_signal_emit_mutable(&buffer->events.destroy, NULL); wlr_addon_set_finish(&buffer->addons); buffer->impl->destroy(buffer); @@ -64,7 +63,7 @@ void wlr_buffer_unlock(struct wlr_buffer *buffer) { buffer->n_locks--; if (buffer->n_locks == 0) { - wlr_signal_emit_safe(&buffer->events.release, NULL); + wl_signal_emit_mutable(&buffer->events.release, NULL); } buffer_consider_destroy(buffer); diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 331d932d5..fd7cc1d0d 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -12,7 +12,6 @@ #include #include "types/wlr_buffer.h" #include "types/wlr_region.h" -#include "util/signal.h" #include "util/time.h" #define COMPOSITOR_VERSION 5 @@ -492,7 +491,7 @@ static void surface_commit_state(struct wlr_surface *surface, surface->role->commit(surface); } - wlr_signal_emit_safe(&surface->events.commit, surface); + wl_signal_emit_mutable(&surface->events.commit, surface); } static void collect_subsurface_damage_iter(struct wlr_surface *surface, @@ -531,7 +530,7 @@ static void subsurface_parent_commit(struct wlr_subsurface *subsurface) { if (!subsurface->added) { subsurface->added = true; - wlr_signal_emit_safe(&subsurface->parent->events.new_subsurface, + wl_signal_emit_mutable(&subsurface->parent->events.new_subsurface, subsurface); } } @@ -541,7 +540,7 @@ static void surface_handle_commit(struct wl_client *client, struct wlr_surface *surface = wlr_surface_from_resource(resource); surface_finalize_pending(surface); - wlr_signal_emit_safe(&surface->events.client_commit, NULL); + wl_signal_emit_mutable(&surface->events.client_commit, NULL); if (surface->pending.cached_state_locks > 0 || !wl_list_empty(&surface->cached)) { surface_cache_pending(surface); @@ -667,7 +666,7 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { surface_output_destroy(surface_output); } - wlr_signal_emit_safe(&surface->events.destroy, surface); + wl_signal_emit_mutable(&surface->events.destroy, surface); wlr_addon_set_finish(&surface->addons); @@ -1126,7 +1125,7 @@ static void compositor_create_surface(struct wl_client *client, return; } - wlr_signal_emit_safe(&compositor->events.new_surface, surface); + wl_signal_emit_mutable(&compositor->events.new_surface, surface); } static void compositor_create_region(struct wl_client *client, @@ -1156,7 +1155,7 @@ static void compositor_handle_display_destroy( struct wl_listener *listener, void *data) { struct wlr_compositor *compositor = wl_container_of(listener, compositor, display_destroy); - wlr_signal_emit_safe(&compositor->events.destroy, NULL); + wl_signal_emit_mutable(&compositor->events.destroy, NULL); wl_list_remove(&compositor->display_destroy.link); wl_global_destroy(compositor->global); free(compositor); diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index d38d279ef..5da51d27f 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -12,7 +12,6 @@ #include #include #include -#include "util/signal.h" struct wlr_cursor_device { struct wlr_cursor *cursor; @@ -368,7 +367,7 @@ static void handle_pointer_motion(struct wl_listener *listener, void *data) { struct wlr_pointer_motion_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, motion); - wlr_signal_emit_safe(&device->cursor->events.motion, event); + wl_signal_emit_mutable(&device->cursor->events.motion, event); } static void apply_output_transform(double *x, double *y, @@ -440,80 +439,80 @@ static void handle_pointer_motion_absolute(struct wl_listener *listener, if (output) { apply_output_transform(&event->x, &event->y, output->transform); } - wlr_signal_emit_safe(&device->cursor->events.motion_absolute, event); + wl_signal_emit_mutable(&device->cursor->events.motion_absolute, event); } static void handle_pointer_button(struct wl_listener *listener, void *data) { struct wlr_pointer_button_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, button); - wlr_signal_emit_safe(&device->cursor->events.button, event); + wl_signal_emit_mutable(&device->cursor->events.button, event); } static void handle_pointer_axis(struct wl_listener *listener, void *data) { struct wlr_pointer_axis_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, axis); - wlr_signal_emit_safe(&device->cursor->events.axis, event); + wl_signal_emit_mutable(&device->cursor->events.axis, event); } static void handle_pointer_frame(struct wl_listener *listener, void *data) { struct wlr_cursor_device *device = wl_container_of(listener, device, frame); - wlr_signal_emit_safe(&device->cursor->events.frame, device->cursor); + wl_signal_emit_mutable(&device->cursor->events.frame, device->cursor); } static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { struct wlr_pointer_swipe_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_begin); - wlr_signal_emit_safe(&device->cursor->events.swipe_begin, event); + wl_signal_emit_mutable(&device->cursor->events.swipe_begin, event); } static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { struct wlr_pointer_swipe_update_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_update); - wlr_signal_emit_safe(&device->cursor->events.swipe_update, event); + wl_signal_emit_mutable(&device->cursor->events.swipe_update, event); } static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { struct wlr_pointer_swipe_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, swipe_end); - wlr_signal_emit_safe(&device->cursor->events.swipe_end, event); + wl_signal_emit_mutable(&device->cursor->events.swipe_end, event); } static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { struct wlr_pointer_pinch_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_begin); - wlr_signal_emit_safe(&device->cursor->events.pinch_begin, event); + wl_signal_emit_mutable(&device->cursor->events.pinch_begin, event); } static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { struct wlr_pointer_pinch_update_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_update); - wlr_signal_emit_safe(&device->cursor->events.pinch_update, event); + wl_signal_emit_mutable(&device->cursor->events.pinch_update, event); } static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { struct wlr_pointer_pinch_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, pinch_end); - wlr_signal_emit_safe(&device->cursor->events.pinch_end, event); + wl_signal_emit_mutable(&device->cursor->events.pinch_end, event); } static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) { struct wlr_pointer_hold_begin_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, hold_begin); - wlr_signal_emit_safe(&device->cursor->events.hold_begin, event); + wl_signal_emit_mutable(&device->cursor->events.hold_begin, event); } static void handle_pointer_hold_end(struct wl_listener *listener, void *data) { struct wlr_pointer_hold_end_event *event = data; struct wlr_cursor_device *device = wl_container_of(listener, device, hold_end); - wlr_signal_emit_safe(&device->cursor->events.hold_end, event); + wl_signal_emit_mutable(&device->cursor->events.hold_end, event); } static void handle_touch_up(struct wl_listener *listener, void *data) { struct wlr_touch_up_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_up); - wlr_signal_emit_safe(&device->cursor->events.touch_up, event); + wl_signal_emit_mutable(&device->cursor->events.touch_up, event); } static void handle_touch_down(struct wl_listener *listener, void *data) { @@ -526,7 +525,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { if (output) { apply_output_transform(&event->x, &event->y, output->transform); } - wlr_signal_emit_safe(&device->cursor->events.touch_down, event); + wl_signal_emit_mutable(&device->cursor->events.touch_down, event); } static void handle_touch_motion(struct wl_listener *listener, void *data) { @@ -539,20 +538,20 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) { if (output) { apply_output_transform(&event->x, &event->y, output->transform); } - wlr_signal_emit_safe(&device->cursor->events.touch_motion, event); + wl_signal_emit_mutable(&device->cursor->events.touch_motion, event); } static void handle_touch_cancel(struct wl_listener *listener, void *data) { struct wlr_touch_cancel_event *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, touch_cancel); - wlr_signal_emit_safe(&device->cursor->events.touch_cancel, event); + wl_signal_emit_mutable(&device->cursor->events.touch_cancel, event); } static void handle_touch_frame(struct wl_listener *listener, void *data) { struct wlr_cursor_device *device = wl_container_of(listener, device, touch_frame); - wlr_signal_emit_safe(&device->cursor->events.touch_frame, NULL); + wl_signal_emit_mutable(&device->cursor->events.touch_frame, NULL); } static void handle_tablet_tool_tip(struct wl_listener *listener, void *data) { @@ -565,7 +564,7 @@ static void handle_tablet_tool_tip(struct wl_listener *listener, void *data) { if (output) { apply_output_transform(&event->x, &event->y, output->transform); } - wlr_signal_emit_safe(&device->cursor->events.tablet_tool_tip, event); + wl_signal_emit_mutable(&device->cursor->events.tablet_tool_tip, event); } static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { @@ -600,7 +599,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) { } } - wlr_signal_emit_safe(&device->cursor->events.tablet_tool_axis, event); + wl_signal_emit_mutable(&device->cursor->events.tablet_tool_axis, event); } static void handle_tablet_tool_button(struct wl_listener *listener, @@ -608,7 +607,7 @@ static void handle_tablet_tool_button(struct wl_listener *listener, struct wlr_tablet_tool_button *event = data; struct wlr_cursor_device *device; device = wl_container_of(listener, device, tablet_tool_button); - wlr_signal_emit_safe(&device->cursor->events.tablet_tool_button, event); + wl_signal_emit_mutable(&device->cursor->events.tablet_tool_button, event); } static void handle_tablet_tool_proximity(struct wl_listener *listener, @@ -622,7 +621,7 @@ static void handle_tablet_tool_proximity(struct wl_listener *listener, if (output) { apply_output_transform(&event->x, &event->y, output->transform); } - wlr_signal_emit_safe(&device->cursor->events.tablet_tool_proximity, event); + wl_signal_emit_mutable(&device->cursor->events.tablet_tool_proximity, event); } static void handle_device_destroy(struct wl_listener *listener, void *data) { diff --git a/types/wlr_damage_ring.c b/types/wlr_damage_ring.c index 378051c7a..000aba935 100644 --- a/types/wlr_damage_ring.c +++ b/types/wlr_damage_ring.c @@ -4,7 +4,6 @@ #include #include #include -#include "util/signal.h" #define WLR_DAMAGE_RING_MAX_RECTS 20 diff --git a/types/wlr_data_control_v1.c b/types/wlr_data_control_v1.c index 239e238ad..55789d4dc 100644 --- a/types/wlr_data_control_v1.c +++ b/types/wlr_data_control_v1.c @@ -7,7 +7,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-data-control-unstable-v1-protocol.h" #define DATA_CONTROL_MANAGER_VERSION 2 @@ -628,7 +627,7 @@ static void manager_handle_get_data_device(struct wl_client *client, &device->seat_set_primary_selection); wl_list_insert(&manager->devices, &device->link); - wlr_signal_emit_safe(&manager->events.new_device, device); + wl_signal_emit_mutable(&manager->events.new_device, device); // At this point maybe the compositor decided to destroy the device. If // it's the case then the resource will be inert. @@ -666,7 +665,7 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_data_control_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_drm.c b/types/wlr_drm.c index 0d50138cc..32eea1c79 100644 --- a/types/wlr_drm.c +++ b/types/wlr_drm.c @@ -11,7 +11,6 @@ #include #include #include "drm-protocol.h" -#include "util/signal.h" #define WLR_DRM_VERSION 2 @@ -172,7 +171,7 @@ static void drm_bind(struct wl_client *client, void *data, } static void drm_destroy(struct wlr_drm *drm) { - wlr_signal_emit_safe(&drm->events.destroy, NULL); + wl_signal_emit_mutable(&drm->events.destroy, NULL); wl_list_remove(&drm->display_destroy.link); wl_list_remove(&drm->renderer_destroy.link); diff --git a/types/wlr_drm_lease_v1.c b/types/wlr_drm_lease_v1.c index 0ef9e0365..315c5ff9f 100644 --- a/types/wlr_drm_lease_v1.c +++ b/types/wlr_drm_lease_v1.c @@ -9,7 +9,6 @@ #include #include "backend/drm/drm.h" #include "drm-lease-v1-protocol.h" -#include "util/signal.h" #include "util/global.h" #define DRM_LEASE_DEVICE_V1_VERSION 1 @@ -353,7 +352,7 @@ static void drm_lease_request_v1_handle_submit( request->lease = lease; /* TODO: reject the request if the user does not grant it */ - wlr_signal_emit_safe(&request->device->manager->events.request, + wl_signal_emit_mutable(&request->device->manager->events.request, request); /* Request is done */ diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c index b47758c63..c1d26e604 100644 --- a/types/wlr_export_dmabuf_v1.c +++ b/types/wlr_export_dmabuf_v1.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-export-dmabuf-unstable-v1-protocol.h" #define EXPORT_DMABUF_MANAGER_VERSION 1 @@ -182,7 +181,7 @@ static void manager_bind(struct wl_client *client, void *data, uint32_t version, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_export_dmabuf_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_foreign_toplevel_management_v1.c b/types/wlr_foreign_toplevel_management_v1.c index a700a115b..c6fea5b7f 100644 --- a/types/wlr_foreign_toplevel_management_v1.c +++ b/types/wlr_foreign_toplevel_management_v1.c @@ -7,7 +7,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-foreign-toplevel-management-unstable-v1-protocol.h" #define FOREIGN_TOPLEVEL_MANAGEMENT_V1_VERSION 3 @@ -33,7 +32,7 @@ static void toplevel_handle_send_maximized_event(struct wl_resource *resource, .toplevel = toplevel, .maximized = state, }; - wlr_signal_emit_safe(&toplevel->events.request_maximize, &event); + wl_signal_emit_mutable(&toplevel->events.request_maximize, &event); } static void foreign_toplevel_handle_set_maximized(struct wl_client *client, @@ -58,7 +57,7 @@ static void toplevel_send_minimized_event(struct wl_resource *resource, .toplevel = toplevel, .minimized = state, }; - wlr_signal_emit_safe(&toplevel->events.request_minimize, &event); + wl_signal_emit_mutable(&toplevel->events.request_minimize, &event); } static void foreign_toplevel_handle_set_minimized(struct wl_client *client, @@ -88,7 +87,7 @@ static void toplevel_send_fullscreen_event(struct wl_resource *resource, .fullscreen = state, .output = output, }; - wlr_signal_emit_safe(&toplevel->events.request_fullscreen, &event); + wl_signal_emit_mutable(&toplevel->events.request_fullscreen, &event); } static void foreign_toplevel_handle_set_fullscreen(struct wl_client *client, @@ -117,7 +116,7 @@ static void foreign_toplevel_handle_activate(struct wl_client *client, .toplevel = toplevel, .seat = seat_client->seat, }; - wlr_signal_emit_safe(&toplevel->events.request_activate, &event); + wl_signal_emit_mutable(&toplevel->events.request_activate, &event); } static void foreign_toplevel_handle_close(struct wl_client *client, @@ -127,7 +126,7 @@ static void foreign_toplevel_handle_close(struct wl_client *client, if (!toplevel) { return; } - wlr_signal_emit_safe(&toplevel->events.request_close, toplevel); + wl_signal_emit_mutable(&toplevel->events.request_close, toplevel); } static void foreign_toplevel_handle_set_rectangle(struct wl_client *client, @@ -154,7 +153,7 @@ static void foreign_toplevel_handle_set_rectangle(struct wl_client *client, .width = width, .height = height, }; - wlr_signal_emit_safe(&toplevel->events.set_rectangle, &event); + wl_signal_emit_mutable(&toplevel->events.set_rectangle, &event); } static void foreign_toplevel_handle_destroy(struct wl_client *client, @@ -495,7 +494,7 @@ void wlr_foreign_toplevel_handle_v1_destroy( return; } - wlr_signal_emit_safe(&toplevel->events.destroy, toplevel); + wl_signal_emit_mutable(&toplevel->events.destroy, toplevel); struct wl_resource *resource, *tmp; wl_resource_for_each_safe(resource, tmp, &toplevel->resources) { @@ -678,7 +677,7 @@ static void foreign_toplevel_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_foreign_toplevel_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_fullscreen_shell_v1.c b/types/wlr_fullscreen_shell_v1.c index 7e9f85539..4d4ded482 100644 --- a/types/wlr_fullscreen_shell_v1.c +++ b/types/wlr_fullscreen_shell_v1.c @@ -4,7 +4,6 @@ #include #include #include -#include "util/signal.h" #define FULLSCREEN_SHELL_VERSION 1 @@ -37,7 +36,7 @@ static void shell_handle_present_surface(struct wl_client *client, .method = method, .output = output, }; - wlr_signal_emit_safe(&shell->events.present_surface, &event); + wl_signal_emit_mutable(&shell->events.present_surface, &event); } static void shell_handle_present_surface_for_mode(struct wl_client *client, @@ -79,7 +78,7 @@ static void shell_bind(struct wl_client *client, void *data, uint32_t version, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_fullscreen_shell_v1 *shell = wl_container_of(listener, shell, display_destroy); - wlr_signal_emit_safe(&shell->events.destroy, shell); + wl_signal_emit_mutable(&shell->events.destroy, shell); wl_list_remove(&shell->display_destroy.link); wl_global_destroy(shell->global); free(shell); diff --git a/types/wlr_gamma_control_v1.c b/types/wlr_gamma_control_v1.c index 095b4a6f4..009a42a52 100644 --- a/types/wlr_gamma_control_v1.c +++ b/types/wlr_gamma_control_v1.c @@ -7,7 +7,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-gamma-control-unstable-v1-protocol.h" #define GAMMA_CONTROL_MANAGER_V1_VERSION 1 @@ -259,7 +258,7 @@ static void gamma_control_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_idle.c b/types/wlr_idle.c index 4c338931c..cb3a1cc38 100644 --- a/types/wlr_idle.c +++ b/types/wlr_idle.c @@ -5,7 +5,6 @@ #include #include #include "idle-protocol.h" -#include "util/signal.h" static const struct org_kde_kwin_idle_timeout_interface idle_timeout_impl; @@ -22,7 +21,7 @@ static int idle_notify(void *data) { return 0; } timer->idle_state = true; - wlr_signal_emit_safe(&timer->events.idle, timer); + wl_signal_emit_mutable(&timer->events.idle, timer); if (timer->resource) { org_kde_kwin_idle_timeout_send_idle(timer->resource); @@ -38,7 +37,7 @@ static void handle_activity(struct wlr_idle_timeout *timer) { // in case the previous state was sleeping send a resume event and switch state if (timer->idle_state) { timer->idle_state = false; - wlr_signal_emit_safe(&timer->events.resume, timer); + wl_signal_emit_mutable(&timer->events.resume, timer); if (timer->resource) { org_kde_kwin_idle_timeout_send_resumed(timer->resource); @@ -212,7 +211,7 @@ static void idle_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_idle *idle = wl_container_of(listener, idle, display_destroy); - wlr_signal_emit_safe(&idle->events.destroy, idle); + wl_signal_emit_mutable(&idle->events.destroy, idle); wl_list_remove(&idle->display_destroy.link); wl_global_destroy(idle->global); free(idle); @@ -249,7 +248,7 @@ struct wlr_idle *wlr_idle_create(struct wl_display *display) { } void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat) { - wlr_signal_emit_safe(&idle->events.activity_notify, seat); + wl_signal_emit_mutable(&idle->events.activity_notify, seat); } struct wlr_idle_timeout *wlr_idle_timeout_create(struct wlr_idle *idle, @@ -258,7 +257,7 @@ struct wlr_idle_timeout *wlr_idle_timeout_create(struct wlr_idle *idle, } void wlr_idle_timeout_destroy(struct wlr_idle_timeout *timer) { - wlr_signal_emit_safe(&timer->events.destroy, NULL); + wl_signal_emit_mutable(&timer->events.destroy, NULL); wl_list_remove(&timer->input_listener.link); wl_list_remove(&timer->seat_destroy.link); diff --git a/types/wlr_idle_inhibit_v1.c b/types/wlr_idle_inhibit_v1.c index 61a66dc1f..7369643e3 100644 --- a/types/wlr_idle_inhibit_v1.c +++ b/types/wlr_idle_inhibit_v1.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -33,7 +32,7 @@ static void idle_inhibitor_v1_destroy(struct wlr_idle_inhibitor_v1 *inhibitor) { return; } - wlr_signal_emit_safe(&inhibitor->events.destroy, inhibitor->surface); + wl_signal_emit_mutable(&inhibitor->events.destroy, inhibitor->surface); wl_resource_set_user_data(inhibitor->resource, NULL); wl_list_remove(&inhibitor->link); @@ -98,7 +97,7 @@ static void manager_handle_create_inhibitor(struct wl_client *client, inhibitor, idle_inhibitor_v1_handle_resource_destroy); wl_list_insert(&manager->inhibitors, &inhibitor->link); - wlr_signal_emit_safe(&manager->events.new_inhibitor, inhibitor); + wl_signal_emit_mutable(&manager->events.new_inhibitor, inhibitor); } static void manager_handle_destroy(struct wl_client *client, @@ -114,7 +113,7 @@ static const struct zwp_idle_inhibit_manager_v1_interface idle_inhibit_impl = { static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_idle_inhibit_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_input_device.c b/types/wlr_input_device.c index 87cc64b8e..21916d699 100644 --- a/types/wlr_input_device.c +++ b/types/wlr_input_device.c @@ -3,7 +3,6 @@ #include #include #include "interfaces/wlr_input_device.h" -#include "util/signal.h" void wlr_input_device_init(struct wlr_input_device *dev, enum wlr_input_device_type type, const char *name) { @@ -21,7 +20,7 @@ void wlr_input_device_finish(struct wlr_input_device *wlr_device) { return; } - wlr_signal_emit_safe(&wlr_device->events.destroy, wlr_device); + wl_signal_emit_mutable(&wlr_device->events.destroy, wlr_device); wl_list_remove(&wlr_device->events.destroy.listener_list); diff --git a/types/wlr_input_inhibitor.c b/types/wlr_input_inhibitor.c index 55b141753..c6fbb5af7 100644 --- a/types/wlr_input_inhibitor.c +++ b/types/wlr_input_inhibitor.c @@ -4,7 +4,6 @@ #include #include "wlr/types/wlr_input_inhibitor.h" #include "wlr-input-inhibitor-unstable-v1-protocol.h" -#include "util/signal.h" static const struct zwlr_input_inhibit_manager_v1_interface inhibit_manager_implementation; static const struct zwlr_input_inhibitor_v1_interface input_inhibitor_implementation; @@ -27,7 +26,7 @@ static void input_inhibit_manager_deactivate( } manager->active_client = NULL; manager->active_inhibitor = NULL; - wlr_signal_emit_safe(&manager->events.deactivate, manager); + wl_signal_emit_mutable(&manager->events.deactivate, manager); } static void input_inhibitor_destroy(struct wl_client *client, @@ -71,7 +70,7 @@ static void inhibit_manager_get_inhibitor(struct wl_client *client, manager->active_client = client; manager->active_inhibitor = wl_resource; - wlr_signal_emit_safe(&manager->events.activate, manager); + wl_signal_emit_mutable(&manager->events.activate, manager); } static const struct zwlr_input_inhibit_manager_v1_interface inhibit_manager_implementation = { @@ -106,7 +105,7 @@ static void inhibit_manager_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_input_inhibit_manager *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_input_method_v2.c b/types/wlr_input_method_v2.c index 4a436e41d..6d2e49f98 100644 --- a/types/wlr_input_method_v2.c +++ b/types/wlr_input_method_v2.c @@ -12,7 +12,6 @@ #include #include "input-method-unstable-v2-protocol.h" #include "util/shm.h" -#include "util/signal.h" static const struct zwp_input_method_v2_interface input_method_impl; static const struct zwp_input_method_keyboard_grab_v2_interface keyboard_grab_impl; @@ -41,7 +40,7 @@ static void input_method_destroy(struct wlr_input_method_v2 *input_method) { popup_surface, tmp, &input_method->popup_surfaces, link) { popup_surface_destroy(popup_surface); } - wlr_signal_emit_safe(&input_method->events.destroy, input_method); + wl_signal_emit_mutable(&input_method->events.destroy, input_method); wl_list_remove(wl_resource_get_link(input_method->resource)); wl_list_remove(&input_method->seat_client_destroy.link); wlr_input_method_keyboard_grab_v2_destroy(input_method->keyboard_grab); @@ -76,7 +75,7 @@ static void im_commit(struct wl_client *client, struct wl_resource *resource, input_method->current_serial = serial; struct wlr_input_method_v2_state default_state = {0}; input_method->pending = default_state; - wlr_signal_emit_safe(&input_method->events.commit, (void*)input_method); + wl_signal_emit_mutable(&input_method->events.commit, (void*)input_method); } static void im_commit_string(struct wl_client *client, @@ -141,10 +140,10 @@ static void popup_surface_set_mapped( struct wlr_input_popup_surface_v2 *popup_surface, bool mapped) { if (mapped && !popup_surface->mapped) { popup_surface->mapped = true; - wlr_signal_emit_safe(&popup_surface->events.map, popup_surface); + wl_signal_emit_mutable(&popup_surface->events.map, popup_surface); } else if (!mapped && popup_surface->mapped) { popup_surface->mapped = false; - wlr_signal_emit_safe(&popup_surface->events.unmap, popup_surface); + wl_signal_emit_mutable(&popup_surface->events.unmap, popup_surface); } } @@ -182,7 +181,7 @@ bool wlr_surface_is_input_popup_surface_v2(struct wlr_surface *surface) { static void popup_surface_destroy( struct wlr_input_popup_surface_v2 *popup_surface) { popup_surface_set_mapped(popup_surface, false); - wlr_signal_emit_safe(&popup_surface->events.destroy, NULL); + wl_signal_emit_mutable(&popup_surface->events.destroy, NULL); wl_list_remove(&popup_surface->surface_destroy.link); wl_list_remove(&popup_surface->link); wl_resource_set_user_data(popup_surface->resource, NULL); @@ -264,7 +263,7 @@ static void im_get_input_popup_surface(struct wl_client *client, && popup_surface->input_method->client_active); wl_list_insert(&input_method->popup_surfaces, &popup_surface->link); - wlr_signal_emit_safe(&input_method->events.new_popup_surface, popup_surface); + wl_signal_emit_mutable(&input_method->events.new_popup_surface, popup_surface); } void wlr_input_method_keyboard_grab_v2_destroy( @@ -272,7 +271,7 @@ void wlr_input_method_keyboard_grab_v2_destroy( if (!keyboard_grab) { return; } - wlr_signal_emit_safe(&keyboard_grab->events.destroy, keyboard_grab); + wl_signal_emit_mutable(&keyboard_grab->events.destroy, keyboard_grab); keyboard_grab->input_method->keyboard_grab = NULL; if (keyboard_grab->keyboard) { wl_list_remove(&keyboard_grab->keyboard_keymap.link); @@ -452,7 +451,7 @@ static void im_grab_keyboard(struct wl_client *client, keyboard_grab->input_method = input_method; input_method->keyboard_grab = keyboard_grab; wl_signal_init(&keyboard_grab->events.destroy); - wlr_signal_emit_safe(&input_method->events.grab_keyboard, keyboard_grab); + wl_signal_emit_mutable(&input_method->events.grab_keyboard, keyboard_grab); } static const struct zwp_input_method_v2_interface input_method_impl = { @@ -575,7 +574,7 @@ static void manager_get_input_method(struct wl_client *client, input_method->resource = im_resource; wl_list_insert(&im_manager->input_methods, wl_resource_get_link(input_method->resource)); - wlr_signal_emit_safe(&im_manager->events.input_method, input_method); + wl_signal_emit_mutable(&im_manager->events.input_method, input_method); } static void manager_destroy(struct wl_client *client, @@ -607,7 +606,7 @@ static void input_method_manager_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_input_method_manager_v2 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 4d866d007..3fe3ba7a5 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -10,7 +10,6 @@ #include "types/wlr_keyboard.h" #include "util/array.h" #include "util/shm.h" -#include "util/signal.h" #include "util/time.h" struct wlr_keyboard *wlr_keyboard_from_input_device( @@ -91,7 +90,7 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, bool updated = keyboard_modifier_update(keyboard); if (updated) { - wlr_signal_emit_safe(&keyboard->events.modifiers, keyboard); + wl_signal_emit_mutable(&keyboard->events.modifiers, keyboard); } keyboard_led_update(keyboard); @@ -100,7 +99,7 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard, void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, struct wlr_keyboard_key_event *event) { keyboard_key_update(keyboard, event); - wlr_signal_emit_safe(&keyboard->events.key, event); + wl_signal_emit_mutable(&keyboard->events.key, event); if (keyboard->xkb_state == NULL) { return; @@ -114,7 +113,7 @@ void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard, bool updated = keyboard_modifier_update(keyboard); if (updated) { - wlr_signal_emit_safe(&keyboard->events.modifiers, keyboard); + wl_signal_emit_mutable(&keyboard->events.modifiers, keyboard); } keyboard_led_update(keyboard); @@ -246,7 +245,7 @@ bool wlr_keyboard_set_keymap(struct wlr_keyboard *kb, keyboard_modifier_update(kb); - wlr_signal_emit_safe(&kb->events.keymap, kb); + wl_signal_emit_mutable(&kb->events.keymap, kb); return true; err: @@ -266,7 +265,7 @@ void wlr_keyboard_set_repeat_info(struct wlr_keyboard *kb, int32_t rate, } kb->repeat_info.rate = rate; kb->repeat_info.delay = delay; - wlr_signal_emit_safe(&kb->events.repeat_info, kb); + wl_signal_emit_mutable(&kb->events.repeat_info, kb); } uint32_t wlr_keyboard_get_modifiers(struct wlr_keyboard *kb) { diff --git a/types/wlr_keyboard_group.c b/types/wlr_keyboard_group.c index 5261c1416..263545844 100644 --- a/types/wlr_keyboard_group.c +++ b/types/wlr_keyboard_group.c @@ -7,7 +7,6 @@ #include #include #include "types/wlr_keyboard.h" -#include "util/signal.h" #include "wlr/interfaces/wlr_keyboard.h" #include "wlr/types/wlr_keyboard.h" #include "wlr/types/wlr_keyboard_group.h" @@ -212,9 +211,9 @@ static void refresh_state(struct keyboard_group_device *device, // If there are any unique keys, emit the enter/leave event if (keys.size > 0) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - wlr_signal_emit_safe(&device->keyboard->group->events.enter, &keys); + wl_signal_emit_mutable(&device->keyboard->group->events.enter, &keys); } else { - wlr_signal_emit_safe(&device->keyboard->group->events.leave, &keys); + wl_signal_emit_mutable(&device->keyboard->group->events.leave, &keys); } } diff --git a/types/wlr_keyboard_shortcuts_inhibit_v1.c b/types/wlr_keyboard_shortcuts_inhibit_v1.c index 247d350d8..cc9bac14c 100644 --- a/types/wlr_keyboard_shortcuts_inhibit_v1.c +++ b/types/wlr_keyboard_shortcuts_inhibit_v1.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include "keyboard-shortcuts-inhibit-unstable-v1-protocol.h" @@ -35,7 +34,7 @@ static void keyboard_shortcuts_inhibitor_v1_destroy( return; } - wlr_signal_emit_safe(&inhibitor->events.destroy, inhibitor); + wl_signal_emit_mutable(&inhibitor->events.destroy, inhibitor); wl_resource_set_user_data(inhibitor->resource, NULL); wl_list_remove(&inhibitor->link); @@ -144,7 +143,7 @@ static void manager_handle_inhibit_shortcuts(struct wl_client *client, keyboard_shortcuts_inhibitor_v1_handle_resource_destroy); wl_list_insert(&manager->inhibitors, &inhibitor->link); - wlr_signal_emit_safe(&manager->events.new_inhibitor, inhibitor); + wl_signal_emit_mutable(&manager->events.new_inhibitor, inhibitor); } static void manager_handle_destroy(struct wl_client *client, @@ -161,7 +160,7 @@ keyboard_shortcuts_inhibit_impl = { static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_keyboard_shortcuts_inhibit_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index daee6290b..f21ae7999 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -8,7 +8,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-layer-shell-unstable-v1-protocol.h" #define LAYER_SHELL_VERSION 4 @@ -223,7 +222,7 @@ static void layer_surface_handle_get_popup(struct wl_client *client, } popup->parent = parent->surface; wl_list_insert(&parent->popups, &popup->link); - wlr_signal_emit_safe(&parent->events.new_popup, popup); + wl_signal_emit_mutable(&parent->events.new_popup, popup); } static void layer_surface_set_layer(struct wl_client *client, @@ -265,7 +264,7 @@ static void layer_surface_unmap(struct wlr_layer_surface_v1 *surface) { surface->configured = surface->mapped = false; // TODO: probably need to ungrab before this event - wlr_signal_emit_safe(&surface->events.unmap, surface); + wl_signal_emit_mutable(&surface->events.unmap, surface); struct wlr_xdg_popup *popup, *popup_tmp; wl_list_for_each_safe(popup, popup_tmp, &surface->popups, link) { @@ -283,7 +282,7 @@ static void layer_surface_destroy(struct wlr_layer_surface_v1 *surface) { if (surface->configured && surface->mapped) { layer_surface_unmap(surface); } - wlr_signal_emit_safe(&surface->events.destroy, surface); + wl_signal_emit_mutable(&surface->events.destroy, surface); wl_resource_set_user_data(surface->resource, NULL); surface->surface->role_data = NULL; wl_list_remove(&surface->surface_destroy.link); @@ -365,7 +364,7 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { surface->added = true; assert(!surface->configured); assert(!surface->mapped); - wlr_signal_emit_safe(&surface->shell->events.new_surface, surface); + wl_signal_emit_mutable(&surface->shell->events.new_surface, surface); // Return early here as the compositor may have closed this layer surface // in response to the new_surface event. return; @@ -374,7 +373,7 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { if (surface->configured && wlr_surface_has_buffer(surface->surface) && !surface->mapped) { surface->mapped = true; - wlr_signal_emit_safe(&surface->events.map, surface); + wl_signal_emit_mutable(&surface->events.map, surface); } } @@ -501,7 +500,7 @@ static void layer_shell_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_layer_shell_v1 *layer_shell = wl_container_of(listener, layer_shell, display_destroy); - wlr_signal_emit_safe(&layer_shell->events.destroy, layer_shell); + wl_signal_emit_mutable(&layer_shell->events.destroy, layer_shell); wl_list_remove(&layer_shell->display_destroy.link); wl_global_destroy(layer_shell->global); free(layer_shell); diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index a124d5212..7480b9e19 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -11,7 +11,6 @@ #include #include "linux-dmabuf-unstable-v1-protocol.h" #include "render/drm_format_set.h" -#include "util/signal.h" #include "util/shm.h" #define LINUX_DMABUF_VERSION 4 @@ -887,7 +886,7 @@ static void linux_dmabuf_bind(struct wl_client *client, void *data, } static void linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) { - wlr_signal_emit_safe(&linux_dmabuf->events.destroy, linux_dmabuf); + wl_signal_emit_mutable(&linux_dmabuf->events.destroy, linux_dmabuf); struct wlr_linux_dmabuf_v1_surface *surface, *surface_tmp; wl_list_for_each_safe(surface, surface_tmp, &linux_dmabuf->surfaces, link) { diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index 0dfc30ca0..8254f65e9 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -5,7 +5,6 @@ #include #include #include -#include "util/signal.h" static void output_handle_destroy(struct wl_listener *listener, void *data) { struct wlr_output_damage *output_damage = @@ -41,7 +40,7 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { return; } - wlr_signal_emit_safe(&output_damage->events.frame, output_damage); + wl_signal_emit_mutable(&output_damage->events.frame, output_damage); } static void output_handle_precommit(struct wl_listener *listener, void *data) { @@ -128,7 +127,7 @@ void wlr_output_damage_destroy(struct wlr_output_damage *output_damage) { if (output_damage == NULL) { return; } - wlr_signal_emit_safe(&output_damage->events.destroy, output_damage); + wl_signal_emit_mutable(&output_damage->events.destroy, output_damage); wl_list_remove(&output_damage->output_destroy.link); wl_list_remove(&output_damage->output_mode.link); wl_list_remove(&output_damage->output_needs_frame.link); diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index ef6e2850c..319b7cf78 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" struct wlr_output_layout_output_state { struct wlr_output_layout *layout; @@ -37,7 +36,7 @@ struct wlr_output_layout *wlr_output_layout_create(void) { static void output_layout_output_destroy( struct wlr_output_layout_output *l_output) { - wlr_signal_emit_safe(&l_output->events.destroy, l_output); + wl_signal_emit_mutable(&l_output->events.destroy, l_output); wlr_output_destroy_global(l_output->output); wl_list_remove(&l_output->state->mode.link); wl_list_remove(&l_output->state->commit.link); @@ -52,7 +51,7 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) { return; } - wlr_signal_emit_safe(&layout->events.destroy, layout); + wl_signal_emit_mutable(&layout->events.destroy, layout); struct wlr_output_layout_output *l_output, *temp; wl_list_for_each_safe(l_output, temp, &layout->outputs, link) { @@ -115,7 +114,7 @@ static void output_layout_reconfigure(struct wlr_output_layout *layout) { max_x += output_box.width; } - wlr_signal_emit_safe(&layout->events.change, layout); + wl_signal_emit_mutable(&layout->events.change, layout); } static void output_update_global(struct wlr_output *output) { @@ -211,7 +210,7 @@ void wlr_output_layout_add(struct wlr_output_layout *layout, output_update_global(output); if (is_new) { - wlr_signal_emit_safe(&layout->events.add, l_output); + wl_signal_emit_mutable(&layout->events.add, l_output); } } @@ -425,7 +424,7 @@ void wlr_output_layout_add_auto(struct wlr_output_layout *layout, output_update_global(output); if (is_new) { - wlr_signal_emit_safe(&layout->events.add, l_output); + wl_signal_emit_mutable(&layout->events.add, l_output); } } diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index c44352f17..64eff211f 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -3,7 +3,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-output-management-unstable-v1-protocol.h" #define OUTPUT_MANAGER_VERSION 2 @@ -413,7 +412,7 @@ static void config_handle_apply(struct wl_client *client, return; } - wlr_signal_emit_safe(&config->manager->events.apply, config); + wl_signal_emit_mutable(&config->manager->events.apply, config); } static void config_handle_test(struct wl_client *client, @@ -432,7 +431,7 @@ static void config_handle_test(struct wl_client *client, return; } - wlr_signal_emit_safe(&config->manager->events.test, config); + wl_signal_emit_mutable(&config->manager->events.test, config); } static void config_handle_destroy(struct wl_client *client, @@ -589,7 +588,7 @@ static void manager_handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_output_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); struct wlr_output_head_v1 *head, *tmp; wl_list_for_each_safe(head, tmp, &manager->heads, link) { diff --git a/types/wlr_output_power_management_v1.c b/types/wlr_output_power_management_v1.c index e607eb161..7e4d1b3f7 100644 --- a/types/wlr_output_power_management_v1.c +++ b/types/wlr_output_power_management_v1.c @@ -7,7 +7,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-output-power-management-unstable-v1-protocol.h" #define OUTPUT_POWER_MANAGER_V1_VERSION 1 @@ -93,7 +92,7 @@ static void output_power_handle_set_mode(struct wl_client *client, .output = output_power->output, .mode = mode, }; - wlr_signal_emit_safe(&output_power->manager->events.set_mode, &event); + wl_signal_emit_mutable(&output_power->manager->events.set_mode, &event); } static const struct zwlr_output_power_v1_interface output_power_impl = { @@ -196,7 +195,7 @@ static void output_power_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_output_power_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_global_destroy(manager->global); free(manager); } diff --git a/types/wlr_pointer_constraints_v1.c b/types/wlr_pointer_constraints_v1.c index e90daf72e..7a8d209bc 100644 --- a/types/wlr_pointer_constraints_v1.c +++ b/types/wlr_pointer_constraints_v1.c @@ -9,7 +9,6 @@ #include #include #include -#include "util/signal.h" static const struct zwp_locked_pointer_v1_interface locked_pointer_impl; static const struct zwp_confined_pointer_v1_interface confined_pointer_impl; @@ -47,7 +46,7 @@ static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constra wlr_log(WLR_DEBUG, "destroying constraint %p", constraint); - wlr_signal_emit_safe(&constraint->events.destroy, constraint); + wl_signal_emit_mutable(&constraint->events.destroy, constraint); wl_resource_set_user_data(constraint->resource, NULL); wl_list_remove(&constraint->link); @@ -130,7 +129,7 @@ static void pointer_constraint_commit( } if (updated_region) { - wlr_signal_emit_safe(&constraint->events.set_region, NULL); + wl_signal_emit_mutable(&constraint->events.set_region, NULL); } } @@ -246,7 +245,7 @@ static void pointer_constraint_create(struct wl_client *client, wl_list_insert(&pointer_constraints->constraints, &constraint->link); - wlr_signal_emit_safe(&pointer_constraints->events.new_constraint, + wl_signal_emit_mutable(&pointer_constraints->events.new_constraint, constraint); } diff --git a/types/wlr_pointer_gestures_v1.c b/types/wlr_pointer_gestures_v1.c index b3f874c95..9089b4806 100644 --- a/types/wlr_pointer_gestures_v1.c +++ b/types/wlr_pointer_gestures_v1.c @@ -9,7 +9,6 @@ #include #include #include -#include "util/signal.h" #include "pointer-gestures-unstable-v1-protocol.h" #define POINTER_GESTURES_VERSION 3 diff --git a/types/wlr_presentation_time.c b/types/wlr_presentation_time.c index a6facbdbe..115315315 100644 --- a/types/wlr_presentation_time.c +++ b/types/wlr_presentation_time.c @@ -7,7 +7,6 @@ #include #include #include "presentation-time-protocol.h" -#include "util/signal.h" #define PRESENTATION_VERSION 1 @@ -173,7 +172,7 @@ static void presentation_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_presentation *presentation = wl_container_of(listener, presentation, display_destroy); - wlr_signal_emit_safe(&presentation->events.destroy, presentation); + wl_signal_emit_mutable(&presentation->events.destroy, presentation); wl_list_remove(&presentation->display_destroy.link); wl_global_destroy(presentation->global); free(presentation); diff --git a/types/wlr_primary_selection.c b/types/wlr_primary_selection.c index 21784aae7..d576bf0a4 100644 --- a/types/wlr_primary_selection.c +++ b/types/wlr_primary_selection.c @@ -2,7 +2,6 @@ #include #include #include -#include "util/signal.h" void wlr_primary_selection_source_init( struct wlr_primary_selection_source *source, @@ -20,7 +19,7 @@ void wlr_primary_selection_source_destroy( return; } - wlr_signal_emit_safe(&source->events.destroy, source); + wl_signal_emit_mutable(&source->events.destroy, source); char **p; wl_array_for_each(p, &source->mime_types) { @@ -63,7 +62,7 @@ void wlr_seat_request_set_primary_selection(struct wlr_seat *seat, .source = source, .serial = serial, }; - wlr_signal_emit_safe(&seat->events.request_set_primary_selection, &event); + wl_signal_emit_mutable(&seat->events.request_set_primary_selection, &event); } static void seat_handle_primary_selection_source_destroy( @@ -72,7 +71,7 @@ static void seat_handle_primary_selection_source_destroy( wl_container_of(listener, seat, primary_selection_source_destroy); wl_list_remove(&seat->primary_selection_source_destroy.link); seat->primary_selection_source = NULL; - wlr_signal_emit_safe(&seat->events.set_primary_selection, seat); + wl_signal_emit_mutable(&seat->events.set_primary_selection, seat); } void wlr_seat_set_primary_selection(struct wlr_seat *seat, @@ -98,5 +97,5 @@ void wlr_seat_set_primary_selection(struct wlr_seat *seat, &seat->primary_selection_source_destroy); } - wlr_signal_emit_safe(&seat->events.set_primary_selection, seat); + wl_signal_emit_mutable(&seat->events.set_primary_selection, seat); } diff --git a/types/wlr_primary_selection_v1.c b/types/wlr_primary_selection_v1.c index 009b09557..511d5ddb9 100644 --- a/types/wlr_primary_selection_v1.c +++ b/types/wlr_primary_selection_v1.c @@ -9,7 +9,6 @@ #include #include #include "primary-selection-unstable-v1-protocol.h" -#include "util/signal.h" #define DEVICE_MANAGER_VERSION 1 @@ -458,7 +457,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { device_destroy(device); } - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index 50871b51e..44da791f7 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,7 @@ static struct wlr_relative_pointer_manager_v1 *relative_pointer_manager_from_res } static void relative_pointer_destroy(struct wlr_relative_pointer_v1 *relative_pointer) { - wlr_signal_emit_safe(&relative_pointer->events.destroy, relative_pointer); + wl_signal_emit_mutable(&relative_pointer->events.destroy, relative_pointer); wl_list_remove(&relative_pointer->link); wl_list_remove(&relative_pointer->seat_destroy.link); @@ -118,7 +117,7 @@ static void relative_pointer_manager_v1_handle_get_relative_pointer(struct wl_cl &relative_pointer->pointer_destroy); relative_pointer->pointer_destroy.notify = relative_pointer_handle_pointer_destroy; - wlr_signal_emit_safe(&manager->events.new_relative_pointer, + wl_signal_emit_mutable(&manager->events.new_relative_pointer, relative_pointer); } @@ -140,7 +139,7 @@ static void relative_pointer_manager_v1_bind(struct wl_client *wl_client, void * static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_relative_pointer_manager_v1 *manager = wl_container_of(listener, manager, display_destroy_listener); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy_listener.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index 0b48fe3f4..30e529a9a 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -12,7 +12,6 @@ #include #include "wlr-screencopy-unstable-v1-protocol.h" #include "render/pixel_format.h" -#include "util/signal.h" #define SCREENCOPY_MANAGER_VERSION 3 @@ -680,7 +679,7 @@ failure: static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_screencopy_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_server_decoration.c b/types/wlr_server_decoration.c index a80793939..425230ec3 100644 --- a/types/wlr_server_decoration.c +++ b/types/wlr_server_decoration.c @@ -4,7 +4,6 @@ #include #include #include "server-decoration-protocol.h" -#include "util/signal.h" static const struct org_kde_kwin_server_decoration_interface server_decoration_impl; @@ -29,14 +28,14 @@ static void server_decoration_handle_request_mode(struct wl_client *client, return; } decoration->mode = mode; - wlr_signal_emit_safe(&decoration->events.mode, decoration); + wl_signal_emit_mutable(&decoration->events.mode, decoration); org_kde_kwin_server_decoration_send_mode(decoration->resource, decoration->mode); } static void server_decoration_destroy( struct wlr_server_decoration *decoration) { - wlr_signal_emit_safe(&decoration->events.destroy, decoration); + wl_signal_emit_mutable(&decoration->events.destroy, decoration); wl_list_remove(&decoration->surface_destroy_listener.link); wl_resource_set_user_data(decoration->resource, NULL); wl_list_remove(&decoration->link); @@ -119,7 +118,7 @@ static void server_decoration_manager_handle_create(struct wl_client *client, org_kde_kwin_server_decoration_send_mode(decoration->resource, decoration->mode); - wlr_signal_emit_safe(&manager->events.new_decoration, decoration); + wl_signal_emit_mutable(&manager->events.new_decoration, decoration); } static const struct org_kde_kwin_server_decoration_manager_interface @@ -166,7 +165,7 @@ static void server_decoration_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_server_decoration_manager *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_session_lock_v1.c b/types/wlr_session_lock_v1.c index ffba20614..294b4a872 100644 --- a/types/wlr_session_lock_v1.c +++ b/types/wlr_session_lock_v1.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" #include "ext-session-lock-v1-protocol.h" #define SESSION_LOCK_VERSION 1 @@ -157,7 +156,7 @@ static void lock_surface_role_commit(struct wlr_surface *surface) { if (!lock_surface->mapped) { lock_surface->mapped = true; - wlr_signal_emit_safe(&lock_surface->events.map, NULL); + wl_signal_emit_mutable(&lock_surface->events.map, NULL); } } @@ -185,7 +184,7 @@ static const struct wlr_surface_role lock_surface_role = { static void lock_surface_destroy( struct wlr_session_lock_surface_v1 *lock_surface) { - wlr_signal_emit_safe(&lock_surface->events.destroy, NULL); + wl_signal_emit_mutable(&lock_surface->events.destroy, NULL); wl_list_remove(&lock_surface->link); @@ -312,7 +311,7 @@ static void lock_handle_get_lock_surface(struct wl_client *client, wl_signal_add(&surface->events.destroy, &lock_surface->surface_destroy); lock_surface->surface_destroy.notify = lock_surface_handle_surface_destroy; - wlr_signal_emit_safe(&lock->events.new_surface, lock_surface); + wl_signal_emit_mutable(&lock->events.new_surface, lock_surface); } static void lock_handle_unlock_and_destroy(struct wl_client *client, @@ -322,7 +321,7 @@ static void lock_handle_unlock_and_destroy(struct wl_client *client, return; } - wlr_signal_emit_safe(&lock->events.unlock, NULL); + wl_signal_emit_mutable(&lock->events.unlock, NULL); wl_resource_destroy(lock_resource); } @@ -344,7 +343,7 @@ static void lock_destroy(struct wlr_session_lock_v1 *lock) { } assert(wl_list_empty(&lock->surfaces)); - wlr_signal_emit_safe(&lock->events.destroy, NULL); + wl_signal_emit_mutable(&lock->events.destroy, NULL); assert(wl_list_empty(&lock->events.new_surface.listener_list)); assert(wl_list_empty(&lock->events.unlock.listener_list)); @@ -395,7 +394,7 @@ static void lock_manager_handle_lock(struct wl_client *client, wl_resource_set_implementation(lock->resource, &lock_implementation, lock, lock_resource_destroy); - wlr_signal_emit_safe(&lock_manager->events.new_lock, lock); + wl_signal_emit_mutable(&lock_manager->events.new_lock, lock); } static const struct ext_session_lock_manager_v1_interface lock_manager_implementation = { @@ -420,7 +419,7 @@ static void lock_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_session_lock_manager_v1 *lock_manager = wl_container_of(listener, lock_manager, display_destroy); - wlr_signal_emit_safe(&lock_manager->events.destroy, NULL); + wl_signal_emit_mutable(&lock_manager->events.destroy, NULL); wl_list_remove(&lock_manager->display_destroy.link); wl_global_destroy(lock_manager->global); diff --git a/types/wlr_subcompositor.c b/types/wlr_subcompositor.c index 75902cac5..530f74765 100644 --- a/types/wlr_subcompositor.c +++ b/types/wlr_subcompositor.c @@ -4,7 +4,6 @@ #include #include #include "types/wlr_region.h" -#include "util/signal.h" #define SUBCOMPOSITOR_VERSION 1 @@ -37,7 +36,7 @@ static void subsurface_destroy(struct wlr_subsurface *subsurface) { subsurface_unmap(subsurface); - wlr_signal_emit_safe(&subsurface->events.destroy, subsurface); + wl_signal_emit_mutable(&subsurface->events.destroy, subsurface); wl_list_remove(&subsurface->surface_destroy.link); wl_list_remove(&subsurface->surface_client_commit.link); @@ -230,7 +229,7 @@ static void subsurface_consider_map(struct wlr_subsurface *subsurface, // Now we can map the subsurface subsurface->mapped = true; - wlr_signal_emit_safe(&subsurface->events.map, subsurface); + wl_signal_emit_mutable(&subsurface->events.map, subsurface); // Try mapping all children too struct wlr_subsurface *child; @@ -250,7 +249,7 @@ static void subsurface_unmap(struct wlr_subsurface *subsurface) { } subsurface->mapped = false; - wlr_signal_emit_safe(&subsurface->events.unmap, subsurface); + wl_signal_emit_mutable(&subsurface->events.unmap, subsurface); // Unmap all children struct wlr_subsurface *child; @@ -458,7 +457,7 @@ static void subcompositor_handle_display_destroy( struct wl_listener *listener, void *data) { struct wlr_subcompositor *subcompositor = wl_container_of(listener, subcompositor, display_destroy); - wlr_signal_emit_safe(&subcompositor->events.destroy, NULL); + wl_signal_emit_mutable(&subcompositor->events.destroy, NULL); wl_list_remove(&subcompositor->display_destroy.link); wl_global_destroy(subcompositor->global); free(subcompositor); diff --git a/types/wlr_text_input_v3.c b/types/wlr_text_input_v3.c index 65a8ebd6f..ca06329e6 100644 --- a/types/wlr_text_input_v3.c +++ b/types/wlr_text_input_v3.c @@ -8,7 +8,6 @@ #include #include #include "text-input-unstable-v3-protocol.h" -#include "util/signal.h" static void text_input_clear_focused_surface(struct wlr_text_input_v3 *text_input) { wl_list_remove(&text_input->surface_destroy.link); @@ -66,7 +65,7 @@ void wlr_text_input_v3_send_done(struct wlr_text_input_v3 *text_input) { } static void wlr_text_input_destroy(struct wlr_text_input_v3 *text_input) { - wlr_signal_emit_safe(&text_input->events.destroy, text_input); + wl_signal_emit_mutable(&text_input->events.destroy, text_input); text_input_clear_focused_surface(text_input); wl_list_remove(&text_input->seat_destroy.link); // remove from manager::text_inputs @@ -188,12 +187,12 @@ static void text_input_commit(struct wl_client *client, if (!old_enabled && text_input->current_enabled) { text_input->active_features = text_input->current.features; - wlr_signal_emit_safe(&text_input->events.enable, text_input); + wl_signal_emit_mutable(&text_input->events.enable, text_input); } else if (old_enabled && !text_input->current_enabled) { text_input->active_features = 0; - wlr_signal_emit_safe(&text_input->events.disable, text_input); + wl_signal_emit_mutable(&text_input->events.disable, text_input); } else { // including never enabled - wlr_signal_emit_safe(&text_input->events.commit, text_input); + wl_signal_emit_mutable(&text_input->events.commit, text_input); } } @@ -280,7 +279,7 @@ static void text_input_manager_get_text_input(struct wl_client *client, text_input_manager_from_resource(resource); wl_list_insert(&manager->text_inputs, &text_input->link); - wlr_signal_emit_safe(&manager->events.text_input, text_input); + wl_signal_emit_mutable(&manager->events.text_input, text_input); } static const struct zwp_text_input_manager_v3_interface @@ -307,7 +306,7 @@ static void text_input_manager_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_text_input_manager_v3 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_viewporter.c b/types/wlr_viewporter.c index 097af8576..504390e7e 100644 --- a/types/wlr_viewporter.c +++ b/types/wlr_viewporter.c @@ -3,7 +3,6 @@ #include #include #include -#include "util/signal.h" #include "viewporter-protocol.h" #define VIEWPORTER_VERSION 1 @@ -211,7 +210,7 @@ static void viewporter_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_viewporter *viewporter = wl_container_of(listener, viewporter, display_destroy); - wlr_signal_emit_safe(&viewporter->events.destroy, NULL); + wl_signal_emit_mutable(&viewporter->events.destroy, NULL); wl_global_destroy(viewporter->global); free(viewporter); } diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 2d313575f..9b90ec9fb 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -8,7 +8,6 @@ #include #include #include -#include "util/signal.h" #include "virtual-keyboard-unstable-v1-protocol.h" static const struct wlr_keyboard_impl keyboard_impl = { @@ -176,7 +175,7 @@ static void virtual_keyboard_manager_create_virtual_keyboard( wl_list_insert(&manager->virtual_keyboards, &virtual_keyboard->link); - wlr_signal_emit_safe(&manager->events.new_virtual_keyboard, + wl_signal_emit_mutable(&manager->events.new_virtual_keyboard, virtual_keyboard); } @@ -201,7 +200,7 @@ static void virtual_keyboard_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_virtual_keyboard_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_virtual_pointer_v1.c b/types/wlr_virtual_pointer_v1.c index f1fea0f02..f4dd60c17 100644 --- a/types/wlr_virtual_pointer_v1.c +++ b/types/wlr_virtual_pointer_v1.c @@ -5,7 +5,6 @@ #include #include #include -#include "util/signal.h" #include "wlr-virtual-pointer-unstable-v1-protocol.h" static const struct wlr_pointer_impl pointer_impl = { @@ -37,7 +36,7 @@ static void virtual_pointer_motion(struct wl_client *client, .unaccel_dx = wl_fixed_to_double(dx), .unaccel_dy = wl_fixed_to_double(dy), }; - wlr_signal_emit_safe(&pointer->pointer.events.motion, &event); + wl_signal_emit_mutable(&pointer->pointer.events.motion, &event); } static void virtual_pointer_motion_absolute(struct wl_client *client, @@ -57,7 +56,7 @@ static void virtual_pointer_motion_absolute(struct wl_client *client, .x = (double)x / x_extent, .y = (double)y / y_extent, }; - wlr_signal_emit_safe(&pointer->pointer.events.motion_absolute, &event); + wl_signal_emit_mutable(&pointer->pointer.events.motion_absolute, &event); } static void virtual_pointer_button(struct wl_client *client, @@ -74,7 +73,7 @@ static void virtual_pointer_button(struct wl_client *client, .button = button, .state = state ? WLR_BUTTON_PRESSED : WLR_BUTTON_RELEASED }; - wlr_signal_emit_safe(&pointer->pointer.events.button, &event); + wl_signal_emit_mutable(&pointer->pointer.events.button, &event); } static void virtual_pointer_axis(struct wl_client *client, @@ -112,14 +111,14 @@ static void virtual_pointer_frame(struct wl_client *client, ++i) { if (pointer->axis_valid[i]) { /* Deliver pending axis event */ - wlr_signal_emit_safe(&pointer->pointer.events.axis, + wl_signal_emit_mutable(&pointer->pointer.events.axis, &pointer->axis_event[i]); memset(&pointer->axis_event[i], 0, sizeof(pointer->axis_event[i])); pointer->axis_valid[i] = false; } } - wlr_signal_emit_safe(&pointer->pointer.events.frame, &pointer->pointer); + wl_signal_emit_mutable(&pointer->pointer.events.frame, &pointer->pointer); } static void virtual_pointer_axis_source(struct wl_client *client, @@ -270,7 +269,7 @@ static void virtual_pointer_manager_create_virtual_pointer_with_output( virtual_pointer->resource = pointer_resource; wl_list_insert(&manager->virtual_pointers, &virtual_pointer->link); - wlr_signal_emit_safe(&manager->events.new_virtual_pointer, &event); + wl_signal_emit_mutable(&manager->events.new_virtual_pointer, &event); } static void virtual_pointer_manager_create_virtual_pointer( @@ -308,7 +307,7 @@ static void virtual_pointer_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_virtual_pointer_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); struct wlr_virtual_pointer_v1 *pointer, *pointer_tmp; diff --git a/types/wlr_xdg_activation_v1.c b/types/wlr_xdg_activation_v1.c index c54364ccc..eb8b930c7 100644 --- a/types/wlr_xdg_activation_v1.c +++ b/types/wlr_xdg_activation_v1.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" #include "util/token.h" #include "xdg-activation-v1-protocol.h" @@ -33,7 +32,7 @@ void wlr_xdg_activation_token_v1_destroy( wl_event_source_remove(token->timeout); } - wlr_signal_emit_safe(&token->events.destroy, NULL); + wl_signal_emit_mutable(&token->events.destroy, NULL); wl_list_remove(&token->link); wl_list_remove(&token->seat_destroy.link); @@ -312,7 +311,7 @@ static void activation_handle_activate(struct wl_client *client, .token = token, .surface = surface, }; - wlr_signal_emit_safe(&activation->events.request_activate, &event); + wl_signal_emit_mutable(&activation->events.request_activate, &event); wlr_xdg_activation_token_v1_destroy(token); } @@ -339,7 +338,7 @@ static void activation_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_xdg_activation_v1 *activation = wl_container_of(listener, activation, display_destroy); - wlr_signal_emit_safe(&activation->events.destroy, NULL); + wl_signal_emit_mutable(&activation->events.destroy, NULL); struct wlr_xdg_activation_token_v1 *token, *token_tmp; wl_list_for_each_safe(token, token_tmp, &activation->tokens, link) { diff --git a/types/wlr_xdg_decoration_v1.c b/types/wlr_xdg_decoration_v1.c index d0f969f45..fcd97a5cc 100644 --- a/types/wlr_xdg_decoration_v1.c +++ b/types/wlr_xdg_decoration_v1.c @@ -3,7 +3,6 @@ #include #include #include -#include "util/signal.h" #include "xdg-decoration-unstable-v1-protocol.h" #define DECORATION_MANAGER_VERSION 1 @@ -31,7 +30,7 @@ static void toplevel_decoration_handle_set_mode(struct wl_client *client, decoration->requested_mode = (enum wlr_xdg_toplevel_decoration_v1_mode)mode; - wlr_signal_emit_safe(&decoration->events.request_mode, decoration); + wl_signal_emit_mutable(&decoration->events.request_mode, decoration); } static void toplevel_decoration_handle_unset_mode(struct wl_client *client, @@ -40,7 +39,7 @@ static void toplevel_decoration_handle_unset_mode(struct wl_client *client, toplevel_decoration_from_resource(resource); decoration->requested_mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE; - wlr_signal_emit_safe(&decoration->events.request_mode, decoration); + wl_signal_emit_mutable(&decoration->events.request_mode, decoration); } static const struct zxdg_toplevel_decoration_v1_interface @@ -62,7 +61,7 @@ static void toplevel_decoration_handle_resource_destroy( struct wl_resource *resource) { struct wlr_xdg_toplevel_decoration_v1 *decoration = toplevel_decoration_from_resource(resource); - wlr_signal_emit_safe(&decoration->events.destroy, decoration); + wl_signal_emit_mutable(&decoration->events.destroy, decoration); wl_list_remove(&decoration->surface_commit.link); wl_list_remove(&decoration->surface_destroy.link); wl_list_remove(&decoration->surface_configure.link); @@ -148,7 +147,7 @@ static void toplevel_decoration_handle_surface_commit( if (decoration->surface->added && !decoration->added) { decoration->added = true; - wlr_signal_emit_safe(&manager->events.new_toplevel_decoration, + wl_signal_emit_mutable(&manager->events.new_toplevel_decoration, decoration); } } @@ -232,7 +231,7 @@ static void decoration_manager_handle_get_toplevel_decoration( if (toplevel->base->added) { decoration->added = true; - wlr_signal_emit_safe(&manager->events.new_toplevel_decoration, + wl_signal_emit_mutable(&manager->events.new_toplevel_decoration, decoration); } } @@ -260,7 +259,7 @@ static void decoration_manager_bind(struct wl_client *client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_xdg_decoration_manager_v1 *manager = wl_container_of(listener, manager, display_destroy); - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); diff --git a/types/wlr_xdg_foreign_registry.c b/types/wlr_xdg_foreign_registry.c index 0b75e5932..c27d84069 100644 --- a/types/wlr_xdg_foreign_registry.c +++ b/types/wlr_xdg_foreign_registry.c @@ -1,5 +1,4 @@ #include -#include "util/signal.h" #include "util/token.h" #include #include @@ -38,7 +37,7 @@ struct wlr_xdg_foreign_exported *wlr_xdg_foreign_registry_find_by_handle( } void wlr_xdg_foreign_exported_finish(struct wlr_xdg_foreign_exported *surface) { - wlr_signal_emit_safe(&surface->events.destroy, NULL); + wl_signal_emit_mutable(&surface->events.destroy, NULL); surface->registry = NULL; wl_list_remove(&surface->link); wl_list_init(&surface->link); @@ -49,7 +48,7 @@ static void foreign_registry_handle_display_destroy(struct wl_listener *listener struct wlr_xdg_foreign_registry *registry = wl_container_of(listener, registry, display_destroy); - wlr_signal_emit_safe(®istry->events.destroy, NULL); + wl_signal_emit_mutable(®istry->events.destroy, NULL); // Implementations are supposed to remove all surfaces assert(wl_list_empty(®istry->exported_surfaces)); diff --git a/types/wlr_xdg_foreign_v1.c b/types/wlr_xdg_foreign_v1.c index b6e1c0a26..c9391662c 100644 --- a/types/wlr_xdg_foreign_v1.c +++ b/types/wlr_xdg_foreign_v1.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" #include "xdg-foreign-unstable-v1-protocol.h" #define FOREIGN_V1_VERSION 1 @@ -361,7 +360,7 @@ static void xdg_foreign_destroy(struct wlr_xdg_foreign_v1 *foreign) { return; } - wlr_signal_emit_safe(&foreign->events.destroy, NULL); + wl_signal_emit_mutable(&foreign->events.destroy, NULL); wl_list_remove(&foreign->foreign_registry_destroy.link); wl_list_remove(&foreign->display_destroy.link); diff --git a/types/wlr_xdg_foreign_v2.c b/types/wlr_xdg_foreign_v2.c index 28efff146..8d2567238 100644 --- a/types/wlr_xdg_foreign_v2.c +++ b/types/wlr_xdg_foreign_v2.c @@ -6,7 +6,6 @@ #include #include #include -#include "util/signal.h" #include "xdg-foreign-unstable-v2-protocol.h" #define FOREIGN_V2_VERSION 1 @@ -367,7 +366,7 @@ static void xdg_foreign_destroy(struct wlr_xdg_foreign_v2 *foreign) { return; } - wlr_signal_emit_safe(&foreign->events.destroy, NULL); + wl_signal_emit_mutable(&foreign->events.destroy, NULL); wl_list_remove(&foreign->foreign_registry_destroy.link); wl_list_remove(&foreign->display_destroy.link); diff --git a/types/wlr_xdg_output_v1.c b/types/wlr_xdg_output_v1.c index 8d5fee485..062bf6e63 100644 --- a/types/wlr_xdg_output_v1.c +++ b/types/wlr_xdg_output_v1.c @@ -6,7 +6,6 @@ #include #include #include "xdg-output-unstable-v1-protocol.h" -#include "util/signal.h" #define OUTPUT_MANAGER_VERSION 3 #define OUTPUT_DONE_DEPRECATED_SINCE_VERSION 3 @@ -231,7 +230,7 @@ static void manager_destroy(struct wlr_xdg_output_manager_v1 *manager) { wl_list_for_each_safe(output, tmp, &manager->outputs, link) { output_destroy(output); } - wlr_signal_emit_safe(&manager->events.destroy, manager); + wl_signal_emit_mutable(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); wl_list_remove(&manager->layout_add.link); wl_list_remove(&manager->layout_change.link); diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index adf94c032..d0b83201b 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -2,7 +2,6 @@ #include #include #include "types/wlr_xdg_shell.h" -#include "util/signal.h" void handle_xdg_popup_ack_configure( struct wlr_xdg_popup *popup, @@ -325,7 +324,7 @@ static void xdg_popup_handle_reposition( wlr_xdg_surface_schedule_configure(popup->base); - wlr_signal_emit_safe(&popup->events.reposition, NULL); + wl_signal_emit_mutable(&popup->events.reposition, NULL); } static void xdg_popup_handle_destroy(struct wl_client *client, @@ -419,7 +418,7 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, if (parent) { surface->popup->parent = parent->surface; wl_list_insert(&parent->popups, &surface->popup->link); - wlr_signal_emit_safe(&parent->events.new_popup, surface->popup); + wl_signal_emit_mutable(&parent->events.new_popup, surface->popup); } else { wl_list_init(&surface->popup->link); } diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c index 06d11847f..69c9a6967 100644 --- a/types/xdg_shell/wlr_xdg_shell.c +++ b/types/xdg_shell/wlr_xdg_shell.c @@ -1,7 +1,6 @@ #include #include #include "types/wlr_xdg_shell.h" -#include "util/signal.h" #define WM_BASE_VERSION 5 @@ -84,7 +83,7 @@ static int xdg_client_ping_timeout(void *user_data) { struct wlr_xdg_surface *surface; wl_list_for_each(surface, &client->surfaces, link) { - wlr_signal_emit_safe(&surface->events.ping_timeout, NULL); + wl_signal_emit_mutable(&surface->events.ping_timeout, NULL); } client->ping_serial = 0; @@ -131,7 +130,7 @@ static void xdg_shell_bind(struct wl_client *wl_client, void *data, static void handle_display_destroy(struct wl_listener *listener, void *data) { struct wlr_xdg_shell *xdg_shell = wl_container_of(listener, xdg_shell, display_destroy); - wlr_signal_emit_safe(&xdg_shell->events.destroy, xdg_shell); + wl_signal_emit_mutable(&xdg_shell->events.destroy, xdg_shell); wl_list_remove(&xdg_shell->display_destroy.link); wl_global_destroy(xdg_shell->global); free(xdg_shell); diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 5c337543b..ae0dfcc14 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -4,7 +4,6 @@ #include #include #include "types/wlr_xdg_shell.h" -#include "util/signal.h" bool wlr_surface_is_xdg_surface(struct wlr_surface *surface) { return surface->role == &xdg_toplevel_surface_role || @@ -34,7 +33,7 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { // TODO: probably need to ungrab before this event if (surface->mapped) { surface->mapped = false; - wlr_signal_emit_safe(&surface->events.unmap, NULL); + wl_signal_emit_mutable(&surface->events.unmap, NULL); } struct wlr_xdg_popup *popup, *popup_tmp; @@ -98,7 +97,7 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client, if (configure->serial == serial) { break; } - wlr_signal_emit_safe(&surface->events.ack_configure, configure); + wl_signal_emit_mutable(&surface->events.ack_configure, configure); xdg_surface_configure_destroy(configure); } @@ -119,7 +118,7 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client, surface->configured = true; surface->pending.configure_serial = serial; - wlr_signal_emit_safe(&surface->events.ack_configure, configure); + wl_signal_emit_mutable(&surface->events.ack_configure, configure); xdg_surface_configure_destroy(configure); } @@ -153,7 +152,7 @@ static void surface_send_configure(void *user_data) { break; } - wlr_signal_emit_safe(&surface->events.configure, configure); + wl_signal_emit_mutable(&surface->events.configure, configure); xdg_surface_send_configure(surface->resource, configure->serial); } @@ -306,13 +305,13 @@ void xdg_surface_role_commit(struct wlr_surface *wlr_surface) { if (!surface->added) { surface->added = true; - wlr_signal_emit_safe(&surface->client->shell->events.new_surface, + wl_signal_emit_mutable(&surface->client->shell->events.new_surface, surface); } if (surface->configured && wlr_surface_has_buffer(surface->surface) && !surface->mapped) { surface->mapped = true; - wlr_signal_emit_safe(&surface->events.map, NULL); + wl_signal_emit_mutable(&surface->events.map, NULL); } } @@ -405,7 +404,7 @@ void reset_xdg_surface(struct wlr_xdg_surface *surface) { } if (surface->added) { - wlr_signal_emit_safe(&surface->events.destroy, NULL); + wl_signal_emit_mutable(&surface->events.destroy, NULL); surface->added = false; } diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 878b00912..58acec271 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -5,7 +5,6 @@ #include #include #include "types/wlr_xdg_shell.h" -#include "util/signal.h" void handle_xdg_toplevel_ack_configure( struct wlr_xdg_toplevel *toplevel, @@ -168,7 +167,7 @@ void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel, toplevel->parent = NULL; } - wlr_signal_emit_safe(&toplevel->events.set_parent, NULL); + wl_signal_emit_mutable(&toplevel->events.set_parent, NULL); } static void xdg_toplevel_handle_set_parent(struct wl_client *client, @@ -198,7 +197,7 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client, free(toplevel->title); toplevel->title = tmp; - wlr_signal_emit_safe(&toplevel->events.set_title, NULL); + wl_signal_emit_mutable(&toplevel->events.set_title, NULL); } static void xdg_toplevel_handle_set_app_id(struct wl_client *client, @@ -215,7 +214,7 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client, free(toplevel->app_id); toplevel->app_id = tmp; - wlr_signal_emit_safe(&toplevel->events.set_app_id, NULL); + wl_signal_emit_mutable(&toplevel->events.set_app_id, NULL); } static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, @@ -246,7 +245,7 @@ static void xdg_toplevel_handle_show_window_menu(struct wl_client *client, .y = y, }; - wlr_signal_emit_safe(&toplevel->events.request_show_window_menu, &event); + wl_signal_emit_mutable(&toplevel->events.request_show_window_menu, &event); } static void xdg_toplevel_handle_move(struct wl_client *client, @@ -275,7 +274,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client, .serial = serial, }; - wlr_signal_emit_safe(&toplevel->events.request_move, &event); + wl_signal_emit_mutable(&toplevel->events.request_move, &event); } static void xdg_toplevel_handle_resize(struct wl_client *client, @@ -305,7 +304,7 @@ static void xdg_toplevel_handle_resize(struct wl_client *client, .edges = edges, }; - wlr_signal_emit_safe(&toplevel->events.request_resize, &event); + wl_signal_emit_mutable(&toplevel->events.request_resize, &event); } static void xdg_toplevel_handle_set_max_size(struct wl_client *client, @@ -329,7 +328,7 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client, struct wlr_xdg_toplevel *toplevel = wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = true; - wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); + wl_signal_emit_mutable(&toplevel->events.request_maximize, NULL); } static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, @@ -337,7 +336,7 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client, struct wlr_xdg_toplevel *toplevel = wlr_xdg_toplevel_from_resource(resource); toplevel->requested.maximized = false; - wlr_signal_emit_safe(&toplevel->events.request_maximize, NULL); + wl_signal_emit_mutable(&toplevel->events.request_maximize, NULL); } static void handle_fullscreen_output_destroy(struct wl_listener *listener, @@ -376,7 +375,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, true, output); - wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); + wl_signal_emit_mutable(&toplevel->events.request_fullscreen, NULL); } static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, @@ -386,7 +385,7 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client, store_fullscreen_requested(toplevel, false, NULL); - wlr_signal_emit_safe(&toplevel->events.request_fullscreen, NULL); + wl_signal_emit_mutable(&toplevel->events.request_fullscreen, NULL); } static void xdg_toplevel_handle_set_minimized(struct wl_client *client, @@ -394,7 +393,7 @@ static void xdg_toplevel_handle_set_minimized(struct wl_client *client, struct wlr_xdg_toplevel *toplevel = wlr_xdg_toplevel_from_resource(resource); toplevel->requested.minimized = true; - wlr_signal_emit_safe(&toplevel->events.request_minimize, NULL); + wl_signal_emit_mutable(&toplevel->events.request_minimize, NULL); } static void xdg_toplevel_handle_destroy(struct wl_client *client, diff --git a/xwayland/server.c b/xwayland/server.c index 0086ad65e..75b919b4d 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -16,7 +16,6 @@ #include #include #include "sockets.h" -#include "util/signal.h" #include "xwayland/config.h" static void safe_close(int fd) { @@ -281,7 +280,7 @@ static int xserver_handle_ready(int fd, uint32_t mask, void *data) { .server = server, .wm_fd = server->wm_fd[0], }; - wlr_signal_emit_safe(&server->events.ready, &event); + wl_signal_emit_mutable(&server->events.ready, &event); /* We removed the source, so don't need recheck */ return 0; @@ -432,7 +431,7 @@ void wlr_xwayland_server_destroy(struct wlr_xwayland_server *server) { server_finish_process(server); server_finish_display(server); - wlr_signal_emit_safe(&server->events.destroy, NULL); + wl_signal_emit_mutable(&server->events.destroy, NULL); free(server); } diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index cb62fcc14..d76f0eec4 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -14,7 +14,6 @@ #include #include #include "sockets.h" -#include "util/signal.h" #include "xwayland/xwm.h" struct wlr_xwayland_cursor { @@ -54,7 +53,7 @@ static void handle_server_ready(struct wl_listener *listener, void *data) { cur->height, cur->hotspot_x, cur->hotspot_y); } - wlr_signal_emit_safe(&xwayland->events.ready, NULL); + wl_signal_emit_mutable(&xwayland->events.ready, NULL); } void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) { diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 1bacd1ce0..fb9e7f441 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -16,7 +16,6 @@ #include #include #include -#include "util/signal.h" #include "xwayland/xwm.h" const char *const atom_map[ATOM_LAST] = { @@ -125,7 +124,7 @@ static struct wlr_xwayland_surface *lookup_surface(struct wlr_xwm *xwm, static int xwayland_surface_handle_ping_timeout(void *data) { struct wlr_xwayland_surface *surface = data; - wlr_signal_emit_safe(&surface->events.ping_timeout, surface); + wl_signal_emit_mutable(&surface->events.ping_timeout, surface); surface->pinging = false; return 1; } @@ -202,7 +201,7 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_list_insert(&xwm->surfaces, &surface->link); - wlr_signal_emit_safe(&xwm->xwayland->events.new_surface, surface); + wl_signal_emit_mutable(&xwm->xwayland->events.new_surface, surface); return surface; } @@ -390,7 +389,7 @@ static void xwayland_surface_destroy( struct wlr_xwayland_surface *xsurface) { xsurface_unmap(xsurface); - wlr_signal_emit_safe(&xsurface->events.destroy, xsurface); + wl_signal_emit_mutable(&xsurface->events.destroy, xsurface); if (xsurface == xsurface->xwm->focus_surface) { xwm_surface_activate(xsurface->xwm, NULL); @@ -456,7 +455,7 @@ static void read_surface_class(struct wlr_xwm *xwm, surface->class = NULL; } - wlr_signal_emit_safe(&surface->events.set_class, surface); + wl_signal_emit_mutable(&surface->events.set_class, surface); } static void read_surface_startup_id(struct wlr_xwm *xwm, @@ -479,7 +478,7 @@ static void read_surface_startup_id(struct wlr_xwm *xwm, wlr_log(WLR_DEBUG, "XCB_ATOM_NET_STARTUP_ID: %s", xsurface->startup_id ? xsurface->startup_id: "(null)"); - wlr_signal_emit_safe(&xsurface->events.set_startup_id, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_startup_id, xsurface); } static void read_surface_role(struct wlr_xwm *xwm, @@ -500,7 +499,7 @@ static void read_surface_role(struct wlr_xwm *xwm, xsurface->role = NULL; } - wlr_signal_emit_safe(&xsurface->events.set_role, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_role, xsurface); } static void read_surface_title(struct wlr_xwm *xwm, @@ -527,7 +526,7 @@ static void read_surface_title(struct wlr_xwm *xwm, } xsurface->has_utf8_title = is_utf8; - wlr_signal_emit_safe(&xsurface->events.set_title, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_title, xsurface); } static bool has_parent(struct wlr_xwayland_surface *parent, @@ -572,7 +571,7 @@ static void read_surface_parent(struct wlr_xwm *xwm, wl_list_init(&xsurface->parent_link); } - wlr_signal_emit_safe(&xsurface->events.set_parent, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_parent, xsurface); } static void read_surface_client_id(struct wlr_xwm *xwm, @@ -606,7 +605,7 @@ static void read_surface_client_id(struct wlr_xwm *xwm, return; } xsurface->pid = *pid; - wlr_signal_emit_safe(&xsurface->events.set_pid, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_pid, xsurface); free(reply); } @@ -629,7 +628,7 @@ static void read_surface_window_type(struct wlr_xwm *xwm, memcpy(xsurface->window_type, atoms, atoms_size); xsurface->window_type_len = atoms_len; - wlr_signal_emit_safe(&xsurface->events.set_window_type, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_window_type, xsurface); } static void read_surface_protocols(struct wlr_xwm *xwm, @@ -674,7 +673,7 @@ static void read_surface_hints(struct wlr_xwm *xwm, xsurface->hints->input = true; } - wlr_signal_emit_safe(&xsurface->events.set_hints, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_hints, xsurface); } static void read_surface_normal_hints(struct wlr_xwm *xwm, @@ -744,7 +743,7 @@ static void read_surface_motif_hints(struct wlr_xwm *xwm, WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE; } } - wlr_signal_emit_safe(&xsurface->events.set_decorations, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_decorations, xsurface); } } @@ -837,7 +836,7 @@ static void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) { if (!surface->mapped && wlr_surface_has_buffer(surface->surface)) { surface->mapped = true; - wlr_signal_emit_safe(&surface->events.map, surface); + wl_signal_emit_mutable(&surface->events.map, surface); xwm_set_net_client_list(surface->xwm); } } @@ -854,7 +853,7 @@ static void xwayland_surface_role_precommit(struct wlr_surface *wlr_surface, // This is a NULL commit if (surface->mapped) { surface->mapped = false; - wlr_signal_emit_safe(&surface->events.unmap, surface); + wl_signal_emit_mutable(&surface->events.unmap, surface); xwm_set_net_client_list(surface->xwm); } } @@ -909,7 +908,7 @@ static void xwm_map_shell_surface(struct wlr_xwm *xwm, static void xsurface_unmap(struct wlr_xwayland_surface *surface) { if (surface->mapped) { - wlr_signal_emit_safe(&surface->events.unmap, surface); + wl_signal_emit_mutable(&surface->events.unmap, surface); surface->mapped = false; xwm_set_net_client_list(surface->xwm); } @@ -977,7 +976,7 @@ static void xwm_handle_configure_request(struct wlr_xwm *xwm, .mask = mask, }; - wlr_signal_emit_safe(&surface->events.request_configure, &wlr_event); + wl_signal_emit_mutable(&surface->events.request_configure, &wlr_event); } static void xwm_handle_configure_notify(struct wlr_xwm *xwm, @@ -1000,11 +999,11 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm, if (xsurface->override_redirect != ev->override_redirect) { xsurface->override_redirect = ev->override_redirect; - wlr_signal_emit_safe(&xsurface->events.set_override_redirect, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_override_redirect, xsurface); } if (geometry_changed) { - wlr_signal_emit_safe(&xsurface->events.set_geometry, NULL); + wl_signal_emit_mutable(&xsurface->events.set_geometry, NULL); } } @@ -1086,7 +1085,7 @@ static void xwm_handle_map_notify(struct wlr_xwm *xwm, if (xsurface->override_redirect != ev->override_redirect) { xsurface->override_redirect = ev->override_redirect; - wlr_signal_emit_safe(&xsurface->events.set_override_redirect, xsurface); + wl_signal_emit_mutable(&xsurface->events.set_override_redirect, xsurface); } } @@ -1198,7 +1197,7 @@ static void xwm_handle_net_wm_moveresize_message(struct wlr_xwm *xwm, switch (detail) { case _NET_WM_MOVERESIZE_MOVE: move_event.surface = xsurface; - wlr_signal_emit_safe(&xsurface->events.request_move, &move_event); + wl_signal_emit_mutable(&xsurface->events.request_move, &move_event); break; case _NET_WM_MOVERESIZE_SIZE_TOPLEFT: case _NET_WM_MOVERESIZE_SIZE_TOP: @@ -1210,7 +1209,7 @@ static void xwm_handle_net_wm_moveresize_message(struct wlr_xwm *xwm, case _NET_WM_MOVERESIZE_SIZE_LEFT: resize_event.surface = xsurface; resize_event.edges = net_wm_edges_to_wlr(detail); - wlr_signal_emit_safe(&xsurface->events.request_resize, &resize_event); + wl_signal_emit_mutable(&xsurface->events.request_resize, &resize_event); break; case _NET_WM_MOVERESIZE_CANCEL: // handled by the compositor @@ -1300,7 +1299,7 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, xsurface->saved_height = xsurface->height; } - wlr_signal_emit_safe(&xsurface->events.request_fullscreen, xsurface); + wl_signal_emit_mutable(&xsurface->events.request_fullscreen, xsurface); } if (maximized != xsurface_is_maximized(xsurface)) { @@ -1309,7 +1308,7 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, xsurface->saved_height = xsurface->height; } - wlr_signal_emit_safe(&xsurface->events.request_maximize, xsurface); + wl_signal_emit_mutable(&xsurface->events.request_maximize, xsurface); } if (minimized != xsurface->minimized) { @@ -1322,7 +1321,7 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, .surface = xsurface, .minimize = xsurface->minimized, }; - wlr_signal_emit_safe(&xsurface->events.request_minimize, &minimize_event); + wl_signal_emit_mutable(&xsurface->events.request_minimize, &minimize_event); } } @@ -1358,7 +1357,7 @@ static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm, if (surface == NULL) { return; } - wlr_signal_emit_safe(&surface->events.request_activate, surface); + wl_signal_emit_mutable(&surface->events.request_activate, surface); } static void pending_startup_id_destroy(struct pending_startup_id *pending) { @@ -1423,7 +1422,7 @@ static void xwm_handle_net_startup_info_message(struct wlr_xwm *xwm, if (id) { struct wlr_xwayland_remove_startup_info_event data = { id, ev->window }; wlr_log(WLR_DEBUG, "Got startup id: %s", id); - wlr_signal_emit_safe(&xwm->xwayland->events.remove_startup_info, &data); + wl_signal_emit_mutable(&xwm->xwayland->events.remove_startup_info, &data); pending_startup_id_destroy(curr); } } @@ -1451,7 +1450,7 @@ static void xwm_handle_wm_change_state_message(struct wlr_xwm *xwm, .surface = xsurface, .minimize = minimize, }; - wlr_signal_emit_safe(&xsurface->events.request_minimize, &minimize_event); + wl_signal_emit_mutable(&xsurface->events.request_minimize, &minimize_event); } static void xwm_handle_client_message(struct wlr_xwm *xwm, From 346e52420171cedaf1fb7dffe7e37f99b478c5b1 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 18 Aug 2022 07:14:28 -0400 Subject: [PATCH 269/298] Remove wlr_signal_emit_safe --- include/util/signal.h | 8 -------- util/meson.build | 1 - util/signal.c | 34 ---------------------------------- 3 files changed, 43 deletions(-) delete mode 100644 include/util/signal.h delete mode 100644 util/signal.c diff --git a/include/util/signal.h b/include/util/signal.h deleted file mode 100644 index fd93073aa..000000000 --- a/include/util/signal.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef UTIL_SIGNAL_H -#define UTIL_SIGNAL_H - -#include - -void wlr_signal_emit_safe(struct wl_signal *signal, void *data); - -#endif diff --git a/util/meson.build b/util/meson.build index a416490f1..8933f2e7e 100644 --- a/util/meson.build +++ b/util/meson.build @@ -6,7 +6,6 @@ wlr_files += files( 'log.c', 'region.c', 'shm.c', - 'signal.c', 'time.c', 'token.c', ) diff --git a/util/signal.c b/util/signal.c deleted file mode 100644 index 39618465d..000000000 --- a/util/signal.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "util/signal.h" - -static void handle_noop(struct wl_listener *listener, void *data) { - // Do nothing -} - -void wlr_signal_emit_safe(struct wl_signal *signal, void *data) { - struct wl_listener cursor; - struct wl_listener end; - - /* Add two special markers: one cursor and one end marker. This way, we know - * that we've already called listeners on the left of the cursor and that we - * don't want to call listeners on the right of the end marker. The 'it' - * function can remove any element it wants from the list without troubles. - * wl_list_for_each_safe tries to be safe but it fails: it works fine - * if the current item is removed, but not if the next one is. */ - wl_list_insert(&signal->listener_list, &cursor.link); - cursor.notify = handle_noop; - wl_list_insert(signal->listener_list.prev, &end.link); - end.notify = handle_noop; - - while (cursor.link.next != &end.link) { - struct wl_list *pos = cursor.link.next; - struct wl_listener *l = wl_container_of(pos, l, link); - - wl_list_remove(&cursor.link); - wl_list_insert(pos, &cursor.link); - - l->notify(l, data); - } - - wl_list_remove(&cursor.link); - wl_list_remove(&end.link); -} From 9ab819684d41b5052260e11a337ce0cdee6ce3bd Mon Sep 17 00:00:00 2001 From: Mark Bolhuis Date: Sat, 13 Aug 2022 22:59:11 +0200 Subject: [PATCH 270/298] types/wlr_xdg_output_v1: Fix wl_output.done bug. If the client binds to version 3 of zxdg_output_v1 and version 1 of wl_output no wl_output.done or zxdg_output_v1.done event is emitted [1]. Also no wl_output.done event is emitted when version 2 or lower of zxdg_output_v1 is bound to. Add a version check to output_manager_handle_get_xdg_output so that no wl_output.done event is emitted when using version 1 of wl_output and version 2 or lower of zxdg_output_v1. [1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/81 --- types/wlr_xdg_output_v1.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/types/wlr_xdg_output_v1.c b/types/wlr_xdg_output_v1.c index 062bf6e63..d030748d2 100644 --- a/types/wlr_xdg_output_v1.c +++ b/types/wlr_xdg_output_v1.c @@ -127,11 +127,11 @@ static void output_manager_handle_get_xdg_output(struct wl_client *client, wl_resource_get_link(xdg_output_resource)); // Name and description should only be sent once per output - uint32_t version = wl_resource_get_version(xdg_output_resource); - if (version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { + uint32_t xdg_version = wl_resource_get_version(xdg_output_resource); + if (xdg_version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { zxdg_output_v1_send_name(xdg_output_resource, output->name); } - if (version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION && + if (xdg_version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION && output->description != NULL) { zxdg_output_v1_send_description(xdg_output_resource, output->description); @@ -139,7 +139,11 @@ static void output_manager_handle_get_xdg_output(struct wl_client *client, output_send_details(xdg_output, xdg_output_resource); - wl_output_send_done(output_resource); + uint32_t wl_version = wl_resource_get_version(output_resource); + if (wl_version >= WL_OUTPUT_DONE_SINCE_VERSION && + xdg_version >= OUTPUT_DONE_DEPRECATED_SINCE_VERSION) { + wl_output_send_done(output_resource); + } } static const struct zxdg_output_manager_v1_interface From 724aa38fc2de14909663cb984a9de64a561abf5f Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 18 Aug 2022 11:51:21 +0200 Subject: [PATCH 271/298] util/array: Add array_realloc for wl_array array_realloc will grow the array for the target size like wl_insert_add, but will also shrink the array if the target size is sufficiently smaller than the current allocation. --- include/util/array.h | 5 +++++ util/array.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/util/array.h b/include/util/array.h index 9612e7db9..2b7278ccc 100644 --- a/include/util/array.h +++ b/include/util/array.h @@ -27,4 +27,9 @@ bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target); */ void array_remove_at(struct wl_array *arr, size_t offset, size_t size); +/** + * Grow or shrink the array to fit the specifized size. + */ +bool array_realloc(struct wl_array *arr, size_t size); + #endif diff --git a/util/array.c b/util/array.c index 50025b77c..9da261270 100644 --- a/util/array.c +++ b/util/array.c @@ -55,3 +55,32 @@ void array_remove_at(struct wl_array *arr, size_t offset, size_t size) { memmove(&data[offset], &data[offset + size], arr->size - offset - size); arr->size -= size; } + +bool array_realloc(struct wl_array *arr, size_t size) { + // If the size is less than 1/4th of the allocation size, we shrink it. + // 1/4th is picked to provide hysteresis, without which an array with size + // arr->alloc would constantly reallocate if an element is added and then + // removed continously. + size_t alloc; + if (arr->alloc > 0 && size > arr->alloc / 4) { + alloc = arr->alloc; + } else { + alloc = 16; + } + + while (alloc < size) { + alloc *= 2; + } + + if (alloc == arr->alloc) { + return true; + } + + void *data = realloc(arr->data, alloc); + if (data == NULL) { + return false; + } + arr->data = data; + arr->alloc = alloc; + return true; +} From 7c575922c05e4d5fd9a403c2aa631a54c7531d44 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Thu, 18 Aug 2022 11:54:03 +0200 Subject: [PATCH 272/298] wlr_scene: Convert render_list to wl_array This simplifies some of the growth logic, but uses array_realloc to shrink the array if needed. --- include/wlr/types/wlr_scene.h | 7 +--- types/scene/wlr_scene.c | 68 ++++++++++------------------------- 2 files changed, 19 insertions(+), 56 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index d92df7db1..614397f71 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -157,11 +157,6 @@ struct wlr_scene_buffer { pixman_region32_t opaque_region; }; -struct wlr_scene_output_render_list { - struct wlr_scene_node **data; - size_t capacity; -}; - /** A viewport for an output in the scene-graph */ struct wlr_scene_output { struct wlr_output *output; @@ -189,7 +184,7 @@ struct wlr_scene_output { struct wl_list damage_highlight_regions; - struct wlr_scene_output_render_list render_list; + struct wl_array render_list; }; /** A layer shell scene helper */ diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 27494248e..79701ab3d 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -13,10 +13,10 @@ #include #include "types/wlr_buffer.h" #include "types/wlr_scene.h" +#include "util/array.h" #include "util/time.h" #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 -#define RENDER_LIST_MIN_ALLOCATION 8 static struct wlr_scene_tree *scene_tree_from_node(struct wlr_scene_node *node) { assert(node->type == WLR_SCENE_NODE_TREE); @@ -1276,7 +1276,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wl_list_remove(&scene_output->output_damage.link); wl_list_remove(&scene_output->output_needs_frame.link); - free(scene_output->render_list.data); + wl_array_release(&scene_output->render_list); free(scene_output); } @@ -1321,18 +1321,9 @@ static bool scene_node_invisible(struct wlr_scene_node *node) { return false; } -static size_t max(size_t fst, size_t snd) { - if (fst > snd) { - return fst; - } else { - return snd; - } -} - struct render_list_constructor_data { struct wlr_box box; - struct wlr_scene_output_render_list *render_list; - size_t size; + struct wl_array *render_list; }; static bool construct_render_list_iterator(struct wlr_scene_node *node, @@ -1367,22 +1358,11 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node, pixman_region32_fini(&intersection); - if (data->size == data->render_list->capacity) { - size_t alloc_size = - max(data->render_list->capacity * 2, RENDER_LIST_MIN_ALLOCATION); - void *alloc = realloc(data->render_list->data, alloc_size - * sizeof(struct wlr_scene_node *)); - - if (alloc) { - data->render_list->data = alloc; - data->render_list->capacity = alloc_size; - } + struct wlr_scene_node **entry = wl_array_add(data->render_list, + sizeof(struct wlr_scene_node *)); + if (entry) { + *entry = node; } - - if (data->size < data->render_list->capacity) { - data->render_list->data[data->size++] = node; - } - return false; } @@ -1441,21 +1421,6 @@ static bool scene_node_try_direct_scanout(struct wlr_scene_node *node, return wlr_output_commit(output); } -static void compact_render_list(struct wlr_scene_output_render_list *list, size_t size) { - assert(size <= list->capacity); - - size_t alloc_size = max(RENDER_LIST_MIN_ALLOCATION, size); - if (alloc_size == list->capacity) { - return; - } - - void *alloc = realloc(list->data, alloc_size * sizeof(struct wlr_scene_node *)); - if (alloc) { - list->data = alloc; - list->capacity = alloc_size; - } -} - bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct wlr_output *output = scene_output->output; enum wlr_scene_debug_damage_option debug_damage = @@ -1467,20 +1432,23 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct render_list_constructor_data list_con = { .box = { .x = scene_output->x, .y = scene_output->y }, .render_list = &scene_output->render_list, - .size = 0, }; wlr_output_effective_resolution(output, &list_con.box.width, &list_con.box.height); + list_con.render_list->size = 0; scene_nodes_in_box(&scene_output->scene->tree.node, &list_con.box, construct_render_list_iterator, &list_con); - compact_render_list(list_con.render_list, list_con.size); + array_realloc(list_con.render_list, list_con.render_list->size); + + int list_len = list_con.render_list->size / sizeof(struct wlr_scene_node *); + struct wlr_scene_node **list_data = list_con.render_list->data; // if there is only one thing to render let's see if that thing can be // directly scanned out bool scanout = false; - if (list_con.size == 1) { - struct wlr_scene_node *node = list_con.render_list->data[0]; + if (list_len == 1) { + struct wlr_scene_node *node = list_data[0]; scanout = scene_node_try_direct_scanout(node, scene_output, &list_con.box); } @@ -1493,7 +1461,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { } if (scanout) { - struct wlr_scene_node *node = list_con.render_list->data[0]; + struct wlr_scene_node *node = list_data[0]; assert(node->type == WLR_SCENE_NODE_BUFFER); struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); @@ -1569,11 +1537,11 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_renderer_clear(renderer, (float[4]){ 0.0, 0.0, 0.0, 1.0 }); } - for (int i = list_con.size - 1; i >= 0; i--) { - struct wlr_scene_node *node = list_con.render_list->data[i]; + for (int i = list_len - 1; i >= 0; i--) { + struct wlr_scene_node *node = list_data[i]; scene_node_render(node, scene_output, &damage); } - + wlr_renderer_scissor(renderer, NULL); if (debug_damage == WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT) { From 4d4f823263031cbef06f51547a5fe476e2eb5e38 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 16 Aug 2022 07:03:22 -0400 Subject: [PATCH 273/298] wlr_scene: Simplify calculate_visibilty option --- types/scene/wlr_scene.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 79701ab3d..ddd09a359 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -398,15 +398,13 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node, struct wlr_box box = { .x = lx, .y = ly }; scene_node_get_size(node, &box.width, &box.height); + pixman_region32_subtract(&node->visible, &node->visible, data->update_region); + pixman_region32_union(&node->visible, &node->visible, data->visible); + pixman_region32_intersect_rect(&node->visible, &node->visible, + lx, ly, box.width, box.height); + if (data->calculate_visibility) { - pixman_region32_subtract(&node->visible, &node->visible, data->update_region); - pixman_region32_union(&node->visible, &node->visible, data->visible); - pixman_region32_intersect_rect(&node->visible, &node->visible, - lx, ly, box.width, box.height); scene_node_cull_hidden(node, lx, ly, data->visible); - } else { - pixman_region32_fini(&node->visible); - pixman_region32_init_rect(&node->visible, lx, ly, box.width, box.height); } update_node_update_outputs(node, data->outputs, NULL); From 6d1b8b376d1e4a5e1b4b07e53487533711988136 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 16 Aug 2022 07:06:17 -0400 Subject: [PATCH 274/298] wlr_scene: Only enable black rect optimization if culling is enabled If culling is not enabled, there is no longer any guarantee that the elements behind the rect won't be rendered. We must render the black rect in all circumstances to cover up anything rendered. This fixes the WLR_SCENE_DISABLE_VISIBILTY option. --- types/scene/wlr_scene.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index ddd09a359..5c14aa66e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1322,6 +1322,7 @@ static bool scene_node_invisible(struct wlr_scene_node *node) { struct render_list_constructor_data { struct wlr_box box; struct wl_array *render_list; + bool calculate_visibility; }; static bool construct_render_list_iterator(struct wlr_scene_node *node, @@ -1335,7 +1336,7 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node, // while rendering, the background should always be black. // If we see a black rect, we can ignore rendering everything under the rect // and even the rect itself. - if (node->type == WLR_SCENE_NODE_RECT) { + if (node->type == WLR_SCENE_NODE_RECT && data->calculate_visibility) { struct wlr_scene_rect *rect = scene_rect_from_node(node); float *black = (float[4]){ 0.f, 0.f, 0.f, 1.f }; @@ -1430,6 +1431,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct render_list_constructor_data list_con = { .box = { .x = scene_output->x, .y = scene_output->y }, .render_list = &scene_output->render_list, + .calculate_visibility = scene_output->scene->calculate_visibility, }; wlr_output_effective_resolution(output, &list_con.box.width, &list_con.box.height); From 9bba4284e454c72f8269f766069456ad2aa17ad3 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 22 Aug 2022 10:17:59 -0400 Subject: [PATCH 275/298] wlr_scene: Cull background We don't need to worry about the black rect optimization here (that always assumes that there will be a black background) because the background is culled based on the render list. That means if a black rect is removed, the visibility will reach all the way to the bottom forcing the renderer to clear the area not breaking the assumption. --- types/scene/wlr_scene.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 5c14aa66e..c1d7569af 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1530,12 +1530,28 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_renderer_begin(renderer, output->width, output->height); + pixman_region32_t background; + pixman_region32_copy(&background, &damage); + + // Cull areas of the background that are occluded by opaque regions of + // scene nodes above. Those scene nodes will just render atop having us + // never see the background. + if (scene_output->scene->calculate_visibility) { + for (int i = list_len - 1; i >= 0; i--) { + struct wlr_scene_node *node = list_data[i]; + int x, y; + wlr_scene_node_coords(node, &x, &y); + scene_node_cull_hidden(node, x, y, &background); + } + } + int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); + pixman_box32_t *rects = pixman_region32_rectangles(&background, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(output, &rects[i]); wlr_renderer_clear(renderer, (float[4]){ 0.0, 0.0, 0.0, 1.0 }); } + pixman_region32_fini(&background); for (int i = list_len - 1; i >= 0; i--) { struct wlr_scene_node *node = list_data[i]; From e7477c71147617572c98a7daaf5934d4ad848d2a Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 16 Aug 2022 08:17:13 -0400 Subject: [PATCH 276/298] wlr_scene: Improve awkward code style --- types/scene/wlr_scene.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index c1d7569af..a33ea1b31 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -234,11 +234,9 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box case WLR_SCENE_NODE_BUFFER:; struct wlr_box node_box = { .x = lx, .y = ly }; scene_node_get_size(node, &node_box.width, &node_box.height); - bool intersects; - intersects = wlr_box_intersection(&node_box, &node_box, box); - - if (intersects && iterator(node, lx, ly, user_data)) { + if (wlr_box_intersection(&node_box, &node_box, box) && + iterator(node, lx, ly, user_data)) { return true; } break; From 31a9fc1fb60f8001f43186d36e3fbb5fce584d91 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 19 Aug 2022 09:59:30 -0400 Subject: [PATCH 277/298] util: Introduce env helpers --- include/util/env.h | 11 +++++++++++ util/env.c | 38 ++++++++++++++++++++++++++++++++++++++ util/meson.build | 1 + 3 files changed, 50 insertions(+) create mode 100644 include/util/env.h create mode 100644 util/env.c diff --git a/include/util/env.h b/include/util/env.h new file mode 100644 index 000000000..6720fa896 --- /dev/null +++ b/include/util/env.h @@ -0,0 +1,11 @@ +#ifndef UTIL_ENV_H +#define UTIL_ENV_H + +#include +#include + +bool env_parse_bool(const char *option); + +ssize_t env_parse_switch(const char *option, const char **switches); + +#endif diff --git a/util/env.c b/util/env.c new file mode 100644 index 000000000..b0a9efdae --- /dev/null +++ b/util/env.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include "util/env.h" + +bool env_parse_bool(const char *option) { + const char *env = getenv(option); + if (env) { + wlr_log(WLR_INFO, "Loading %s option: %s", option, env); + } + + if (!env || strcmp(env, "0") == 0) { + return false; + } else if (strcmp(env, "1") == 0) { + return true; + } + + wlr_log(WLR_ERROR, "Unknown %s option: %s", option, env); + return false; +} + +ssize_t env_parse_switch(const char *option, const char **switches) { + const char *env = getenv(option); + if (env) { + wlr_log(WLR_INFO, "Loading %s option: %s", option, env); + } else { + return 0; + } + + for (ssize_t i = 0; switches[i]; i++) { + if (strcmp(env, switches[i]) == 0) { + return i; + } + } + + wlr_log(WLR_ERROR, "Unknown %s option: %s", option, env); + return 0; +} diff --git a/util/meson.build b/util/meson.build index 8933f2e7e..34fc2e232 100644 --- a/util/meson.build +++ b/util/meson.build @@ -2,6 +2,7 @@ wlr_files += files( 'addon.c', 'array.c', 'box.c', + 'env.c', 'global.c', 'log.c', 'region.c', From 8bd7170fd95aa0753dc859457808d7f7f81d560d Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 19 Aug 2022 10:10:52 -0400 Subject: [PATCH 278/298] Use env helpers --- backend/backend.c | 4 +- backend/drm/drm.c | 7 ++-- backend/libinput/backend.c | 10 ++--- render/egl.c | 4 +- render/wlr_renderer.c | 80 ++++++++++++++++++++++---------------- types/output/output.c | 9 ++--- types/scene/wlr_scene.c | 52 +++++-------------------- 7 files changed, 70 insertions(+), 96 deletions(-) diff --git a/backend/backend.c b/backend/backend.c index 32ddca97b..4c886af67 100644 --- a/backend/backend.c +++ b/backend/backend.c @@ -17,6 +17,7 @@ #include "backend/backend.h" #include "backend/multi.h" #include "render/allocator/allocator.h" +#include "util/env.h" #if WLR_HAS_DRM_BACKEND #include @@ -364,8 +365,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { } wlr_multi_backend_add(backend, libinput); #else - const char *no_devs = getenv("WLR_LIBINPUT_NO_DEVICES"); - if (no_devs && strcmp(no_devs, "1") == 0) { + if (env_parse_bool("WLR_LIBINPUT_NO_DEVICES")) { wlr_log(WLR_INFO, "WLR_LIBINPUT_NO_DEVICES is set, " "starting without libinput backend"); } else { diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 9acb41757..94dd7023c 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -29,6 +29,7 @@ #include "render/drm_format_set.h" #include "render/swapchain.h" #include "render/wlr_renderer.h" +#include "util/env.h" // Output state which needs a KMS commit to be applied static const uint32_t COMMIT_OUTPUT_STATE = @@ -74,8 +75,7 @@ bool check_drm_features(struct wlr_drm_backend *drm) { return false; } - const char *no_atomic = getenv("WLR_DRM_NO_ATOMIC"); - if (no_atomic && strcmp(no_atomic, "1") == 0) { + if (env_parse_bool("WLR_DRM_NO_ATOMIC")) { wlr_log(WLR_DEBUG, "WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface"); drm->iface = &legacy_iface; @@ -91,8 +91,7 @@ bool check_drm_features(struct wlr_drm_backend *drm) { int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap); drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME; - const char *no_modifiers = getenv("WLR_DRM_NO_MODIFIERS"); - if (no_modifiers != NULL && strcmp(no_modifiers, "1") == 0) { + if (env_parse_bool("WLR_DRM_NO_MODIFIERS")) { wlr_log(WLR_DEBUG, "WLR_DRM_NO_MODIFIERS set, disabling modifiers"); } else { ret = drmGetCap(drm->fd, DRM_CAP_ADDFB2_MODIFIERS, &cap); diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 02c2f64b1..688fae5d3 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -6,6 +6,7 @@ #include #include #include "backend/libinput.h" +#include "util/env.h" static struct wlr_libinput_backend *get_libinput_backend_from_backend( struct wlr_backend *wlr_backend) { @@ -103,13 +104,8 @@ static bool backend_start(struct wlr_backend *wlr_backend) { libinput_log_set_priority(backend->libinput_context, LIBINPUT_LOG_PRIORITY_ERROR); int libinput_fd = libinput_get_fd(backend->libinput_context); - char *no_devs = getenv("WLR_LIBINPUT_NO_DEVICES"); - if (no_devs) { - if (strcmp(no_devs, "1") != 0) { - no_devs = NULL; - } - } - if (!no_devs && wl_list_empty(&backend->devices)) { + + if (!env_parse_bool("WLR_LIBINPUT_NO_DEVICES") && wl_list_empty(&backend->devices)) { handle_libinput_readable(libinput_fd, WL_EVENT_READABLE, backend); if (wl_list_empty(&backend->devices)) { wlr_log(WLR_ERROR, "libinput initialization failed, no input devices"); diff --git a/render/egl.c b/render/egl.c index 168e358c6..ee961f4b9 100644 --- a/render/egl.c +++ b/render/egl.c @@ -11,6 +11,7 @@ #include #include #include "render/egl.h" +#include "util/env.h" static enum wlr_log_importance egl_log_importance_to_wlr(EGLint type) { switch (type) { @@ -284,8 +285,7 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay *display) { } if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) { - const char *allow_software = getenv("WLR_RENDERER_ALLOW_SOFTWARE"); - if (allow_software != NULL && strcmp(allow_software, "1") == 0) { + if (env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) { wlr_log(WLR_INFO, "Using software rendering"); } else { wlr_log(WLR_ERROR, "Software rendering detected, please use " diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 622f5f961..f140f9afa 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -28,6 +28,7 @@ #include "backend/backend.h" #include "render/pixel_format.h" #include "render/wlr_renderer.h" +#include "util/env.h" void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl) { @@ -266,54 +267,65 @@ bool wlr_renderer_init_wl_display(struct wlr_renderer *r, return true; } -struct wlr_renderer *renderer_autocreate_with_drm_fd(int drm_fd) { - const char *name = getenv("WLR_RENDERER"); - if (name) { - wlr_log(WLR_INFO, "Loading user-specified renderer due to WLR_RENDERER: %s", - name); +static void log_creation_failure(bool is_auto, const char *msg) { + wlr_log(is_auto ? WLR_DEBUG : WLR_ERROR, "%s%s", msg, is_auto ? ". Skipping!" : ""); +} +struct wlr_renderer *renderer_autocreate_with_drm_fd(int drm_fd) { + const char *renderer_options[] = { + "auto", #if WLR_HAS_GLES2_RENDERER - if (strcmp(name, "gles2") == 0) { - if (drm_fd < 0) { - wlr_log(WLR_ERROR, "Cannot create GLES2 renderer: " - "no DRM FD available"); - return NULL; - } - return wlr_gles2_renderer_create_with_drm_fd(drm_fd); - } + "gles2", #endif #if WLR_HAS_VULKAN_RENDERER - if (strcmp(name, "vulkan") == 0) { - return wlr_vk_renderer_create_with_drm_fd(drm_fd); - } + "vulkan", #endif - if (strcmp(name, "pixman") == 0) { - return wlr_pixman_renderer_create(); - } - - wlr_log(WLR_ERROR, "Invalid WLR_RENDERER value: '%s'", name); - return NULL; - } + "pixman", + NULL + }; + const char *renderer_name = renderer_options[env_parse_switch("WLR_RENDERER", renderer_options)]; + bool is_auto = strcmp(renderer_name, "auto") == 0; struct wlr_renderer *renderer = NULL; + #if WLR_HAS_GLES2_RENDERER - if (drm_fd >= 0) { - if ((renderer = wlr_gles2_renderer_create_with_drm_fd(drm_fd)) != NULL) { - return renderer; + if (!renderer && (is_auto || strcmp(renderer_name, "gles2") == 0)) { + if (drm_fd < 0) { + log_creation_failure(is_auto, "Cannot create GLES2 renderer: no DRM FD available"); + } else { + renderer = wlr_gles2_renderer_create_with_drm_fd(drm_fd); + if (!renderer) { + log_creation_failure(is_auto, "Failed to create a GLES2 renderer"); + } } - wlr_log(WLR_DEBUG, "Failed to create GLES2 renderer"); - } else { - wlr_log(WLR_DEBUG, "Skipping GLES2 renderer: no DRM FD available"); } #endif - if ((renderer = wlr_pixman_renderer_create()) != NULL) { - return renderer; +#if WLR_HAS_VULKAN_RENDERER + if (!renderer && (is_auto || strcmp(renderer_name, "vulkan") == 0)) { + if (drm_fd < 0) { + log_creation_failure(is_auto, "Cannot create Vulkan renderer: no DRM FD available"); + } else { + renderer = wlr_vk_renderer_create_with_drm_fd(drm_fd); + if (!renderer) { + log_creation_failure(is_auto, "Failed to create a Vulkan renderer"); + } + } } - wlr_log(WLR_DEBUG, "Failed to create pixman renderer"); +#endif - wlr_log(WLR_ERROR, "Could not initialize renderer"); - return NULL; + if (!renderer && (is_auto || strcmp(renderer_name, "pixman") == 0)) { + renderer = wlr_pixman_renderer_create(); + if (!renderer) { + log_creation_failure(is_auto, "Failed to create a pixman renderer"); + } + } + + if (!renderer) { + wlr_log(WLR_ERROR, "Could not initialize renderer"); + } + + return renderer; } static int open_drm_render_node(void) { diff --git a/types/output/output.c b/types/output/output.c index 549dabd16..a4cb89802 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -10,6 +10,7 @@ #include "render/allocator/allocator.h" #include "render/swapchain.h" #include "types/wlr_output.h" +#include "util/env.h" #include "util/global.h" #define OUTPUT_VERSION 4 @@ -366,11 +367,9 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.destroy); output_state_init(&output->pending); - const char *no_hardware_cursors = getenv("WLR_NO_HARDWARE_CURSORS"); - if (no_hardware_cursors != NULL && strcmp(no_hardware_cursors, "1") == 0) { - wlr_log(WLR_DEBUG, - "WLR_NO_HARDWARE_CURSORS set, forcing software cursors"); - output->software_cursor_locks = 1; + output->software_cursor_locks = env_parse_bool("WLR_NO_HARDWARE_CURSORS"); + if (output->software_cursor_locks) { + wlr_log(WLR_DEBUG, "WLR_NO_HARDWARE_CURSORS set, forcing software cursors"); } wlr_addon_set_init(&output->addons); diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index a33ea1b31..7541affce 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -14,6 +14,7 @@ #include "types/wlr_buffer.h" #include "types/wlr_scene.h" #include "util/array.h" +#include "util/env.h" #include "util/time.h" #define HIGHLIGHT_DAMAGE_FADEOUT_TIME 250 @@ -150,49 +151,16 @@ struct wlr_scene *wlr_scene_create(void) { wl_list_init(&scene->outputs); wl_list_init(&scene->presentation_destroy.link); - char *debug_damage = getenv("WLR_SCENE_DEBUG_DAMAGE"); - if (debug_damage) { - wlr_log(WLR_INFO, "Loading WLR_SCENE_DEBUG_DAMAGE option: %s", debug_damage); - } + const char *debug_damage_options[] = { + "none", + "rerender", + "highlight", + NULL + }; - if (!debug_damage || strcmp(debug_damage, "none") == 0) { - scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_NONE; - } else if (strcmp(debug_damage, "rerender") == 0) { - scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_RERENDER; - } else if (strcmp(debug_damage, "highlight") == 0) { - scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_HIGHLIGHT; - } else { - wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DEBUG_DAMAGE option: %s", debug_damage); - scene->debug_damage_option = WLR_SCENE_DEBUG_DAMAGE_NONE; - } - - char *disable_direct_scanout = getenv("WLR_SCENE_DISABLE_DIRECT_SCANOUT"); - if (disable_direct_scanout) { - wlr_log(WLR_INFO, "Loading WLR_SCENE_DISABLE_DIRECT_SCANOUT option: %s", disable_direct_scanout); - } - - if (!disable_direct_scanout || strcmp(disable_direct_scanout, "0") == 0) { - scene->direct_scanout = true; - } else if (strcmp(disable_direct_scanout, "1") == 0) { - scene->direct_scanout = false; - } else { - wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DISABLE_DIRECT_SCANOUT option: %s", disable_direct_scanout); - scene->direct_scanout = true; - } - - char *visibility_disabled = getenv("WLR_SCENE_DISABLE_VISIBILITY"); - if (visibility_disabled) { - wlr_log(WLR_INFO, "Loading WLR_SCENE_DISABLE_VISIBILITY option: %s", visibility_disabled); - } - - if (!visibility_disabled || strcmp(visibility_disabled, "0") == 0) { - scene->calculate_visibility = true; - } else if (strcmp(visibility_disabled, "1") == 0) { - scene->calculate_visibility = false; - } else { - wlr_log(WLR_ERROR, "Unknown WLR_SCENE_DISABLE_VISIBILITY option: %s", visibility_disabled); - scene->calculate_visibility = true; - } + scene->debug_damage_option = env_parse_switch("WLR_SCENE_DEBUG_DAMAGE", debug_damage_options); + scene->direct_scanout = !env_parse_bool("WLR_SCENE_DISABLE_DIRECT_SCANOUT"); + scene->calculate_visibility = !env_parse_bool("WLR_SCENE_DISABLE_VISIBILITY"); return scene; } From d3cb6b73a2733d8457a8be2593a42942b36b77e2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Mon, 22 Aug 2022 14:45:30 -0400 Subject: [PATCH 279/298] wlr_scene: Initialize region32 before trying to use it --- types/scene/wlr_scene.c | 1 + 1 file changed, 1 insertion(+) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 7541affce..102e9e3ab 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1497,6 +1497,7 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { wlr_renderer_begin(renderer, output->width, output->height); pixman_region32_t background; + pixman_region32_init(&background); pixman_region32_copy(&background, &damage); // Cull areas of the background that are occluded by opaque regions of From 4c1afb126b9a49aee367276f634f8686428d6147 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 30 Jun 2022 14:01:46 +0200 Subject: [PATCH 280/298] wlr-output-management: Implement version 3 release requests Head/mode resources older than version 3 and lacking a release request are intentionally leaked as this is the only way to fix the race. Implements: https://gitlab.freedesktop.org/wlroots/wlr-protocols/-/merge_requests/114 --- .../wlr-output-management-unstable-v1.xml | 47 +++++++++++++------ types/wlr_output_management_v1.c | 37 ++++++++++++--- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/protocol/wlr-output-management-unstable-v1.xml b/protocol/wlr-output-management-unstable-v1.xml index cadc45fb2..3568e04ce 100644 --- a/protocol/wlr-output-management-unstable-v1.xml +++ b/protocol/wlr-output-management-unstable-v1.xml @@ -39,7 +39,7 @@ interface version number is reset. - + This interface is a manager that allows reading and writing the current output device configuration. @@ -115,7 +115,7 @@ - + This event indicates that the compositor is done sending manager events. The compositor will destroy the object immediately after sending this @@ -125,7 +125,7 @@ - + A head is an output device. The difference between a wl_output object and a head is that heads are advertised even if they are turned off. A head @@ -251,14 +251,15 @@ - - The compositor will destroy the object immediately after sending this - event, so it will become invalid and the client should release any - resources associated with it. + + This event indicates that the head is no longer available. The head + object becomes inert. Clients should send a destroy request and release + any resources associated with it. + This event describes the manufacturer of the head. @@ -328,9 +329,18 @@ + + + + + + This request indicates that the client will no longer use this head + object. + + - + This object describes an output mode. @@ -368,15 +378,24 @@ - - The compositor will destroy the object immediately after sending this - event, so it will become invalid and the client should release any - resources associated with it. + + This event indicates that the mode is no longer available. The mode + object becomes inert. Clients should send a destroy request and release + any resources associated with it. + + + + + + This request indicates that the client will no longer use this mode + object. + + - + This object is used by the client to describe a full output configuration. @@ -494,7 +513,7 @@ - + This object is used by the client to update a single head's configuration. diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index 64eff211f..f7ac5dcf2 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -5,7 +5,7 @@ #include #include "wlr-output-management-unstable-v1-protocol.h" -#define OUTPUT_MANAGER_VERSION 2 +#define OUTPUT_MANAGER_VERSION 3 enum { HEAD_STATE_ENABLED = 1 << 0, @@ -27,6 +27,7 @@ static struct wlr_output_head_v1 *head_from_resource( return wl_resource_get_user_data(resource); } +// Can return NULL if the mode is inert static struct wlr_output_mode *mode_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, @@ -41,11 +42,15 @@ static void head_destroy(struct wlr_output_head_v1 *head) { struct wl_resource *resource, *tmp; wl_resource_for_each_safe(resource, tmp, &head->mode_resources) { zwlr_output_mode_v1_send_finished(resource); - wl_resource_destroy(resource); + wl_list_remove(wl_resource_get_link(resource)); + wl_list_init(wl_resource_get_link(resource)); + wl_resource_set_user_data(resource, NULL); } wl_resource_for_each_safe(resource, tmp, &head->resources) { zwlr_output_head_v1_send_finished(resource); - wl_resource_destroy(resource); + wl_list_remove(wl_resource_get_link(resource)); + wl_list_init(wl_resource_get_link(resource)); + wl_resource_set_user_data(resource, NULL); } wl_list_remove(&head->link); wl_list_remove(&head->output_destroy.link); @@ -648,10 +653,19 @@ static void send_mode_state(struct wl_resource *mode_resource, } } -static void mode_handle_resource_destroy(struct wl_resource *resource) { +static void output_mode_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(resource)); } +static void output_mode_handle_release(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static const struct zwlr_output_mode_v1_interface output_mode_impl = { + .release = output_mode_handle_release, +}; + static struct wl_resource *head_send_mode(struct wlr_output_head_v1 *head, struct wl_resource *head_resource, struct wlr_output_mode *mode) { struct wl_client *client = wl_resource_get_client(head_resource); @@ -662,8 +676,8 @@ static struct wl_resource *head_send_mode(struct wlr_output_head_v1 *head, wl_resource_post_no_memory(head_resource); return NULL; } - wl_resource_set_implementation(mode_resource, NULL, mode, - mode_handle_resource_destroy); + wl_resource_set_implementation(mode_resource, &output_mode_impl, mode, + output_mode_handle_resource_destroy); wl_list_insert(&head->mode_resources, wl_resource_get_link(mode_resource)); zwlr_output_head_v1_send_mode(head_resource, mode_resource); @@ -739,6 +753,15 @@ static void head_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(resource)); } +static void head_handle_release(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static const struct zwlr_output_head_v1_interface head_impl = { + .release = head_handle_release, +}; + static void manager_send_head(struct wlr_output_manager_v1 *manager, struct wlr_output_head_v1 *head, struct wl_resource *manager_resource) { struct wlr_output *output = head->state.output; @@ -751,7 +774,7 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager, wl_resource_post_no_memory(manager_resource); return; } - wl_resource_set_implementation(head_resource, NULL, head, + wl_resource_set_implementation(head_resource, &head_impl, head, head_handle_resource_destroy); wl_list_insert(&head->resources, wl_resource_get_link(head_resource)); From d452a729cb7b81a91086ca2cacb054b19923f4c5 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 25 Aug 2022 00:51:32 +0200 Subject: [PATCH 281/298] wlr-output-management: fix broken asserts These asserts were broken in 4c1afb12 as new implementations were added without updating the wl_resource_instance_of() calls. --- types/wlr_output_management_v1.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/types/wlr_output_management_v1.c b/types/wlr_output_management_v1.c index f7ac5dcf2..3fb9cf432 100644 --- a/types/wlr_output_management_v1.c +++ b/types/wlr_output_management_v1.c @@ -18,20 +18,23 @@ enum { static const uint32_t HEAD_STATE_ALL = HEAD_STATE_ENABLED | HEAD_STATE_MODE | HEAD_STATE_POSITION | HEAD_STATE_TRANSFORM | HEAD_STATE_SCALE; +static const struct zwlr_output_head_v1_interface head_impl; // Can return NULL if the head is inert static struct wlr_output_head_v1 *head_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, - &zwlr_output_head_v1_interface, NULL)); + &zwlr_output_head_v1_interface, &head_impl)); return wl_resource_get_user_data(resource); } +static const struct zwlr_output_mode_v1_interface output_mode_impl; + // Can return NULL if the mode is inert static struct wlr_output_mode *mode_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, - &zwlr_output_mode_v1_interface, NULL)); + &zwlr_output_mode_v1_interface, &output_mode_impl)); return wl_resource_get_user_data(resource); } From 525506559a5226302eb8b1100a94ef02e9d4df15 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 25 Aug 2022 18:59:33 -0400 Subject: [PATCH 282/298] wlr_compositor: Use wlr_fbox_equal --- types/wlr_compositor.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index fd7cc1d0d..cb0267833 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -230,10 +230,7 @@ static void surface_update_damage(pixman_region32_t *buffer_damage, if (pending->width != current->width || pending->height != current->height || - pending->viewport.src.x != current->viewport.src.x || - pending->viewport.src.y != current->viewport.src.y || - pending->viewport.src.width != current->viewport.src.width || - pending->viewport.src.height != current->viewport.src.height) { + !wlr_fbox_equal(&pending->viewport.src, ¤t->viewport.src)) { // Damage the whole buffer on resize or viewport source box change pixman_region32_union_rect(buffer_damage, buffer_damage, 0, 0, pending->buffer_width, pending->buffer_height); From 6a11256cd0f19fa0ab26f204404e9f9e3f41f851 Mon Sep 17 00:00:00 2001 From: yiqiang Date: Tue, 23 Aug 2022 15:44:26 +0800 Subject: [PATCH 283/298] scene/wlr_scene:fix judgment of invisible node --- types/scene/wlr_scene.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 102e9e3ab..9516971aa 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1272,10 +1272,9 @@ static bool scene_node_invisible(struct wlr_scene_node *node) { if (node->type == WLR_SCENE_NODE_TREE) { return true; } else if (node->type == WLR_SCENE_NODE_RECT) { - float *clear = (float[4]){ 0.f, 0.f, 0.f, 0.f }; struct wlr_scene_rect *rect = scene_rect_from_node(node); - return memcmp(rect->color, clear, sizeof(float) * 4) == 0; + return rect->color[3] == 0.f; } else if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node); From fa7d2cb8d60ed48c44c707106c03682056ddfaca Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Fri, 26 Aug 2022 19:07:52 -0400 Subject: [PATCH 284/298] wlr_scene: Only consider visible parts of the node when culling background Originally, I thought that we could safely subtract opaque regions from the background even if the black rect optimization was kicking in. This is wrong because a scene node that isn't fully occluded will still appear in the render list even if its partially under a black rect. We need to make sure that while culling the background, we only consider opaque regions that are also visible. This will fix the black rect optimization with the background. --- types/scene/wlr_scene.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 9516971aa..5e5f80039 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -221,8 +221,8 @@ static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, return _scene_nodes_in_box(node, box, iterator, user_data, x, y); } -static void scene_node_cull_hidden(struct wlr_scene_node *node, int x, int y, - pixman_region32_t *visible) { +static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, + pixman_region32_t *opaque) { if (node->type == WLR_SCENE_NODE_RECT) { struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); if (scene_rect->color[3] != 1) { @@ -236,19 +236,16 @@ static void scene_node_cull_hidden(struct wlr_scene_node *node, int x, int y, } if (!buffer_is_opaque(scene_buffer->buffer)) { - pixman_region32_translate(visible, -x, -y); - pixman_region32_subtract(visible, visible, &scene_buffer->opaque_region); - pixman_region32_translate(visible, x, y); + pixman_region32_copy(opaque, &scene_buffer->opaque_region); + pixman_region32_translate(opaque, x, y); return; } } int width, height; scene_node_get_size(node, &width, &height); - pixman_region32_t opaque; - pixman_region32_init_rect(&opaque, x, y, width, height); - pixman_region32_subtract(visible, visible, &opaque); - pixman_region32_fini(&opaque); + pixman_region32_fini(opaque); + pixman_region32_init_rect(opaque, x, y, width, height); } struct scene_update_data { @@ -370,7 +367,11 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node, lx, ly, box.width, box.height); if (data->calculate_visibility) { - scene_node_cull_hidden(node, lx, ly, data->visible); + pixman_region32_t opaque; + pixman_region32_init(&opaque); + scene_node_opaque_region(node, lx, ly, &opaque); + pixman_region32_subtract(data->visible, data->visible, &opaque); + pixman_region32_fini(&opaque); } update_node_update_outputs(node, data->outputs, NULL); @@ -1507,7 +1508,20 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { struct wlr_scene_node *node = list_data[i]; int x, y; wlr_scene_node_coords(node, &x, &y); - scene_node_cull_hidden(node, x, y, &background); + + // We must only cull opaque regions that are visible by the node. + // The node's visibility will have the knowledge of a black rect + // that may have been omitted from the render list via the black + // rect optimization. In order to ensure we don't cull background + // rendering in that black rect region, consider the node's visibility. + pixman_region32_t opaque; + pixman_region32_init(&opaque); + scene_node_opaque_region(node, x, y, &opaque); + pixman_region32_intersect(&opaque, &opaque, &node->visible); + + wlr_region_scale(&opaque, &opaque, scene_output->output->scale); + pixman_region32_subtract(&background, &background, &opaque); + pixman_region32_fini(&opaque); } } From d94d1bf0ea9d777a03429a20c544195402965d9b Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sat, 27 Aug 2022 12:20:03 +0200 Subject: [PATCH 285/298] output: clean up after modifierless test failure If the first test in output_ensure_buffer() fails with modifiers we replace the swapchain with a modifierless swapchain and try again. However if that fails as well the output is currently stuck without modifiers until the next modeset. To fix this, destroy the modifierless swapchain if the test using it fails. The next output_attach_back_buffer() call will create a swapchain that allows modifiers when needed. --- types/output/render.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/types/output/render.c b/types/output/render.c index 2e38919a1..eaacf8a06 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -240,7 +240,7 @@ bool output_ensure_buffer(struct wlr_output *output, } if (!output_attach_empty_back_buffer(output, state)) { - return false; + goto error_destroy_swapchain; } if (output_test_with_back_buffer(output, state)) { @@ -250,6 +250,13 @@ bool output_ensure_buffer(struct wlr_output *output, output_clear_back_buffer(output); +error_destroy_swapchain: + // Destroy the modifierless swapchain so that the output does not get stuck + // without modifiers. A new swapchain with modifiers will be created when + // needed by output_attach_back_buffer(). + wlr_swapchain_destroy(output->swapchain); + output->swapchain = NULL; + return false; } From eee0f5e71f4e3a6ded27d2d5046a243277c00ab8 Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Date: Sun, 28 Aug 2022 16:32:09 -0300 Subject: [PATCH 286/298] render/vulkan: fix memory type detection From a comment by emersion: > There is a logic error here: we pass 0xFFFFFFFF to vulkan_find_mem_type, which > returns an index, and then we logical-and that with mem_reqs.memoryTypeBits. > Instead we should pass mem_reqs.memoryTypeBits to vulkan_find_mem_type and use > the result for the memoryTypeIndex field directly. Ideally checking for errors > (-1 return value) in case no memory type is suitable. Closes: #3470 --- render/vulkan/texture.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 88298d93a..52356f640 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -270,8 +270,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_r texture->format = &fmt->format; // create image - unsigned mem_bits = 0xFFFFFFFF; - VkImageCreateInfo img_info = {0}; img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; img_info.imageType = VK_IMAGE_TYPE_2D; @@ -286,8 +284,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_r img_info.tiling = VK_IMAGE_TILING_OPTIMAL; img_info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - mem_bits = vulkan_find_mem_type(renderer->dev, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mem_bits); VkImageLayout layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; res = vkCreateImage(dev, &img_info, NULL, &texture->image); @@ -303,7 +299,15 @@ static struct wlr_texture *vulkan_texture_from_pixels(struct wlr_renderer *wlr_r VkMemoryAllocateInfo mem_info = {0}; mem_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; mem_info.allocationSize = mem_reqs.size; - mem_info.memoryTypeIndex = mem_bits & mem_reqs.memoryTypeBits; + + int mem_type_index = vulkan_find_mem_type(renderer->dev, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mem_reqs.memoryTypeBits); + if (mem_type_index == -1) { + wlr_log(WLR_ERROR, "failed to find suitable vulkan memory type"); + goto error; + } + mem_info.memoryTypeIndex = mem_type_index; + res = vkAllocateMemory(dev, &mem_info, NULL, &texture->memories[0]); if (res != VK_SUCCESS) { wlr_vk_error("vkAllocatorMemory failed", res); From 20c208d46a140e148da29730a3adbfa9b88de467 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 19 Aug 2022 21:19:30 +0300 Subject: [PATCH 287/298] util/array: unclutter --- include/util/array.h | 17 ---------- include/util/set.h | 25 +++++++++++++++ types/seat/wlr_seat_pointer.c | 2 +- types/tablet_v2/wlr_tablet_v2_tool.c | 2 +- types/wlr_keyboard.c | 2 +- util/array.c | 46 --------------------------- util/meson.build | 1 + util/set.c | 47 ++++++++++++++++++++++++++++ 8 files changed, 76 insertions(+), 66 deletions(-) create mode 100644 include/util/set.h create mode 100644 util/set.c diff --git a/include/util/array.h b/include/util/array.h index 2b7278ccc..a51bdb640 100644 --- a/include/util/array.h +++ b/include/util/array.h @@ -1,27 +1,10 @@ #ifndef UTIL_ARRAY_H #define UTIL_ARRAY_H -#include #include #include #include -size_t push_zeroes_to_end(uint32_t arr[], size_t n); - -/** - * Add `target` to `values` if it doesn't exist - * "set"s should only be modified with set_* functions - * Values MUST be greater than 0 - */ -bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target); - -/** - * Remove `target` from `values` if it exists - * "set"s should only be modified with set_* functions - * Values MUST be greater than 0 - */ -bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target); - /** * Remove a chunk of memory of the specified size at the specified offset. */ diff --git a/include/util/set.h b/include/util/set.h new file mode 100644 index 000000000..41099621a --- /dev/null +++ b/include/util/set.h @@ -0,0 +1,25 @@ +#ifndef UTIL_SET_H +#define UTIL_SET_H + +#include +#include +#include + +size_t push_zeroes_to_end(uint32_t arr[], size_t n); + +/** + * Add `target` to `values` if it doesn't exist + * "set"s should only be modified with set_* functions + * Values MUST be greater than 0 + */ +bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target); + +/** + * Remove `target` from `values` if it exists + * "set"s should only be modified with set_* functions + * Values MUST be greater than 0 + */ +bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target); + +#endif + diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 5a6cb2359..8d6154b02 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -7,7 +7,7 @@ #include #include #include "types/wlr_seat.h" -#include "util/array.h" +#include "util/set.h" static void default_pointer_enter(struct wlr_seat_pointer_grab *grab, struct wlr_surface *surface, double sx, double sy) { diff --git a/types/tablet_v2/wlr_tablet_v2_tool.c b/types/tablet_v2/wlr_tablet_v2_tool.c index a2d7778c9..9590cd887 100644 --- a/types/tablet_v2/wlr_tablet_v2_tool.c +++ b/types/tablet_v2/wlr_tablet_v2_tool.c @@ -10,7 +10,7 @@ #include #include #include -#include "util/array.h" +#include "util/set.h" #include "util/time.h" #include "tablet-unstable-v2-protocol.h" diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c index 3fe3ba7a5..5150af877 100644 --- a/types/wlr_keyboard.c +++ b/types/wlr_keyboard.c @@ -8,7 +8,7 @@ #include #include "interfaces/wlr_input_device.h" #include "types/wlr_keyboard.h" -#include "util/array.h" +#include "util/set.h" #include "util/shm.h" #include "util/time.h" diff --git a/util/array.c b/util/array.c index 9da261270..ec16a7b13 100644 --- a/util/array.c +++ b/util/array.c @@ -2,52 +2,6 @@ #include #include -// https://www.geeksforgeeks.org/move-zeroes-end-array/ -size_t push_zeroes_to_end(uint32_t arr[], size_t n) { - size_t count = 0; - - for (size_t i = 0; i < n; i++) { - if (arr[i] != 0) { - arr[count++] = arr[i]; - } - } - - size_t ret = count; - - while (count < n) { - arr[count++] = 0; - } - - return ret; -} - -bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target) { - if (*len == cap) { - return false; - } - for (uint32_t i = 0; i < *len; ++i) { - if (values[i] == target) { - return false; - } - } - values[(*len)++] = target; - return false; -} - -bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target) { - for (uint32_t i = 0; i < *len; ++i) { - if (values[i] == target) { - // Set to 0 and swap with the end element so that - // zeroes exist only after all the values. - size_t last_elem_pos = --(*len); - values[i] = values[last_elem_pos]; - values[last_elem_pos] = 0; - return true; - } - } - return false; -} - void array_remove_at(struct wl_array *arr, size_t offset, size_t size) { assert(arr->size >= offset + size); diff --git a/util/meson.build b/util/meson.build index 34fc2e232..1cd7f65c9 100644 --- a/util/meson.build +++ b/util/meson.build @@ -6,6 +6,7 @@ wlr_files += files( 'global.c', 'log.c', 'region.c', + 'set.c', 'shm.c', 'time.c', 'token.c', diff --git a/util/set.c b/util/set.c new file mode 100644 index 000000000..b3aa18ff4 --- /dev/null +++ b/util/set.c @@ -0,0 +1,47 @@ +#include "util/set.h" + +// https://www.geeksforgeeks.org/move-zeroes-end-array/ +size_t push_zeroes_to_end(uint32_t arr[], size_t n) { + size_t count = 0; + + for (size_t i = 0; i < n; i++) { + if (arr[i] != 0) { + arr[count++] = arr[i]; + } + } + + size_t ret = count; + + while (count < n) { + arr[count++] = 0; + } + + return ret; +} + +bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target) { + if (*len == cap) { + return false; + } + for (uint32_t i = 0; i < *len; ++i) { + if (values[i] == target) { + return false; + } + } + values[(*len)++] = target; + return false; +} + +bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target) { + for (uint32_t i = 0; i < *len; ++i) { + if (values[i] == target) { + // Set to 0 and swap with the end element so that + // zeroes exist only after all the values. + size_t last_elem_pos = --(*len); + values[i] = values[last_elem_pos]; + values[last_elem_pos] = 0; + return true; + } + } + return false; +} From 7333a4602a333c8710ada6f8a16435745aa4a557 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Fri, 19 Aug 2022 21:20:43 +0300 Subject: [PATCH 288/298] util/set: overhaul --- include/util/set.h | 26 ++++++++------ types/tablet_v2/wlr_tablet_v2_tool.c | 52 ++++++++-------------------- util/set.c | 46 +++++++----------------- 3 files changed, 41 insertions(+), 83 deletions(-) diff --git a/include/util/set.h b/include/util/set.h index 41099621a..d6330108a 100644 --- a/include/util/set.h +++ b/include/util/set.h @@ -2,24 +2,28 @@ #define UTIL_SET_H #include -#include #include - -size_t push_zeroes_to_end(uint32_t arr[], size_t n); +#include /** - * Add `target` to `values` if it doesn't exist - * "set"s should only be modified with set_* functions - * Values MUST be greater than 0 + * Add target to values. + * + * Target is added to the end of the set. + * + * Returns the index of target, or -1 if the set is full or target already + * exists. */ -bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target); +ssize_t set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target); /** - * Remove `target` from `values` if it exists - * "set"s should only be modified with set_* functions - * Values MUST be greater than 0 + * Remove target from values. + * + * When target is removed, the last element of the set is moved to where + * target was. + * + * Returns the previous index of target, or -1 if target wasn't in values. */ -bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target); +ssize_t set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target); #endif diff --git a/types/tablet_v2/wlr_tablet_v2_tool.c b/types/tablet_v2/wlr_tablet_v2_tool.c index 9590cd887..df8ab7618 100644 --- a/types/tablet_v2/wlr_tablet_v2_tool.c +++ b/types/tablet_v2/wlr_tablet_v2_tool.c @@ -257,50 +257,26 @@ struct wlr_tablet_tool_client_v2 *tablet_tool_client_from_resource(struct wl_res return wl_resource_get_user_data(resource); } - -/* Actual protocol foo */ - -// Button 0 is KEY_RESERVED in input-event-codes on linux (and freebsd) static ssize_t tablet_tool_button_update(struct wlr_tablet_v2_tablet_tool *tool, uint32_t button, enum zwp_tablet_pad_v2_button_state state) { - bool found = false; - size_t i = 0; - for (; i < tool->num_buttons; ++i) { - if (tool->pressed_buttons[i] == button) { - found = true; - wlr_log(WLR_DEBUG, "Found the button \\o/: %u", button); - break; - - } - } - - if (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED && found) { - /* Already have the button saved, durr */ - return -1; - } - - if (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED && !found) { - if (tool->num_buttons < WLR_TABLET_V2_TOOL_BUTTONS_CAP) { - i = tool->num_buttons++; - tool->pressed_buttons[i] = button; + ssize_t i; + if (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED) { + i = set_add(tool->pressed_buttons, &tool->num_buttons, + WLR_TABLET_V2_TOOL_BUTTONS_CAP, button); + if (i != -1) { tool->pressed_serials[i] = -1; } else { - i = -1; - wlr_log(WLR_ERROR, "You pressed more than %d tablet tool buttons. " - "This is currently not supported by wlroots. Please report this " - "with a description of your tablet, since this is either a " - "bug, or fancy hardware", WLR_TABLET_V2_TOOL_BUTTONS_CAP); + wlr_log(WLR_ERROR, "Failed to add tablet tool button %x", button); + } + } else { + i = set_remove(tool->pressed_buttons, &tool->num_buttons, + WLR_TABLET_V2_TOOL_BUTTONS_CAP, button); + if (i != -1) { + tool->pressed_serials[i] = tool->pressed_serials[tool->num_buttons]; + } else { + wlr_log(WLR_ERROR, "Failed to remove tablet tool button %x", button); } } - if (state == ZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED && found) { - wlr_log(WLR_DEBUG, "Removed the button \\o/: %u", button); - tool->pressed_buttons[i] = 0; - tool->pressed_serials[i] = 0; - tool->num_buttons = push_zeroes_to_end(tool->pressed_buttons, WLR_TABLET_V2_TOOL_BUTTONS_CAP); - tool->num_buttons = push_zeroes_to_end(tool->pressed_serials, WLR_TABLET_V2_TOOL_BUTTONS_CAP); - } - - assert(tool->num_buttons <= WLR_TABLET_V2_TOOL_BUTTONS_CAP); return i; } diff --git a/util/set.c b/util/set.c index b3aa18ff4..1366d04f8 100644 --- a/util/set.c +++ b/util/set.c @@ -1,47 +1,25 @@ #include "util/set.h" -// https://www.geeksforgeeks.org/move-zeroes-end-array/ -size_t push_zeroes_to_end(uint32_t arr[], size_t n) { - size_t count = 0; - - for (size_t i = 0; i < n; i++) { - if (arr[i] != 0) { - arr[count++] = arr[i]; +ssize_t set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target) { + for (uint32_t i = 0; i < *len; ++i) { + if (values[i] == target) { + return i; } } - - size_t ret = count; - - while (count < n) { - arr[count++] = 0; - } - - return ret; -} - -bool set_add(uint32_t values[], size_t *len, size_t cap, uint32_t target) { if (*len == cap) { - return false; + return -1; } - for (uint32_t i = 0; i < *len; ++i) { - if (values[i] == target) { - return false; - } - } - values[(*len)++] = target; - return false; + values[*len] = target; + return (*len)++; } -bool set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target) { +ssize_t set_remove(uint32_t values[], size_t *len, size_t cap, uint32_t target) { for (uint32_t i = 0; i < *len; ++i) { if (values[i] == target) { - // Set to 0 and swap with the end element so that - // zeroes exist only after all the values. - size_t last_elem_pos = --(*len); - values[i] = values[last_elem_pos]; - values[last_elem_pos] = 0; - return true; + --(*len); + values[i] = values[*len]; + return i; } } - return false; + return -1; } From fe9e193ab5958760b1d6cbeb839fc2836bb124c9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 28 Aug 2022 11:01:19 -0400 Subject: [PATCH 289/298] wlr_scene: More sanity checking The render list should neither contain scene trees or null buffers. --- types/scene/wlr_scene.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 5e5f80039..3088db7c0 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1043,7 +1043,7 @@ static void scene_node_render(struct wlr_scene_node *node, enum wl_output_transform transform; switch (node->type) { case WLR_SCENE_NODE_TREE: - /* Root or tree node has nothing to render itself */ + assert(false); break; case WLR_SCENE_NODE_RECT:; struct wlr_scene_rect *scene_rect = scene_rect_from_node(node); @@ -1053,9 +1053,7 @@ static void scene_node_render(struct wlr_scene_node *node, break; case WLR_SCENE_NODE_BUFFER:; struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); - if (!scene_buffer->buffer) { - return; - } + assert(scene_buffer->buffer); struct wlr_renderer *renderer = output->renderer; texture = scene_buffer_get_texture(scene_buffer, renderer); From 78cf39b6bd7e82f6d55bb6ef2707f69da150e109 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sat, 27 Aug 2022 20:35:18 -0400 Subject: [PATCH 290/298] wlr_scene: Don't leak a region32 when texture failed to upload --- types/scene/wlr_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 3088db7c0..d963e70a2 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1058,7 +1058,7 @@ static void scene_node_render(struct wlr_scene_node *node, struct wlr_renderer *renderer = output->renderer; texture = scene_buffer_get_texture(scene_buffer, renderer); if (texture == NULL) { - return; + break; } transform = wlr_output_transform_invert(scene_buffer->transform); From 138d21464df551dddad4243efb0bc38226110957 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Tue, 30 Aug 2022 03:03:21 -0400 Subject: [PATCH 291/298] wlr_compositor: Don't leak region32 when calculating opaque region --- types/wlr_compositor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index cb0267833..f6bbcd029 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -386,6 +386,7 @@ static void surface_update_opaque_region(struct wlr_surface *surface) { } if (surface->opaque) { + pixman_region32_fini(&surface->opaque_region); pixman_region32_init_rect(&surface->opaque_region, 0, 0, surface->current.width, surface->current.height); return; From 4462f5dcb38b8b4ddc4c1eb888aa0d0c859a10a1 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 30 Aug 2022 19:18:42 +0300 Subject: [PATCH 292/298] cursor: avoid uninitialized wlr_box fields --- types/wlr_cursor.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 5da51d27f..aafae2482 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -236,19 +236,22 @@ static void cursor_warp_unchecked(struct wlr_cursor *cur, * Absolute movement for touch and pen devices will be relative to this box and * pointer movement will be constrained to this box. * - * If none of these are set, empties the box and absolute movement should be + * If none of these are set, the box is empty and absolute movement should be * relative to the extents of the layout. */ static void get_mapping(struct wlr_cursor *cur, struct wlr_input_device *dev, struct wlr_box *box) { assert(cur->state->layout); - struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); + memset(box, 0, sizeof(*box)); + + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); if (c_device) { if (!wlr_box_empty(&c_device->mapped_box)) { *box = c_device->mapped_box; return; - } else if (c_device->mapped_output) { + } + if (c_device->mapped_output) { wlr_output_layout_get_box(cur->state->layout, c_device->mapped_output, box); return; @@ -257,11 +260,12 @@ static void get_mapping(struct wlr_cursor *cur, if (!wlr_box_empty(&cur->state->mapped_box)) { *box = cur->state->mapped_box; - } else if (cur->state->mapped_output) { + return; + } + if (cur->state->mapped_output) { wlr_output_layout_get_box(cur->state->layout, cur->state->mapped_output, box); - } else { - box->width = box->height = 0; + return; } } @@ -868,19 +872,21 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur, void wlr_cursor_map_to_region(struct wlr_cursor *cur, const struct wlr_box *box) { + memset(&cur->state->mapped_box, 0, sizeof(cur->state->mapped_box)); + if (box) { if (wlr_box_empty(box)) { wlr_log(WLR_ERROR, "cannot map cursor to an empty region"); return; } cur->state->mapped_box = *box; - } else { - cur->state->mapped_box.width = cur->state->mapped_box.height = 0; } } void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, struct wlr_input_device *dev, const struct wlr_box *box) { + memset(&cur->state->mapped_box, 0, sizeof(cur->state->mapped_box)); + struct wlr_cursor_device *c_device = get_cursor_device(cur, dev); if (!c_device) { wlr_log(WLR_ERROR, "Cannot map device \"%s\" to geometry (not found in" @@ -896,7 +902,5 @@ void wlr_cursor_map_input_to_region(struct wlr_cursor *cur, return; } c_device->mapped_box = *box; - } else { - c_device->mapped_box.width = c_device->mapped_box.height = 0; } } From 2ea80eb115a74ed2047fc19914f0c04f18bb7e5e Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 30 Aug 2022 19:19:47 +0300 Subject: [PATCH 293/298] output-layout: avoid uninitialized wlr_box fields --- types/wlr_output_layout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 319b7cf78..275f87d74 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -365,6 +365,8 @@ void wlr_output_layout_closest_point(struct wlr_output_layout *layout, void wlr_output_layout_get_box(struct wlr_output_layout *layout, struct wlr_output *reference, struct wlr_box *dest_box) { + memset(dest_box, 0, sizeof(*dest_box)); + struct wlr_output_layout_output *l_output; if (reference) { // output extents @@ -372,8 +374,6 @@ void wlr_output_layout_get_box(struct wlr_output_layout *layout, if (l_output) { output_layout_output_get_box(l_output, dest_box); - } else { - dest_box->width = dest_box->height = 0; } } else { // layout extents From 26e1812ab3eb75ba5c13f1a4060dd74fb4c93263 Mon Sep 17 00:00:00 2001 From: Kirill Primak Date: Tue, 30 Aug 2022 19:22:33 +0300 Subject: [PATCH 294/298] output-layout: improve wlr_output_layout_output_in_direction() Now the function checks if the reference output belongs to the layout, and returns NULL if it doesn't. --- types/wlr_output_layout.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 275f87d74..37c57fc66 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -459,6 +459,10 @@ static struct wlr_output *wlr_output_layout_output_in_direction( struct wlr_box ref_box; wlr_output_layout_get_box(layout, reference, &ref_box); + if (wlr_box_empty(&ref_box)) { + // The output doesn't belong to the layout + return NULL; + } double min_distance = (distance_method == NEAREST) ? DBL_MAX : DBL_MIN; struct wlr_output *closest_output = NULL; From 8c70245d5fe044f09882653437e0a9dc7c336a0c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 18 Jun 2021 12:40:07 +0200 Subject: [PATCH 295/298] output: fail commits if adaptive sync cannot be enabled Previously, adaptive sync was just a hint and wouldn't make any atomic commit fail if the backend didn't support it. The main reason is wlr_output_test wasn't supported at the time. Now that we have a way for compositors to test whether a change can work, let's remove the exception for adaptive sync and convert it to a regular output state field. --- backend/drm/atomic.c | 6 ++++-- backend/drm/drm.c | 9 ++++++++- backend/drm/legacy.c | 6 ++++-- backend/x11/output.c | 3 ++- include/wlr/interfaces/wlr_output.h | 1 - include/wlr/types/wlr_output.h | 5 ++++- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index ab1b21601..05d011251 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -254,8 +254,10 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, bool prev_vrr_enabled = output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED; bool vrr_enabled = prev_vrr_enabled; - if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) && - drm_connector_supports_vrr(conn)) { + if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED)) { + if (!drm_connector_supports_vrr(conn)) { + return false; + } vrr_enabled = state->base->adaptive_sync_enabled; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 94dd7023c..06548ed07 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -36,7 +36,8 @@ static const uint32_t COMMIT_OUTPUT_STATE = WLR_OUTPUT_STATE_BUFFER | WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_ENABLED | - WLR_OUTPUT_STATE_GAMMA_LUT; + WLR_OUTPUT_STATE_GAMMA_LUT | + WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE; @@ -489,6 +490,12 @@ static bool drm_connector_test(struct wlr_output *output, } } + if ((state->committed & WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) && + state->adaptive_sync_enabled && + !drm_connector_supports_vrr(conn)) { + return false; + } + struct wlr_drm_connector_state pending = {0}; drm_connector_state_init(&pending, conn, state); diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c index 84e8a914f..bd8813e83 100644 --- a/backend/drm/legacy.c +++ b/backend/drm/legacy.c @@ -115,8 +115,10 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn, } } - if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) && - drm_connector_supports_vrr(conn)) { + if (state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { + if (!drm_connector_supports_vrr(conn)) { + return false; + } if (drmModeObjectSetProperty(drm->fd, crtc->id, DRM_MODE_OBJECT_CRTC, crtc->props.vrr_enabled, state->base->adaptive_sync_enabled) != 0) { diff --git a/backend/x11/output.c b/backend/x11/output.c index f56129ab7..0e124f9a9 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -26,7 +26,8 @@ static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | WLR_OUTPUT_STATE_BUFFER | - WLR_OUTPUT_STATE_MODE; + WLR_OUTPUT_STATE_MODE | + WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; static void parse_xcb_setup(struct wlr_output *output, xcb_connection_t *xcb) { diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 7a1252db8..7ef3de98e 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -22,7 +22,6 @@ WLR_OUTPUT_STATE_SCALE | \ WLR_OUTPUT_STATE_TRANSFORM | \ WLR_OUTPUT_STATE_RENDER_FORMAT | \ - WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED | \ WLR_OUTPUT_STATE_SUBPIXEL) /** diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 4f8bff0df..2a290b465 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -301,7 +301,10 @@ void wlr_output_set_transform(struct wlr_output *output, enum wl_output_transform transform); /** * Enables or disables adaptive sync (ie. variable refresh rate) on this - * output. This is just a hint, the backend is free to ignore this setting. + * output. On some backends, this is just a hint and may be ignored. + * Compositors can inspect `wlr_output.adaptive_sync_status` to query the + * effective status. Backends that don't support adaptive sync will reject + * the output commit. * * When enabled, compositors can submit frames a little bit later than the * deadline without dropping a frame. From 2ec27d23e01377b341346036176cdc2faf0662cf Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 28 Jun 2022 19:55:48 +0200 Subject: [PATCH 296/298] backend/wayland: report adaptive sync as enabled Adaptive sync is effectively always enabled when using the Wayland backend. This is not something we have control over, so we set the state to enabled on creating the output and never allow changing it. --- backend/wayland/output.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 36b3911b1..28fa5e99d 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -29,7 +29,8 @@ static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | WLR_OUTPUT_STATE_BUFFER | - WLR_OUTPUT_STATE_MODE; + WLR_OUTPUT_STATE_MODE | + WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED; static struct wlr_wl_output *get_wl_output_from_output( struct wlr_output *wlr_output) { @@ -251,6 +252,16 @@ static bool output_test(struct wlr_output *wlr_output, return false; } + // Adaptive sync is effectively always enabled when using the Wayland + // backend. This is not something we have control over, so we set the state + // to enabled on creating the output and never allow changing it. + assert(wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED); + if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { + if (!state->adaptive_sync_enabled) { + return false; + } + } + if (state->committed & WLR_OUTPUT_STATE_MODE) { assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); } @@ -521,6 +532,8 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { wlr_output_update_custom_mode(wlr_output, 1280, 720, 0); + wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED; + char name[64]; snprintf(name, sizeof(name), "WL-%zu", ++backend->last_output_num); wlr_output_set_name(wlr_output, name); From 135e60ff8210d7194a67fda1125a74ee102eb2e8 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 28 Jun 2022 19:57:49 +0200 Subject: [PATCH 297/298] backend/x11: report adaptive sync as enabled All we can do to influence adaptive sync on the X11 backend is set the _VARIABLE_REFRESH window property like mesa automatically does. We don't have any control beyond that, so we set the state to enabled on creating the output and never allow changing it (just like the Wayland backend). --- backend/x11/output.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/backend/x11/output.c b/backend/x11/output.c index 0e124f9a9..f109757dd 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -113,6 +113,17 @@ static bool output_test(struct wlr_output *wlr_output, return false; } + // All we can do to influence adaptive sync on the X11 backend is set the + // _VARIABLE_REFRESH window property like mesa automatically does. We don't + // have any control beyond that, so we set the state to enabled on creating + // the output and never allow changing it (just like the Wayland backend). + assert(wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED); + if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { + if (!state->adaptive_sync_enabled) { + return false; + } + } + if (state->committed & WLR_OUTPUT_STATE_MODE) { assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); } @@ -335,21 +346,6 @@ static bool output_commit(struct wlr_output *wlr_output, } } - if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED && - x11->atoms.variable_refresh != XCB_ATOM_NONE) { - if (state->adaptive_sync_enabled) { - uint32_t enabled = 1; - xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win, - x11->atoms.variable_refresh, XCB_ATOM_CARDINAL, 32, 1, - &enabled); - wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_UNKNOWN; - } else { - xcb_delete_property(x11->xcb, output->win, - x11->atoms.variable_refresh); - wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED; - } - } - if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (!output_commit_buffer(output, state)) { return false; @@ -574,6 +570,12 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) { x11->atoms.wm_protocols, XCB_ATOM_ATOM, 32, 1, &x11->atoms.wm_delete_window); + uint32_t enabled = 1; + xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win, + x11->atoms.variable_refresh, XCB_ATOM_CARDINAL, 32, 1, + &enabled); + wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED; + wlr_x11_output_set_title(wlr_output, NULL); xcb_map_window(x11->xcb, output->win); From fd0b0276c9ecc159549acff48b932b83ec3b4f12 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 28 Jun 2022 19:58:26 +0200 Subject: [PATCH 298/298] output: remove unknown adaptive sync state This was previously used by the X11 backend but is no longer required since the previous commit. --- include/wlr/types/wlr_output.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 2a290b465..01a9d49f0 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -45,7 +45,6 @@ struct wlr_output_cursor { enum wlr_output_adaptive_sync_status { WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED, WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED, - WLR_OUTPUT_ADAPTIVE_SYNC_UNKNOWN, // requested, but maybe disabled }; enum wlr_output_state_field {