From 7d07dfd960f6fc78477b10cb84a30076ecbe29df Mon Sep 17 00:00:00 2001 From: project-repo Date: Mon, 7 Oct 2024 16:52:56 +0000 Subject: [PATCH] Release 2.4.0 - Migrate to wlroots 0.18 - Improve documentation - CONTRIBUTING.md - README.md - Drop privilege correctly, even on some BSDs #81 (would be denial of service, not priv escalation) - Improve resilience by mirroring packages, doc and code elsewhere - Add setmodecursor command - Fix typo in FAQ (#76 by meisme-dev) --- CONTRIBUTING.md | 35 +- FAQ.md | 2 +- Hashes.md | 20 + README.md | 17 +- cagebreak.c | 61 ++-- fuzz/execl_override.c | 2 - fuzz/fuzz-lib.c | 23 +- idle_inhibit_v1.c | 3 +- input_manager.c | 17 +- ipc_server.c | 6 +- keybinding.c | 41 ++- keybinding.h | 2 + libinput.c | 2 +- man/cagebreak-config.5.md | 2 +- man/cagebreak-socket.7.md | 2 +- man/cagebreak.1.md | 2 +- meson.build | 31 +- message.c | 16 +- message.h | 2 + output.c | 90 +++-- parse.c | 28 +- release-non-auto-checks/Bugs.md | 4 +- release-non-auto-checks/FAQ.md | 4 +- release-non-auto-checks/SECURITY.md | 4 +- release-non-auto-checks/WLR_XDG_VERSION | 4 +- .../acknowledge-contributors | 4 +- release-non-auto-checks/archwiki | 4 +- release-non-auto-checks/changelog-major-minor | 4 +- release-non-auto-checks/internal-wiki | 4 +- release-non-auto-checks/release-note | 4 +- .../reproducibility-checked | 4 +- .../security-to-man-page-info-transfer | 4 +- release-non-auto-checks/version-restrictions | 4 +- scripts/fuzz | 2 +- seat.c | 26 +- seat.h | 2 +- server.h | 4 +- signatures/2.3.1-cagebreak-config.5.sig | Bin 0 -> 566 bytes signatures/2.3.1-cagebreak-socket.7.sig | Bin 0 -> 566 bytes signatures/2.3.1-cagebreak.1.sig | Bin 0 -> 566 bytes signatures/2.3.1-cagebreak.sig | Bin 0 -> 566 bytes signatures/cagebreak-config.5.sig | Bin 566 -> 566 bytes signatures/cagebreak-socket.7.sig | Bin 566 -> 566 bytes signatures/cagebreak.1.sig | Bin 566 -> 566 bytes signatures/cagebreak.sig | Bin 566 -> 566 bytes view.c | 9 +- workspace.c | 8 +- workspace.h | 3 +- xdg_shell.c | 344 +++++++++++------- xdg_shell.h | 22 +- xwayland.c | 24 +- xwayland.h | 1 + 52 files changed, 546 insertions(+), 351 deletions(-) create mode 100644 signatures/2.3.1-cagebreak-config.5.sig create mode 100644 signatures/2.3.1-cagebreak-socket.7.sig create mode 100644 signatures/2.3.1-cagebreak.1.sig create mode 100644 signatures/2.3.1-cagebreak.sig diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4da2ae2..285cbef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,8 +45,7 @@ at the time of release. However, Cagebreak may also work on other distributions given the proper library versions (Some package maintainers have done this and it -seems to work (To date, we dealt with a few Issues and never felt the -need to ask for the distribution the user was having the issue on.)). +seems to work. [![Packaging status](https://repology.org/badge/vertical-allrepos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) @@ -120,12 +119,6 @@ time has to be set in `meson.build`: meson compile adjust-epoch -C build ``` -or - -``` -./scripts/adjust-epoch -``` - #### Git tag If you are on the master branch, everything is ready and you want to create @@ -138,12 +131,6 @@ meson compile git-tag -C build If you want to use another signing key than the prespecified one, configure Cagebreak with `-Dgpg_id=GPGID`. -``` -./scripts/git-tag GPGID CBVERSION -``` - -can be used alternatively. - #### Output Hashes Hashes of release versions of all binaries can be output to `local-hashes.txt` @@ -153,14 +140,6 @@ via: meson compile output-hashes -C build ``` -Or - -``` -./scripts/output-hashes VERSION -``` - -if meson is unavailable. - #### Create Signatures Creation of signatures for releases can be achieved through: @@ -172,12 +151,6 @@ meson compile create-sigs -C build Configure Cagebreak with `-Dgpg_id=GPGID` for a different gpg signing key. -Without meson use: - -``` -./scripts/create-signatures GPGID -``` - #### Set Version Number Once the version number is set within meson.build, you can use @@ -304,12 +277,6 @@ We have found code path discovery to increase rapidly when the fuzzer is supplie with an initial config file. We are working on improving our fuzzing coverage to find bugs in other areas of the code. -### Caveat - -Currently, there are memory leaks which do not seem to stem from our code but rather -the code of wlroots or some other library we depend on. We are working on the problem. -In the meantime, add `-Db_detect-leaks=0` to the meson command to exclude memory leaks. - ## Reproducible Builds Cagebreak offers reproducible builds given the exact library versions specified diff --git a/FAQ.md b/FAQ.md index 83fd29b..38499b2 100644 --- a/FAQ.md +++ b/FAQ.md @@ -42,7 +42,7 @@ Execute the following commands with the appropriate env vars: ``` export XDG_SESSION_TYPE=wayland -export XDG_CURRENT_DESKTIP=sway +export XDG_CURRENT_DESKTOP=sway /usr/lib/xdg-desktop-portal -r /usr/lib/xdg-desktop-portal-wlr ``` diff --git a/Hashes.md b/Hashes.md index 7f0018a..b319cca 100644 --- a/Hashes.md +++ b/Hashes.md @@ -1,5 +1,25 @@ # Hashes +2.4.0 cagebreak + + * sha 256: 510b848cde5719234338d7e4e710233f69c08c3b3953bdda5d1f021bd66996a9 + * sha 512: 6645e9a27aef030ac065edde7bf7f8d3c9e75ea2efc72016cbe639b93fbf2d5a961c93b0c7f0dbaf2b35655c75c74cf8d84a1aba98c49fb51868065d5d17f478 + +2.4.0 cagebreak.1 + + * sha 256: 9cf5b33bebe9778a0c670ce9723692f1788684ea26a8fe33fa100c8f9bbab3a8 + * sha 512: fb4fa9fc4e1b95aef54f5411c312b6b50b65442abd98c22ede6a18ff354769d31b2b7949a85e133af73ca0d2a89d6706bc2eca8c1c84727c5e7fbf2a35e0d582 + +2.4.0 cagebreak-config.5 + + * sha 256: ce12966517e2f3bcbb5fba2c82ae6aaed2ec072d19ecea609dade802085271ab + * sha 512: 420872f557347d16993765e91fbe475d3290ff562e9f63e97395b71078fc29fa21e29adcc90d8b5abe98f61e2563aab65bc86e5b6c2bb1304a3b0c22aa8005a9 + +2.4.0 cagebreak-socket.7 + + * sha 256: ddf4b9150f15f225bfcd4dbdc2255d3a355ccd1ed9abc68c7c7b874b63226d34 + * sha 512: 5bbeed9b5539fd0ca10241589bafc714c9e539ee6d46f9c8c9054b483ad32140b70c0e45996175ec9a72c9fb0e08651fbd7734fdbd3ba2ee8b04c43abe4ce98a + 2.3.1 cagebreak * sha 256: 51d76608726a6251690d6dd1371cdfaa6eae5188a08798cda9c9280b3fcbe3fa diff --git a/README.md b/README.md index c4ce338..a91d21c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Cagebreak: A Tiling Wayland Compositor -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6532/badge)](https://bestpractices.coreinfrastructure.org/projects/6532) [![Packaging status](https://repology.org/badge/tiny-repos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) [![AUR package](https://repology.org/badge/version-for-repo/aur/cagebreak.svg?minversion=2.3.1)](https://repology.org/project/cagebreak/versions) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6532/badge)](https://bestpractices.coreinfrastructure.org/projects/6532) [![Packaging status](https://repology.org/badge/tiny-repos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) [![AUR package](https://repology.org/badge/version-for-repo/aur/cagebreak.svg?minversion=2.4.0)](https://repology.org/project/cagebreak/versions) [![Contact](img/mail.svg)](SECURITY.md) [![Manuals](img/manuals.svg)](manuals.md) [![FAQ](img/faq.svg)](FAQ.md) [![CONTRIBUTING](img/contributing.svg)](CONTRIBUTING.md) [![ArchWiki](img/archwiki.svg)](https://wiki.archlinux.org/title/Cagebreak) [![AUR](img/aur.svg)](https://aur.archlinux.org/packages?O=0&K=cagebreak) @@ -178,6 +178,21 @@ as a source of inspiration and explanation for certain particularities. > Example scripts can be found in the repository under `example_scripts/`. +## Resilience + +To become more resilient to outages of GitHub, we have created a [website](https://cagebreak.project-repo.co). + +It is not possible to open issues on the website directly, use the mail contact +if GitHub is down. + +The following links may be useful: + + * [Artefacts mirror](https://cagebreak.project-repo.co/release-artefacts.html) + * [PKGBUILD depending on the mirror](https://cagebreak.project-repo.co/cb-red-pkgb/PKGBUILD) + * [binary PKGBUILD depending on the mirror](https://cagebreak.project-repo.co/cb-red-bin-pkgb/PKGBUILD) + * [cagebreak repo mirror](https://cagebreak.project-repo.co/cagebreak.git) + * [cagebreak-bin repo mirror](https://cagebreak.project-repo.co/cagebreak-pkgbuild.git) + ## Roadmap Cagebreak plans to do or keep doing the following things diff --git a/cagebreak.c b/cagebreak.c index 9ce99b8..00886e2 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +83,16 @@ set_sig_handler(int sig, void (*action)(int)) { static bool drop_permissions(void) { if(getuid() != geteuid() || getgid() != getegid()) { + // Drop ancillary groups + gid_t gid = getgid(); + setgroups(1, &gid); // Set gid before uid +#ifdef linux if(setgid(getgid()) != 0 || setuid(getuid()) != 0) { +#else + if(setregid(getgid(), getgid()) != 0 || + setreuid(getuid(), getuid()) != 0) { +#endif wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); return false; } @@ -278,15 +286,17 @@ main(int argc, char *argv[]) { struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; struct wlr_data_control_manager_v1 *data_control_manager = NULL; struct wlr_viewporter *viewporter = NULL; - struct wlr_presentation *presentation = NULL; struct wlr_xdg_output_manager_v1 *output_manager = NULL; struct wlr_xdg_shell *xdg_shell = NULL; wl_list_init(&server.input_config); wl_list_init(&server.output_config); wl_list_init(&server.output_priorities); + wl_list_init(&server.xdg_decorations); int ret = 0; server.bs = 0; + server.set_mode_cursor = strdup("cell"); + server.message_config.enabled = true; char *config_path = NULL; if(!parse_args(&server, argc, argv, &config_path)) { @@ -369,8 +379,8 @@ main(int argc, char *argv[]) { wl_event_loop_add_signal(event_loop, SIGPIPE, handle_signal, &server); server.event_loop = event_loop; - backend = wlr_backend_autocreate(server.wl_display, &server.session); - server.headless_backend = wlr_headless_backend_create(server.wl_display); + backend = wlr_backend_autocreate(event_loop, &server.session); + server.headless_backend = wlr_headless_backend_create(event_loop); if(!backend) { wlr_log(WLR_ERROR, "Unable to create the wlroots backend"); ret = 1; @@ -411,7 +421,7 @@ main(int argc, char *argv[]) { wl_list_init(&server.outputs); wl_list_init(&server.disabled_outputs); - server.output_layout = wlr_output_layout_create(); + server.output_layout = wlr_output_layout_create(server.wl_display); if(!server.output_layout) { wlr_log(WLR_ERROR, "Unable to create output layout"); ret = 1; @@ -470,7 +480,7 @@ main(int argc, char *argv[]) { server.new_output.notify = handle_new_output; wl_signal_add(&backend->events.new_output, &server.new_output); - server.seat = seat_create(&server, backend); + server.seat = seat_create(&server); if(!server.seat) { wlr_log(WLR_ERROR, "Unable to create the seat"); ret = 1; @@ -489,15 +499,15 @@ main(int argc, char *argv[]) { &server.new_idle_inhibitor_v1); wl_list_init(&server.inhibitors); - xdg_shell = wlr_xdg_shell_create(server.wl_display, 3); + xdg_shell = wlr_xdg_shell_create(server.wl_display, 5); if(!xdg_shell) { wlr_log(WLR_ERROR, "Unable to create the XDG shell interface"); ret = 1; goto end; } - server.new_xdg_shell_surface.notify = handle_xdg_shell_surface_new; - wl_signal_add(&xdg_shell->events.new_surface, - &server.new_xdg_shell_surface); + server.new_xdg_shell_toplevel.notify = handle_xdg_shell_toplevel_new; + wl_signal_add(&xdg_shell->events.new_toplevel, + &server.new_xdg_shell_toplevel); xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(server.wl_display); @@ -527,14 +537,6 @@ main(int argc, char *argv[]) { goto end; } - presentation = wlr_presentation_create(server.wl_display, server.backend); - if(!presentation) { - wlr_log(WLR_ERROR, "Unable to create the presentation interface"); - ret = 1; - goto end; - } - wlr_scene_set_presentation(server.scene, presentation); - export_dmabuf_manager = wlr_export_dmabuf_manager_v1_create(server.wl_display); if(!export_dmabuf_manager) { @@ -589,8 +591,8 @@ main(int argc, char *argv[]) { &server.new_xwayland_surface); if(setenv("DISPLAY", server.xwayland->display_name, true) < 0) { - wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland.", - "Clients may not be able to connect"); + wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland. Clients " + "may not be able to connect"); } else { wlr_log(WLR_DEBUG, "XWayland is running on display %s", server.xwayland->display_name); @@ -621,8 +623,8 @@ main(int argc, char *argv[]) { } if(setenv("WAYLAND_DISPLAY", socket, true) < 0) { - wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.", - "Clients may not be able to connect"); + wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY. Clients may " + "not be able to connect"); } else { fprintf(stdout, "Cagebreak " CG_VERSION " is running on Wayland display %s\n", @@ -705,6 +707,10 @@ main(int argc, char *argv[]) { } free(server.modes); } + if(server.set_mode_cursor != NULL) { + free(server.set_mode_cursor); + server.set_mode_cursor = NULL; + } if(config_path != NULL) { free(config_path); @@ -752,8 +758,15 @@ main(int argc, char *argv[]) { if(server.wl_display != NULL) { wl_display_destroy(server.wl_display); } - if(server.output_layout != NULL) { - wlr_output_layout_destroy(server.output_layout); + + if(server.allocator != NULL) { + wlr_allocator_destroy(server.allocator); + } + if(server.renderer != NULL) { + wlr_renderer_destroy(server.renderer); + } + if(server.scene != NULL) { + wlr_scene_node_destroy(&server.scene->tree.node); } if(server.input != NULL) { diff --git a/fuzz/execl_override.c b/fuzz/execl_override.c index 0f9a19f..0369f34 100644 --- a/fuzz/execl_override.c +++ b/fuzz/execl_override.c @@ -3,11 +3,9 @@ // This file is used by the fuzzer in order to prevent executing shell commands. #define _GNU_SOURCE -#include "../output.h" #include #include #include -#include int fork(void) { diff --git a/fuzz/fuzz-lib.c b/fuzz/fuzz-lib.c index 2d46e50..59a6edb 100644 --- a/fuzz/fuzz-lib.c +++ b/fuzz/fuzz-lib.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -123,7 +122,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; struct wlr_data_control_manager_v1 *data_control_manager = NULL; struct wlr_viewporter *viewporter = NULL; - struct wlr_presentation *presentation = NULL; struct wlr_xdg_output_manager_v1 *output_manager = NULL; struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; struct wlr_xdg_shell *xdg_shell = NULL; @@ -202,7 +200,8 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { server.message_config.display_time = 2; server.message_config.font = strdup("pango:Monospace 10"); - backend = wlr_multi_backend_create(server.wl_display); + server.event_loop = wl_display_get_event_loop(server.wl_display); + backend = wlr_multi_backend_create(server.event_loop); if(!backend) { wlr_log(WLR_ERROR, "Unable to create the wlroots multi backend"); ret = 1; @@ -211,7 +210,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { server.backend = backend; struct wlr_backend *headless_backend = - wlr_headless_backend_create(server.wl_display); + wlr_headless_backend_create(server.event_loop); if(!headless_backend) { wlr_log(WLR_ERROR, "Unable to create the wlroots headless backend"); ret = 1; @@ -251,7 +250,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { wlr_renderer_init_wl_display(server.renderer, server.wl_display); server.bg_color = calloc(4, sizeof(float *)); - server.output_layout = wlr_output_layout_create(); + server.output_layout = wlr_output_layout_create(server.wl_display); if(!server.output_layout) { wlr_log(WLR_ERROR, "Unable to create output layout"); ret = 1; @@ -303,7 +302,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { server.new_output.notify = handle_new_output; wl_signal_add(&backend->events.new_output, &server.new_output); - server.seat = seat_create(&server, backend); + server.seat = seat_create(&server); if(!server.seat) { wlr_log(WLR_ERROR, "Unable to create the seat"); ret = 1; @@ -334,9 +333,9 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { ret = 1; goto end; } - server.new_xdg_shell_surface.notify = handle_xdg_shell_surface_new; + server.new_xdg_shell_toplevel.notify = handle_xdg_shell_toplevel_new; wl_signal_add(&xdg_shell->events.new_surface, - &server.new_xdg_shell_surface); + &server.new_xdg_shell_toplevel); xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(server.wl_display); @@ -366,14 +365,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; } - presentation = wlr_presentation_create(server.wl_display, server.backend); - if(!presentation) { - wlr_log(WLR_ERROR, "Unable to create the presentation interface"); - ret = 1; - goto end; - } - wlr_scene_set_presentation(server.scene, presentation); - export_dmabuf_manager = wlr_export_dmabuf_manager_v1_create(server.wl_display); if(!export_dmabuf_manager) { diff --git a/idle_inhibit_v1.c b/idle_inhibit_v1.c index bc76ff7..b389ff1 100644 --- a/idle_inhibit_v1.c +++ b/idle_inhibit_v1.c @@ -24,7 +24,8 @@ idle_inhibit_v1_check_active(struct cg_server *server) { } static void -handle_destroy(struct wl_listener *listener, void *data) { +handle_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_idle_inhibitor_v1 *inhibitor = wl_container_of(listener, inhibitor, destroy); struct cg_server *server = inhibitor->server; diff --git a/input_manager.c b/input_manager.c index 47ce206..b0bf57b 100644 --- a/input_manager.c +++ b/input_manager.c @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -42,8 +42,16 @@ strip_whitespace(char *str) { char * input_device_get_identifier(struct wlr_input_device *device) { - int vendor = device->vendor; - int product = device->product; + int vendor = 0; + int product = 0; +#if WLR_HAS_LIBINPUT_BACKEND + if(wlr_input_device_is_libinput(device)) { + struct libinput_device *libinput_dev = + wlr_libinput_get_device_handle(device); + vendor = libinput_device_get_id_vendor(libinput_dev); + product = libinput_device_get_id_product(libinput_dev); + } +#endif char *name = strdup(device->name ? device->name : ""); strip_whitespace(name); @@ -71,7 +79,8 @@ input_device_get_identifier(struct wlr_input_device *device) { } void -input_manager_handle_device_destroy(struct wl_listener *listener, void *data) { +input_manager_handle_device_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_input_device *input_device = wl_container_of(listener, input_device, device_destroy); diff --git a/ipc_server.c b/ipc_server.c index 37e59ad..22d8676 100644 --- a/ipc_server.c +++ b/ipc_server.c @@ -23,7 +23,8 @@ static const char ipc_magic[] = {'c', 'g', '-', 'i', 'p', 'c'}; #define IPC_HEADER_SIZE sizeof(ipc_magic) static void -handle_display_destroy(struct wl_listener *listener, void *data) { +handle_display_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_ipc_handle *ipc = wl_container_of(listener, ipc, display_destroy); if(ipc->event_source != NULL) { wl_event_source_remove(ipc->event_source); @@ -114,7 +115,8 @@ ipc_init(struct cg_server *server) { } int -ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { +ipc_client_handle_writable(__attribute__((unused)) int client_fd, uint32_t mask, + void *data) { struct cg_ipc_client *client = data; if(mask & WL_EVENT_ERROR) { diff --git a/keybinding.c b/keybinding.c index 9878a58..80bb1e3 100644 --- a/keybinding.c +++ b/keybinding.c @@ -103,6 +103,10 @@ keybinding_free(struct keybinding *keybinding, bool recursive) { free(keybinding->data.c); } break; + case KEYBINDING_SETMODECURSOR: + if(keybinding->data.c != NULL) { + free(keybinding->data.c); + } default: break; } @@ -840,7 +844,7 @@ print_message_conf(struct cg_message_config *config) { struct dyn_str outp_str; outp_str.len = 0; outp_str.cur_pos = 0; - uint32_t nmemb = 7; + uint32_t nmemb = 8; outp_str.str_arr = calloc(nmemb, sizeof(char *)); print_str(&outp_str, "\"message_config\": {"); print_str(&outp_str, "\"font\": \"%s\",\n", config->font); @@ -849,6 +853,7 @@ print_message_conf(struct cg_message_config *config) { config->bg_color[1], config->bg_color[2], config->bg_color[3]); print_str(&outp_str, "\"fg_color\": [%f,%f,%f,%f],\n", config->fg_color[0], config->fg_color[1], config->fg_color[2], config->fg_color[3]); + print_str(&outp_str, "\"enabled\": %d,\n", config->enabled == 1); switch(config->anchor) { case CG_MESSAGE_TOP_LEFT: print_str(&outp_str, "\"anchor\": \"top_left\"\n", config->font); @@ -1172,15 +1177,15 @@ print_input_device(struct cg_input_device *dev) { print_str(&outp_str, "\"NULL\": {\n"); } print_str(&outp_str, "\"is_virtual\": %d,\n", dev->is_virtual); - print_str( - &outp_str, "\"type\": \"%s\"\n", - dev->wlr_device->type == WLR_INPUT_DEVICE_POINTER ? "pointer" - : dev->wlr_device->type == WLR_INPUT_DEVICE_SWITCH ? "switch" - : dev->wlr_device->type == WLR_INPUT_DEVICE_TABLET_PAD ? "tablet pad" - : dev->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL ? "tablet tool" - : dev->wlr_device->type == WLR_INPUT_DEVICE_TOUCH ? "touch" - : dev->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD ? "keyboard" - : "unknown"); + print_str(&outp_str, "\"type\": \"%s\"\n", + dev->wlr_device->type == WLR_INPUT_DEVICE_POINTER ? "pointer" + : dev->wlr_device->type == WLR_INPUT_DEVICE_SWITCH ? "switch" + : dev->wlr_device->type == WLR_INPUT_DEVICE_TABLET_PAD + ? "tablet pad" + : dev->wlr_device->type == WLR_INPUT_DEVICE_TABLET ? "tablet" + : dev->wlr_device->type == WLR_INPUT_DEVICE_TOUCH ? "touch" + : dev->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD ? "keyboard" + : "unknown"); print_str(&outp_str, "}"); return dyn_str_to_str(&outp_str); } @@ -1669,6 +1674,9 @@ keybinding_configure_message(struct cg_server *server, if(config->anchor != CG_MESSAGE_NOPT) { server->message_config.anchor = config->anchor; } + if(config->enabled != -1) { + server->message_config.enabled = config->enabled; + } ipc_send_event(server, "{\"event_name\":\"configure_message\"}"); } @@ -1740,10 +1748,11 @@ run_action(enum keybinding_action action, struct cg_server *server, case KEYBINDING_SWITCH_MODE: if(data.u != server->seat->default_mode) { wlr_seat_pointer_notify_clear_focus(server->seat->seat); - if(server->seat->enable_cursor == true) { + if(server->seat->enable_cursor == true && + server->set_mode_cursor != NULL) { wlr_cursor_set_xcursor(server->seat->cursor, server->seat->xcursor_manager, - "dot_box_mask"); + server->set_mode_cursor); } } server->seat->mode = data.u; @@ -1866,6 +1875,14 @@ run_action(enum keybinding_action action, struct cg_server *server, server->curr_output->workspaces[server->curr_output->curr_workspace] ->focused_tile->view); break; + case KEYBINDING_SETMODECURSOR: + if(data.c != NULL) { + if(server->set_mode_cursor != NULL) { + free(server->set_mode_cursor); + } + server->set_mode_cursor = strdup(data.c); + } + break; default: { wlr_log(WLR_ERROR, "run_action was called with a value not present in \"enum " diff --git a/keybinding.h b/keybinding.h index fca1271..db9a6f3 100644 --- a/keybinding.h +++ b/keybinding.h @@ -78,6 +78,8 @@ struct cg_server; \ KEYBINDING(KEYBINDING_DEFINEKEY, \ definekey) /* data.kb is the keybinding definition */ \ + KEYBINDING(KEYBINDING_SETMODECURSOR, \ + setmodecursor) /* data.c is the name of ther cursor */ \ KEYBINDING(KEYBINDING_BACKGROUND, \ background) /* data.color is the background color */ \ KEYBINDING(KEYBINDING_DEFINEMODE, \ diff --git a/libinput.c b/libinput.c index b6244aa..a8778da 100644 --- a/libinput.c +++ b/libinput.c @@ -252,7 +252,7 @@ input_device_get_type(struct cg_input_device *device) { return "keyboard"; case WLR_INPUT_DEVICE_TOUCH: return "touch"; - case WLR_INPUT_DEVICE_TABLET_TOOL: + case WLR_INPUT_DEVICE_TABLET: return "tablet_tool"; case WLR_INPUT_DEVICE_TABLET_PAD: return "tablet_pad"; diff --git a/man/cagebreak-config.5.md b/man/cagebreak-config.5.md index 7c18c9a..029f4a3 100644 --- a/man/cagebreak-config.5.md +++ b/man/cagebreak-config.5.md @@ -1,4 +1,4 @@ -cagebreak-config(5) "Version 2.3.1" "Cagebreak Manual" +cagebreak-config(5) "Version 2.4.0" "Cagebreak Manual" # NAME diff --git a/man/cagebreak-socket.7.md b/man/cagebreak-socket.7.md index a5f3d8a..eeff810 100644 --- a/man/cagebreak-socket.7.md +++ b/man/cagebreak-socket.7.md @@ -1,4 +1,4 @@ -cagebreak-socket(7) "Version 2.3.1" "Cagebreak Manual" +cagebreak-socket(7) "Version 2.4.0" "Cagebreak Manual" # NAME diff --git a/man/cagebreak.1.md b/man/cagebreak.1.md index d91c589..ca3c443 100644 --- a/man/cagebreak.1.md +++ b/man/cagebreak.1.md @@ -1,4 +1,4 @@ -cagebreak(1) "Version 2.3.1" "Cagebreak Manual" +cagebreak(1) "Version 2.4.0" "Cagebreak Manual" # NAME diff --git a/meson.build b/meson.build index 6b57a32..407b8a3 100644 --- a/meson.build +++ b/meson.build @@ -3,9 +3,9 @@ project( 'cagebreak', 'c', -version : '2.3.1', +version : '2.4.0', license : 'MIT', -default_options : ['c_std=c11', 'warning_level=3'] +default_options : ['c_std=c23', 'warning_level=3'] ) add_project_arguments( @@ -13,7 +13,6 @@ add_project_arguments( '-DWLR_USE_UNSTABLE', '-Werror=implicit-function-declaration', '-Wundef', - '-Wno-unused-parameter', ], language: 'c', ) @@ -55,7 +54,7 @@ if is_freebsd ) endif -wlroots = dependency('wlroots', version: ['>=0.17.0', '< 0.18.0']) +wlroots = dependency('wlroots-0.18') wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') wayland_cursor = dependency('wayland-cursor') @@ -202,17 +201,17 @@ cagebreak_dependencies_dict = { reproducible_build_versions = { 'server_protos': '-1', 'wayland_server': '1.19.0', - 'wayland_client': '1.22.0', - 'wayland_cursor': '1.22.0', - 'wlroots': '0.17.1', - 'xkbcommon': '1.6.0', + 'wayland_client': '1.23.1', + 'wayland_cursor': '1.23.1', + 'wlroots': '0.18.1', + 'xkbcommon': '1.7.0', 'fontconfig': '2.15.0', - 'libinput': '1.25.0', - 'libevdev': '1.13.1', - 'libudev': '255', - 'pango': '1.51.0', - 'cairo': '1.18.0', - 'pangocairo': '1.51.0', + 'libinput': '1.26.2', + 'libevdev': '1.13.3', + 'libudev': '256', + 'pango': '1.54.0', + 'cairo': '1.18.2', + 'pangocairo': '1.54.0', 'math': '-1' } @@ -238,7 +237,7 @@ foreach name, dep : cagebreak_dependencies_dict endforeach reproducible_build_compiler = 'gcc' -reproducible_build_compiler_version = '13.2.1' +reproducible_build_compiler_version = '14.2.1' if cc.get_id() != reproducible_build_compiler warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in Hashes.md (' + reproducible_build_compiler + ').') @@ -260,7 +259,7 @@ install_data('LICENSE', install_dir : '/usr/share/licenses/' + meson.project_nam if get_option('man-pages') scdoc = find_program('scdoc') - secssinceepoch = 1706350970 + secssinceepoch = 1728318420 shcommand = 'export SOURCE_DATE_EPOCH=' + secssinceepoch.to_string() + ' ; @0@ < @INPUT@'.format(scdoc.path()) sh = find_program('sh') mandir1 = join_paths(get_option('mandir'), 'man1') diff --git a/message.c b/message.c index 4b99aaf..85ae2e6 100644 --- a/message.c +++ b/message.c @@ -37,7 +37,8 @@ msg_buffer_destroy(struct wlr_buffer *wlr_buffer) { } static bool -msg_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags, +msg_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, + __attribute__((unused)) uint32_t flags, void **data, uint32_t *format, size_t *stride) { struct msg_buffer *buffer = wl_container_of(wlr_buffer, buffer, base); @@ -54,7 +55,8 @@ msg_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags, } static void -msg_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) { +msg_buffer_end_data_ptr_access( + __attribute__((unused)) struct wlr_buffer *wlr_buffer) { // This space is intentionally left blank } @@ -238,6 +240,7 @@ message_set_output(struct cg_output *output, const char *string, } message->message = wlr_scene_buffer_create(&scene_output->scene->tree, &buf->base); + message->buf = buf; wlr_scene_node_raise_to_top(&message->message->node); wlr_scene_node_set_enabled(&message->message->node, true); wlr_scene_buffer_set_dest_size(message->message, width, height); @@ -249,7 +252,7 @@ message_set_output(struct cg_output *output, const char *string, void message_printf(struct cg_output *output, const char *fmt, ...) { - if(output->destroyed) { + if(output->destroyed || output->server->message_config.enabled == 0) { return; } va_list ap; @@ -312,7 +315,7 @@ message_printf(struct cg_output *output, const char *fmt, ...) { void message_printf_pos(struct cg_output *output, struct wlr_box *position, const enum cg_message_anchor anchor, const char *fmt, ...) { - if(output->destroyed) { + if(output->destroyed || output->server->message_config.enabled == 0) { free(position); return; } @@ -334,10 +337,11 @@ message_clear(struct cg_output *output) { struct cg_message *message, *tmp; wl_list_for_each_safe(message, tmp, &output->messages, link) { wl_list_remove(&message->link); - struct wlr_buffer *buf = message->message->buffer; wlr_scene_node_destroy(&message->message->node); free(message->position); - buf->impl->destroy(buf); + if(message->buf != NULL) { + msg_buffer_destroy(&message->buf->base); + } free(message); } } diff --git a/message.h b/message.h index a1b8f13..98a9fe4 100644 --- a/message.h +++ b/message.h @@ -27,6 +27,7 @@ struct cg_message_config { int display_time; float bg_color[4]; float fg_color[4]; + int enabled; enum cg_message_anchor anchor; }; @@ -34,6 +35,7 @@ struct cg_message { struct wlr_box *position; struct wlr_scene_buffer *message; struct wl_surface *surface; + struct msg_buffer *buf; struct wl_list link; }; diff --git a/output.c b/output.c index c048b9b..d892f15 100644 --- a/output.c +++ b/output.c @@ -143,7 +143,7 @@ output_destroy(struct cg_output *output) { } output->destroyed = true; enum output_role role = output->role; - if(role == OUTPUT_ROLE_PERMANENT) { + if(role == OUTPUT_ROLE_PERMANENT && server->running) { output->wlr_output = wlr_headless_add_output(server->headless_backend, output->layout_box.width, output->layout_box.height); @@ -159,6 +159,8 @@ output_destroy(struct cg_output *output) { output_clear(output); + wlr_scene_node_destroy(&output->bg->node); + for(unsigned int i = 0; i < server->nws; ++i) { workspace_free(output->workspaces[i]); } @@ -177,13 +179,14 @@ output_destroy(struct cg_output *output) { wlr_log(WLR_ERROR, "Failed to allocate memory for output name in output_destroy"); } - if(wl_list_empty(&server->outputs)) { + if(wl_list_empty(&server->outputs) && server->running) { wl_display_terminate(server->wl_display); } } static void -handle_output_destroy(struct wl_listener *listener, void *data) { +handle_output_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_output *output = wl_container_of(listener, output, destroy); output_destroy(output); } @@ -210,7 +213,8 @@ handle_output_gamma_control_set_gamma(struct wl_listener *listener, } static void -handle_output_frame(struct wl_listener *listener, void *data) { +handle_output_frame(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_output *output = wl_container_of(listener, output, frame); if(!output->wlr_output->enabled) { return; @@ -228,14 +232,14 @@ handle_output_frame(struct wl_listener *listener, void *data) { } static int -output_set_mode(struct wlr_output *output, int width, int height, - float refresh_rate) { +output_set_mode(struct wlr_output *output, struct wlr_output_state *state, + int width, int height, float refresh_rate) { int mhz = (int)(refresh_rate * 1000); if(wl_list_empty(&output->modes)) { wlr_log(WLR_DEBUG, "Assigning custom mode to %s", output->name); - wlr_output_set_custom_mode(output, width, height, - refresh_rate > 0 ? mhz : 0); + wlr_output_state_set_custom_mode(state, width, height, + refresh_rate > 0 ? mhz : 0); return 0; } @@ -259,9 +263,9 @@ output_set_mode(struct wlr_output *output, int width, int height, } else { wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name); } - wlr_output_set_mode(output, best); - wlr_output_commit(output); - if(!wlr_output_test(output)) { + wlr_output_state_set_mode(state, best); + wlr_output_commit_state(output, state); + if(!wlr_output_test_state(output, state)) { wlr_log(WLR_ERROR, "Unable to assign configured mode to %s, picking arbitrary " "available mode", @@ -271,13 +275,13 @@ output_set_mode(struct wlr_output *output, int width, int height, if(mode == best) { continue; } - wlr_output_set_mode(output, mode); - wlr_output_commit(output); - if(wlr_output_test(output)) { + wlr_output_state_set_mode(state, mode); + wlr_output_commit_state(output, state); + if(wlr_output_test_state(output, state)) { break; } } - if(!wlr_output_test(output)) { + if(!wlr_output_test_state(output, state)) { return 1; } } @@ -312,6 +316,13 @@ output_apply_config(struct cg_server *server, struct cg_output *output, struct cg_output_config *config) { struct wlr_output *wlr_output = output->wlr_output; + struct wlr_output_state *state = calloc(1, sizeof(*state)); + if(!state) { + wlr_log(WLR_ERROR, "Could not allocate memory for output state, " + "skipping output configuration."); + return; + } + wlr_output_state_init(state); struct wlr_box prev_box; prev_box.x = output->layout_box.x; prev_box.y = output->layout_box.y; @@ -324,6 +335,7 @@ output_apply_config(struct cg_server *server, struct cg_output *output, (output->destroyed == true)) { output_destroy(output); wlr_output_destroy(wlr_output); + free(state); return; } } @@ -334,20 +346,21 @@ output_apply_config(struct cg_server *server, struct cg_output *output, } if(config->angle != -1) { - wlr_output_set_transform(wlr_output, config->angle); + wlr_output_state_set_transform(state, config->angle); } if(config->scale != -1) { wlr_log(WLR_INFO, "Setting output scale to %f", config->scale); - wlr_output_set_scale(wlr_output, config->scale); + wlr_output_state_set_scale(state, config->scale); } if(config->pos.x != -1) { - if(output_set_mode(wlr_output, config->pos.width, config->pos.height, - config->refresh_rate) != 0) { + if(output_set_mode(wlr_output, state, config->pos.width, + config->pos.height, config->refresh_rate) != 0) { wlr_log(WLR_ERROR, "Setting output mode failed, disabling output."); output_clear(output); wl_list_insert(&server->disabled_outputs, &output->link); - wlr_output_enable(wlr_output, false); - wlr_output_commit(wlr_output); + wlr_output_state_set_enabled(state, false); + wlr_output_commit_state(wlr_output, state); + free(state); return; } if(wlr_box_empty(&output->layout_box)) { @@ -407,7 +420,7 @@ output_apply_config(struct cg_server *server, struct cg_output *output, struct wlr_output_mode *preferred_mode = wlr_output_preferred_mode(wlr_output); if(preferred_mode) { - wlr_output_set_mode(wlr_output, preferred_mode); + wlr_output_state_set_mode(state, preferred_mode); } } /* Refuse to disable the only output */ @@ -415,15 +428,15 @@ output_apply_config(struct cg_server *server, struct cg_output *output, wl_list_length(&server->outputs) > 1) { output_clear(output); wl_list_insert(&server->disabled_outputs, &output->link); - wlr_output_enable(wlr_output, false); - wlr_output_commit(wlr_output); + wlr_output_state_set_enabled(state, false); + wlr_output_commit_state(wlr_output, state); } else { if(prio_changed) { wl_list_remove(&output->link); output_insert(server, output); } - wlr_output_enable(wlr_output, true); - wlr_output_commit(wlr_output); + wlr_output_state_set_enabled(state, true); + wlr_output_commit_state(wlr_output, state); } if(output->bg != NULL) { @@ -433,6 +446,7 @@ output_apply_config(struct cg_server *server, struct cg_output *output, struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(output->server->scene, output->wlr_output); if(scene_output == NULL) { + free(state); return; } output->bg = wlr_scene_rect_create( @@ -441,6 +455,7 @@ output_apply_config(struct cg_server *server, struct cg_output *output, wlr_scene_node_set_position(&output->bg->node, scene_output->x, scene_output->y); wlr_scene_node_lower_to_bottom(&output->bg->node); + free(state); } struct cg_output_config * @@ -586,8 +601,7 @@ output_make_workspace_fullscreen(struct cg_output *output, int ws) { } workspace_free_tiles(output->workspaces[ws]); - if(full_screen_workspace_tiles(server->output_layout, - output->workspaces[ws], + if(full_screen_workspace_tiles(output->workspaces[ws], &server->tiles_curr_id) != 0) { wlr_log(WLR_ERROR, "Failed to allocate space for fullscreen workspace"); return; @@ -609,7 +623,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { struct cg_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; - wlr_output_enable(wlr_output, true); if(!wlr_output_init_render(wlr_output, server->allocator, server->renderer)) { @@ -642,6 +655,13 @@ handle_new_output(struct wl_listener *listener, void *data) { output->destroyed = false; if(!reinit) { + struct wlr_output_state *state = calloc(1, sizeof(*state)); + wlr_output_state_init(state); + wlr_output_state_set_transform(state, WL_OUTPUT_TRANSFORM_NORMAL); + wlr_output_state_set_enabled(state, true); + wlr_output_commit_state(wlr_output, state); + free(state); + output->server = server; output->name = strdup(wlr_output->name); @@ -653,7 +673,6 @@ handle_new_output(struct wl_listener *listener, void *data) { } } output->priority = prio; - wlr_output_set_transform(wlr_output, WL_OUTPUT_TRANSFORM_NORMAL); output->workspaces = NULL; wl_list_init(&output->messages); @@ -701,16 +720,19 @@ handle_new_output(struct wl_listener *listener, void *data) { struct wlr_output_mode *preferred_mode = wlr_output_preferred_mode(wlr_output); + struct wlr_output_state *state = calloc(1, sizeof(*state)); + wlr_output_state_init(state); + wlr_output_state_set_transform(state, WL_OUTPUT_TRANSFORM_NORMAL); if(preferred_mode) { - wlr_output_set_mode(wlr_output, preferred_mode); + wlr_output_state_set_mode(state, preferred_mode); } - wlr_output_set_transform(wlr_output, WL_OUTPUT_TRANSFORM_NORMAL); wlr_scene_output_set_position( output->scene_output, output->layout_box.x, output->layout_box.y); - wlr_output_enable(wlr_output, true); - wlr_output_commit(wlr_output); + wlr_output_state_set_enabled(state, true); + wlr_output_commit_state(wlr_output, state); output_configure(server, output); output_get_layout_box(output); + free(state); } wlr_cursor_set_xcursor(server->seat->cursor, server->seat->xcursor_manager, diff --git a/parse.c b/parse.c index 72d8295..b125cec 100644 --- a/parse.c +++ b/parse.c @@ -430,8 +430,7 @@ parse_definekey(struct cg_server *server, char **saveptr, char **errstr, } int -parse_background(struct cg_server *server, float *color, char **saveptr, - char **errstr) { +parse_background(float *color, char **saveptr, char **errstr) { /* Read rgb numbers */ for(unsigned int i = 0; i < 3; ++i) { char *nstr = strtok_r(NULL, " \n", saveptr); @@ -493,10 +492,10 @@ parse_cursor(char **saveptr, char **errstr) { } else if(strcmp(*saveptr, "disable") == 0) { return 0; } else { - wlr_log(WLR_ERROR, - "Invalid option \"%s\" for \"cursor\". Expected \"enable\" or " - "\"disable\".", - *saveptr); + *errstr = log_error( + "Invalid option \"%s\" for \"cursor\". Expected \"enable\" or " + "\"disable\".", + *saveptr); return -1; } } @@ -721,6 +720,7 @@ parse_message_config(char **saveptr, char **errstr) { cfg->display_time = -1; cfg->font = NULL; cfg->anchor = CG_MESSAGE_NOPT; + cfg->enabled = -1; char *setting = strtok_r(NULL, " ", saveptr); if(setting == NULL) { @@ -780,6 +780,10 @@ parse_message_config(char **saveptr, char **errstr) { "the given anchor value is not a valid option"); goto error; } + } else if(strcmp(setting, "enable") == 0) { + cfg->enabled = 1; + } else if(strcmp(setting, "disable") == 0) { + cfg->enabled = 0; } else { *errstr = log_error("Invalid option to command \"configure_message\""); goto error; @@ -1011,6 +1015,15 @@ parse_command(struct cg_server *server, struct keybinding *keybinding, return -1; } keybinding->data.u = (unsigned int)mode_idx; + } else if(strcmp(action, "setmodecursor") == 0) { + keybinding->action = KEYBINDING_SETMODECURSOR; + char *cursor = strtok_r(NULL, " ", &saveptr); + if(cursor == NULL) { + *errstr = log_error( + "Expected cursor name after \"setmodecursor\". Got nothing."); + return -1; + } + keybinding->data.c = strdup(cursor); } else if(strcmp(action, "bind") == 0) { keybinding->action = KEYBINDING_DEFINEKEY; keybinding->data.kb = @@ -1027,8 +1040,7 @@ parse_command(struct cg_server *server, struct keybinding *keybinding, } } else if(strcmp(action, "background") == 0) { keybinding->action = KEYBINDING_BACKGROUND; - if(parse_background(server, keybinding->data.color, &saveptr, errstr) != - 0) { + if(parse_background(keybinding->data.color, &saveptr, errstr) != 0) { return -1; } } else if(strcmp(action, "escape") == 0) { diff --git a/release-non-auto-checks/Bugs.md b/release-non-auto-checks/Bugs.md index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/Bugs.md +++ b/release-non-auto-checks/Bugs.md @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/FAQ.md b/release-non-auto-checks/FAQ.md index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/FAQ.md +++ b/release-non-auto-checks/FAQ.md @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/SECURITY.md b/release-non-auto-checks/SECURITY.md index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/SECURITY.md +++ b/release-non-auto-checks/SECURITY.md @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/WLR_XDG_VERSION b/release-non-auto-checks/WLR_XDG_VERSION index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/WLR_XDG_VERSION +++ b/release-non-auto-checks/WLR_XDG_VERSION @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/acknowledge-contributors b/release-non-auto-checks/acknowledge-contributors index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/acknowledge-contributors +++ b/release-non-auto-checks/acknowledge-contributors @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/archwiki b/release-non-auto-checks/archwiki index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/archwiki +++ b/release-non-auto-checks/archwiki @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/changelog-major-minor b/release-non-auto-checks/changelog-major-minor index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/changelog-major-minor +++ b/release-non-auto-checks/changelog-major-minor @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/internal-wiki b/release-non-auto-checks/internal-wiki index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/internal-wiki +++ b/release-non-auto-checks/internal-wiki @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/release-note b/release-non-auto-checks/release-note index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/release-note +++ b/release-non-auto-checks/release-note @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/reproducibility-checked b/release-non-auto-checks/reproducibility-checked index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/reproducibility-checked +++ b/release-non-auto-checks/reproducibility-checked @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/security-to-man-page-info-transfer b/release-non-auto-checks/security-to-man-page-info-transfer index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/security-to-man-page-info-transfer +++ b/release-non-auto-checks/security-to-man-page-info-transfer @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/release-non-auto-checks/version-restrictions b/release-non-auto-checks/version-restrictions index 8e6104c..c62aa02 100644 --- a/release-non-auto-checks/version-restrictions +++ b/release-non-auto-checks/version-restrictions @@ -1,2 +1,2 @@ -2.3.1 -2024-01-27 +2.4.0 +2024-10-07 diff --git a/scripts/fuzz b/scripts/fuzz index e90e17a..667e6c9 100755 --- a/scripts/fuzz +++ b/scripts/fuzz @@ -11,7 +11,7 @@ then fi rm -rf fuzzing-directory -CC=clang meson setup fuzzing-directory -Dfuzz=true -Db_sanitize=address,undefined -Db_lundef=false -Db_detect-leaks=0 +CC=clang CCXFLAGS=-std=c11 meson setup fuzzing-directory -Dfuzz=true -Db_sanitize=address,undefined -Db_lundef=false ninja -C fuzzing-directory/ WLR_BACKENDS=headless ./fuzzing-directory/fuzz-parse -jobs=12 -max_len=50000 -close_fd_mask=3 "${fuzzing_corpus}" rm -rf fuzzing-directory diff --git a/seat.c b/seat.c index a011251..11bfa9c 100644 --- a/seat.c +++ b/seat.c @@ -154,7 +154,6 @@ handle_keyboard_repeat(void *data) { wlr_log(WLR_DEBUG, "failed to update key repeat timer"); } } - run_action((*cg_group->repeat_keybinding)->action, cg_group->seat->server, (*cg_group->repeat_keybinding)->data); @@ -321,7 +320,8 @@ handle_keyboard_group_key(struct wl_listener *listener, void *data) { } static void -handle_keyboard_group_modifiers(struct wl_listener *listener, void *_data) { +handle_keyboard_group_modifiers(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_keyboard_group *group = wl_container_of(listener, group, modifiers); handle_modifier_event(&group->wlr_group->keyboard.base, group->seat); @@ -451,7 +451,7 @@ seat_add_device(struct cg_seat *seat, struct cg_input_device *device) { case WLR_INPUT_DEVICE_SWITCH: wlr_log(WLR_DEBUG, "Switch input is not implemented"); return; - case WLR_INPUT_DEVICE_TABLET_TOOL: + case WLR_INPUT_DEVICE_TABLET: case WLR_INPUT_DEVICE_TABLET_PAD: wlr_log(WLR_DEBUG, "Tablet input is not implemented"); return; @@ -488,6 +488,7 @@ remove_keyboard(struct cg_seat *seat, struct cg_input_device *keyboard) { wl_list_remove(&group->link); wl_list_remove(&group->key.link); wl_list_remove(&group->modifiers.link); + wl_event_source_remove(group->key_repeat_timer); if(group->identifier != NULL) { free(group->identifier); } @@ -520,7 +521,7 @@ seat_remove_device(struct cg_seat *seat, struct cg_input_device *device) { case WLR_INPUT_DEVICE_SWITCH: wlr_log(WLR_DEBUG, "Switch input is not implemented"); return; - case WLR_INPUT_DEVICE_TABLET_TOOL: + case WLR_INPUT_DEVICE_TABLET: case WLR_INPUT_DEVICE_TABLET_PAD: wlr_log(WLR_DEBUG, "Tablet input is not implemented"); return; @@ -659,7 +660,8 @@ handle_touch_motion(struct wl_listener *listener, void *data) { } static void -handle_cursor_frame(struct wl_listener *listener, void *_data) { +handle_cursor_frame(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_frame); wlr_seat_pointer_notify_frame(seat->seat); @@ -671,9 +673,9 @@ handle_cursor_axis(struct wl_listener *listener, void *data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_axis); struct wlr_pointer_axis_event *event = data; - wlr_seat_pointer_notify_axis(seat->seat, event->time_msec, - event->orientation, event->delta, - event->delta_discrete, event->source); + wlr_seat_pointer_notify_axis( + seat->seat, event->time_msec, event->orientation, event->delta, + event->delta_discrete, event->source, event->relative_direction); wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } @@ -816,7 +818,8 @@ drag_icon_update_position(struct cg_drag_icon *drag_icon) { } static void -handle_drag_icon_destroy(struct wl_listener *listener, void *_data) { +handle_drag_icon_destroy(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_drag_icon *drag_icon = wl_container_of(listener, drag_icon, destroy); @@ -883,7 +886,8 @@ handle_start_drag(struct wl_listener *listener, void *data) { } static void -handle_destroy(struct wl_listener *listener, void *_data) { +handle_destroy(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_seat *seat = wl_container_of(listener, seat, destroy); wl_list_remove(&seat->destroy.link); @@ -923,7 +927,7 @@ handle_destroy(struct wl_listener *listener, void *_data) { } struct cg_seat * -seat_create(struct cg_server *server, struct wlr_backend *backend) { +seat_create(struct cg_server *server) { struct cg_seat *seat = calloc(1, sizeof(struct cg_seat)); if(!seat) { wlr_log(WLR_ERROR, "Cannot allocate seat"); diff --git a/seat.h b/seat.h index 135c06a..cfa6c92 100644 --- a/seat.h +++ b/seat.h @@ -103,7 +103,7 @@ struct cg_drag_icon { }; struct cg_seat * -seat_create(struct cg_server *server, struct wlr_backend *backend); +seat_create(struct cg_server *server); void seat_destroy(struct cg_seat *seat); struct cg_view * diff --git a/server.h b/server.h index 3224174..9b362f7 100644 --- a/server.h +++ b/server.h @@ -48,7 +48,8 @@ struct cg_server { struct wlr_scene *scene; struct wl_listener xdg_toplevel_decoration; - struct wl_listener new_xdg_shell_surface; + struct wl_listener new_xdg_shell_toplevel; + struct wl_list xdg_decorations; #if CG_HAS_XWAYLAND struct wl_listener new_xwayland_surface; struct wlr_xwayland *xwayland; @@ -65,6 +66,7 @@ struct cg_server { bool bs; bool running; char **modes; + char *set_mode_cursor; uint16_t nws; float *bg_color; uint32_t views_curr_id; diff --git a/signatures/2.3.1-cagebreak-config.5.sig b/signatures/2.3.1-cagebreak-config.5.sig new file mode 100644 index 0000000000000000000000000000000000000000..62cebfaba585b711bc49dc7839295f7ffd85c68c GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j*fj3?c-(R61$^wxVt5(TqTjC^AS0%f$@sQ?NI5JeIN zvr>$FW8Cl$|45rH8WFc5lrS%z74%wY9GI|z!VFw8XeZdd`n!c2nU}Rv^&>GFvX#rX zfjvv$5L-XAnuQM*Qfsy^H+D$6QzdMlcU$C^^sE$MenxkbL|=Gf2Qw}IAqpTIxtRAW__o_5JKakaHLmKhqSRn$L=&G;($n^zPb zvyvYkF*^O!Ah@Gx7;UBdl}|Dq?IT9qqdECXqn7qafV)NZv!XCQAL2+c|4_}z5L#GY zRISsGOye!5tSX(ag0b7+9a*wBVP662*U=62n=||R>z9s*iIvL&S#>Ot|1@!jS_bOe zO4S63u=!WXf5Vg)vzd$@*fzAsHE4a@kZts-cK2Z|z_UL(9}Z}bp)F&^3eN(Nd1kXG zm{Ca1V@$8$yRu%ygFR_du;TO?HOL%>)iBgn`Uj+UrGC{V>oS0=_oj{7J(bi1+ZL41 E8&L=kV*mgE literal 0 HcmV?d00001 diff --git a/signatures/2.3.1-cagebreak-socket.7.sig b/signatures/2.3.1-cagebreak-socket.7.sig new file mode 100644 index 0000000000000000000000000000000000000000..aef73c01926681303c84a6e4ec26f7a8fdbae5cf GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j*fj3?c-(R61$^wxVt5(TqTjC^AS0%f$@sQ?NI5JeIN zvr>$FV_&Ne|8g17?vtmp>3vx=zNZM!kMq2S^V-sec=@NKc*~G3Vtq>kgBHDzsT0d2 zrV5#w{0NKQScyx+3Fk|R-4%1s=4xoGnulP2*dWAZHo?c8&?1q74CC{r!2f>8i)jz`?VG^>e2KiKU zvItc1lAl*}l{&k)D&y}u(`cSXu3^Dk)jpr^y?yslGho~_VjtJ>s;M7Zov@u9tgU8{ zl!uBrQI*HviAIMD_a1x);I9M0CrYxtK23zh6?A`44_<^WCCXxf4hxg;Zl|lG-c}F0 zz@}*%2U^XkC3-Gyby2No7V`Vn$>$%>q?*w_wnT?AHl|8#I_c85v!H9Xrwiz~$FV{T{<|6Ks-TbRaT8rP-<=GyDZMhh(G0u$8VZ(2k36vHjKq- z;c1H_3tOsROcZpS4xZE;RCJ@XV_o6t{ybUV_w&%DCQdwDB1yaQ9H56g984G_Vg-ik zjTl#*JO!c?;n$|}WU>C&7TY`vp6}+n78`YgW>iCq0n%iQ)~aw2Jw7*=OL|=vpodM`7YRO5B5-=OE}~TRi*5U zD9KT+WoPG9#(Vgme4onI@zD@8G*v?DV~!%n(JTZ zvI|2sc?VT{SJ;bq#L|8>XyhkFSy<~Ypz)*-ouu}CVafeIY&c-Ap`?SfIdhjz5@$ltn}6z((Hj4SY0{bbu= zBD~n|;c`QuR`B3D&ywXzP=Tne1A&K(9vqR;nHb-IcK1Ve5Z*h;>J?=i(nf3_wuD0$ zw+|rpBd1^a%m>3cthyi4h-BM8p2v&tB}`hWoRKRltxI<)9+k!0ienyjeVzIPt38lP Esj9RbYybcN literal 0 HcmV?d00001 diff --git a/signatures/2.3.1-cagebreak.sig b/signatures/2.3.1-cagebreak.sig new file mode 100644 index 0000000000000000000000000000000000000000..a6fd9ddb4fbc1cb45eab137fc1c3ca0cdbf8be3b GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j*fj3?c-(R61$^wxVt5(TqTjC^AS0%f$@sQ?NI5JeIN zvr>$FV{;4-|5@q1Qne+3wGrkR`oF!b&U&^;#9`%VL(gM&4CJh~yB9gudHiY%GB+n?U%g0kT zt)MjeG-91;E>3l;kHGc5Vl{T^;!|uK@3xv$-=^L^LO8}TNV3L(so>O>em&Y!Tf&;4 zgIFGgS4D|5;Pw@6pa6f?nd0?FfNUU3wcN+&_U;W9oSCY!>y(3~yxX1~xQ9Dp=Po$# z_4GvjTo8GIXY66?#&B6ky?0-AF+y;`*-XkW;poGTz+7W!gSBU&uV%7l1#gn{cKQR-N9$nrIq(#o z=jC>B8g>U84If2}=&h>>Ny|?C3}a-;murMiX%a`&43G>p*5D+o2n$d_UFi^{A)gEf zRXWLdTwz0;DfQkMGluAAb0(7(CGIypVwmb0eBT*S@JiWDPYPzu#p3vK` zmg(n5Cr5}{yCL+U)&Kwi literal 0 HcmV?d00001 diff --git a/signatures/cagebreak-config.5.sig b/signatures/cagebreak-config.5.sig index 62cebfaba585b711bc49dc7839295f7ffd85c68c..d12c71f921b7f0d440ab16aa7fd63f0cd08c0c54 100644 GIT binary patch delta 543 zcmV+)0^t3&1hxc_B7bKD5QP8=2@pjR1+!9&d}HMO5CDQy>@a1oZ_0C9tIy-yixQUv z%3{G{R*US(p*mhS)F7Z2fAfGX_sImq1Ou|N-liAeypPROh^ASF!?cg2s3%$2AGhOd zncOQhSc?0>%8z+`&80=ku05>zZ@ z>C`a_eRlD;2adOVhQAB_nNEyvt2%#R!i5EHVg{NtZcVNx-_n|6nG3a~ugvCi+1Nbs z*~Lp{kEUWw-C2Vz2_}*sW5x*^$H*!o*!V{SbkDZ8oFU-pu3A79P^GZr(foCPyGJYmCyP?*G zlG&$010;y)N078mXSVNmP!Xfj=YuR&3?c3QnRk3fn-i4e&#w`RsVk|}dX#A$O;>~# ze}U?C_lM9i7;ZFzg&S|cGRv6{jnQ5Len%)?=F@|1VSlD2No>54xwfasu1z!K&^rz+ zZ$Ymu%$&NhoLlPWA2d4)34q8=jJ#pRBAeIPfzaxURGn)e9JSB$q@)V!GlcPW1zA0i zCl?^XoZqqluj7XB+hkDn&mMDdoqt=El?ukM&d*t}X4U0!ii$bN7v}xn^;e$gUu(g- hewN_mfEa%k64?8hciyF9m~YVpf(0%_(XXedDBaPl3?Tpj delta 543 zcmV+)0^t3&1hxc_B7bGH+o=Ew2@pjR1+!9&d}G}35C2G;EgBKGB9t&Mo)z?3XdIZZ zg2D`3GH55*zWTd`8=052QuQM-8nTtkw}CxN;1F9sw3>wv7E)`rFE@5bx>F@=pLbj2 zmh`L?lXjZKlot|QfckmQ8n{OhdTE*nxtQ!3O$GPUhG%>6Dt`io)m2~v_xvL4+86WT zLSXH$MoJ-+;ojyDD@Lgx9wUAgRJ}keUSB8SlkT^H0mXMp!e}T#1g+%Pb&(B5gDoU) z!d~0W`Ga}92>q5M*8-I&u_7Px{x7lqKW7~RSy9@GEwC0cpg6WK9wcW# zd07!9sbIR+0)NKf6iA{fofeFuhcltY=}AHV@Iedvs=*$)MZW3g*w5d$f!2ASz(4F% zV^x=)cF8qywY4~w85*Zm)IW>O_$v9ER}>zzk{=#1I{nljxT9$pZKeB_Pcj|tBSze# zIr&PXmi9=1yG8c1qA)%m;z%+7P|e8@T3BCHt<#T8<9{uutSX(ag0b7+9a*wBVP662 z*U=62n=||R>z9s*iIvL&S#>Ot|1@!jS_bOeO4S63u=!WXf5Vg)vzd$@*fzAsHE4a@ zkZts-cK2Z|z_UL(9}Z}bp)F&^3eN(Nd1kXGm{Ca1V@$8$yRu%ygFR_du;TO?HOL%> h)iBgn`WOeKccp&SCF?SPtM{gj+C7!j1ltyr&l?yW2=M>_ diff --git a/signatures/cagebreak-socket.7.sig b/signatures/cagebreak-socket.7.sig index aef73c01926681303c84a6e4ec26f7a8fdbae5cf..0166ae6c9be6e11742cc654dce0d7e164d06a960 100644 GIT binary patch delta 543 zcmV+)0^t3&1hxc_B7bKD5QP8=2@pjR1+!9&d}G#k5B?=8y%@5{Bv)a@5*Ydq(*9Bi z`FV_?;pK%@7$a+?mRW3f*YXan*xdYSZVC;e$?H3Vy%8hBd8}odTqnB~hC!n4ff?DK zq(>F(wo|mD5mr&K$b6(V3u9uu0kBz=ju93CLUyHD^T1~&d4H5T!lS}_=LHhE=*C>? zvYzv}PwBimv=>MD%pSO4g>U+^Vho_sY9vxfK{XJ38i|?homYztvL=&oe~7#Gst_(Z zGH$N!)a!yN)%P2!toCiyv)ApZV-EaIqY8oGRC@SPqN06G#WQhRCB?I(G%vdhM2iZM zf3$;ciTJoHet$Rf62s`sKb#>UC%1(WIsY%uTlZKyL2ems#0ln$;$Ln~z`EavQup!A zp9(iB@Fq_>QR8xJ}|HAMjaX z7Ov7fu3^hp^k=}V!DoGEPFU}kz1n-H_HCl_(vWK+NqqlgkwjN_rnV1sW&E>;r2(T`qt`)<7J*+ zOit{Efn+7mt4IgIgx=LZ!yaK0vaAOARCKZkRPmCZS9Fy+ySOUj?>f_Ho<^==!Ccio zpYOeW_fa!o+*Ot!9vvhl)8-mB-(SMu!Xc9()JjuLHp+O0vB^ zO@zf2bbn9}UW6_s%3^^I3zP6}r>mphRu8+trfC}oTFt2?dM<8tQLShe^841w=O53c zn$bSCM29jqrb=x(>C(8fpli0L3+TAxgkY*^*W#bC?0;3t=BfWEJd6}WEbx)rJEyK+ zrPv%2FN)6c1#la;Wb$Dw4A6P~=yWmWbFU|()J~;{I*EZ&w|(7sT^eH2#vHSQOxuyj zRFb2vC)j-?@nji4^2m%#l?-M`R{;bgu7Z$KMgSObzIILBaoU-ffwi|~Ul|594Q@U2tzQ)40*uD50mKlFue zF}I8=TPT`1J?Qhmjp#nLW1GG*2c>1ZWT`S}!57~xvY5~%Pw_1vASZAbE;IP9v|5AD zzB&Qh-j9MjAb-5XI%=$;RL|-QF0xXy6x z98H%C%SGa81hGAZ63T@fwjuaADvE~g9%hj&Yb6GsUc;i7a6R3RW|jG$n+SW8L9+L= zk~Jk2WWS~|@U4>4IAzVEiABVQUTl8zbvt|2=#`O;yMJt`{wlEy%zNYH5#%+p|Fyub zB#)a<2uW>H0X+S5GVL3D>hDlbeiuUpD$qb`VpWjqyag=soX5e6Ub|}`F7{pr40zch zQy?4`)BlAoF~`HIj}^e5zFCrL=MH2tKy^|ahn}WtElRC=HST`h0|(S%z$j}!t;FPo hNF7q}Ru~NECYrYAo@yQ#t?N!f#3|$u*uMRDYF+4^34j0q delta 543 zcmV+)0^t3&1hxc_B7bGH+o=Ew2@pjR1+!9&d}D5C5C2^N>0InU*W-2hbFMyX)t!S; zChg01v31)Ga0~0;D$dc|#axp`;Bdm-@PhcCz;x{>>T==euryuRk*W(u)so~uZBN~b(4{6$JX|74yYd{MhdUfh7$jl^hU$$NSDicsq7&iQrt)O5{?``UJPV%h=DQXf zf^Pwm@Wpl;f%~>cuQQ*$=Mi#GO5&=14fnUc+PRXoO{_vYg&%|A_64EPaGq0Z|Ih~U ze0%31t&_7o1b@rtE-x3qv(|2UUAl*o%0?(tb5)~Ypz)*-ouu}CVafeIY& zc-Ap`?SfIdhjz5@$ltn}6z((Hj4SY0{bbu=BD~n|;c`QuR`B3D&ywXzP=Tne1A&K( z9vqR;nHb-IcK1Ve5Z*h;>J?=i(nf3_wuD0$w+|rpBd1^a%m>3cthyi4h-BM8p2v&t hB}`hWoEVWSE3Hd+DIS%@+lpfzc72`t1FJodN~xyf75V@G diff --git a/signatures/cagebreak.sig b/signatures/cagebreak.sig index a6fd9ddb4fbc1cb45eab137fc1c3ca0cdbf8be3b..f4118cabdb19605f62d0f36c5ea7a59151b8788f 100644 GIT binary patch delta 543 zcmV+)0^t3&1hxc_B7bKD5QP8=2@pjR1+!9&d}GUv5CD`cC0*Yx28cjUv@D$czxv)h zMjgxHY2@G=ugE+((`TJu_79S=(^WFIHUCjGn8z@SU$<2PDIA%8vWX)&=aF{aaPZ`j zUN_~ZQfI%kg?9Mm<*d1qKr)& z=rGio^Mo})7#bZE+Zh^8I1Y<;Vv&{F{|t)kc)Wya_6N+})%=-uIXAADdM!x%H?T$@ zS*++(RqP^j#$PuN_2?<94N`N+7HD+fqbt|T9|0-L)nb1hw_%i!gx?-X{j?dva;>Wd zG68~WgXRcT#D4%*p@h^9+H(=nC>nc?JT*kh4#uT)Dk*x%% zm;(NzTTl{LuNlZN;sTDuTidAl}%9@uj;PQc2Fhc=cDnd9;Z8y%g;;sXS@?)H%|G4CSy;+Kx+# zVj*8GGyWNRaF7a(lJSnpPu|xVzhbHa)CWJAa%o4W0q>x~4*S<=s|k)~gO|6?U0>6a hM23yQBN&G%!ln!y1^CEj1;2zmej delta 543 zcmV+)0^t3&1hxc_B7bGH+o=Ew2@pjR1+!9&d}DJA5C2)|y;8L$fVC0k82Z1xtj>D2 zNW@|25WqNVYm5t!L7JbjjP+Ke^}UbzLvuXi#cCQXwD#X)y-*{PuFMvPIA{5Xhr_NX zCei}X2__94mLihA2{wfFv?R|ctjot!Hm#sE`ZQvlX)aE6tACHc^}b>?cIx6&Y#i^l znpEGW-abM&#xY2;#(}Be)Ruld+EQD>nxKPN9)(v$i8SE$6>gvaf7Y4e^+$kgAWOB} z$LIF$4Hlf4sY=ZOsZ1|#4OaXm~J^J199S;`&c;;Z)4%G8q zKC~*H%~?DdpR3T8ce{$Ip#3x>x7oA!cC9|&4R~KeIW_Ggy(uYvWjU}BVC*VcO2m$# zGna+vEQ^;_`t0!qZ<6$O`UBEO>tOad@D!fs<#urzc7F#O4If2}=&h>>Ny|?C3}a-; zmurMiX%a`&43G>p*5D+o2n$d_UFi^{A)gEfRXWLdTwz0;DfQkMGluAAb0(7(CGIyp zVwmb0eBT*S@JiWDPYPzu#p3vK`mg(n5Cr5}{yCpGtgMJBneUW(XMI)EQ-(jtMEHRT5o7=W diff --git a/view.c b/view.c index 1d2d9c3..88e60bb 100644 --- a/view.c +++ b/view.c @@ -109,8 +109,6 @@ view_unmap(struct cg_view *view) { tile_id = view->tile->id; } - wlr_scene_node_destroy(&view->scene_tree->node); - #if CG_HAS_XWAYLAND if((view->type != CG_XWAYLAND_VIEW || xwayland_view_should_manage(view))) #endif @@ -140,6 +138,8 @@ view_unmap(struct cg_view *view) { } #endif + wlr_scene_node_destroy(&view->scene_tree->node); + wl_list_remove(&view->link); view->wlr_surface = NULL; @@ -156,7 +156,7 @@ view_map(struct cg_view *view, struct wlr_surface *surface, struct cg_output *output = ws->output; view->wlr_surface = surface; - view->scene_tree = wlr_scene_subsurface_tree_create(ws->scene, surface); + wlr_scene_node_reparent(&view->scene_tree->node, ws->scene); if(!view->scene_tree) { wl_resource_post_no_memory(surface->resource); return; @@ -217,4 +217,7 @@ view_init(struct cg_view *view, enum cg_view_type type, view->impl = impl; view->id = server->views_curr_id; ++server->views_curr_id; + view->scene_tree = wlr_scene_tree_create( + server->curr_output->workspaces[server->curr_output->curr_workspace] + ->scene); } diff --git a/workspace.c b/workspace.c index 7d93183..8fc9f80 100644 --- a/workspace.c +++ b/workspace.c @@ -30,8 +30,7 @@ workspace_tile_update_view(struct cg_tile *tile, struct cg_view *view) { } int -full_screen_workspace_tiles(struct wlr_output_layout *layout, - struct cg_workspace *workspace, +full_screen_workspace_tiles(struct cg_workspace *workspace, uint32_t *tiles_curr_id) { workspace->focused_tile = calloc(1, sizeof(struct cg_tile)); if(!workspace->focused_tile) { @@ -68,8 +67,8 @@ full_screen_workspace(struct cg_output *output) { workspace->server = output->server; workspace->num = -1; workspace->scene = wlr_scene_tree_create(&scene_output->scene->tree); - if(full_screen_workspace_tiles(output->server->output_layout, workspace, - &output->server->tiles_curr_id) != 0) { + if(full_screen_workspace_tiles(workspace, &output->server->tiles_curr_id) != + 0) { free(workspace); return NULL; } @@ -106,6 +105,7 @@ workspace_free_tiles(struct cg_workspace *workspace) { void workspace_free(struct cg_workspace *workspace) { + wlr_scene_node_destroy(&workspace->scene->node); workspace_free_tiles(workspace); free(workspace); } diff --git a/workspace.h b/workspace.h index 83b41a1..8ee08a7 100644 --- a/workspace.h +++ b/workspace.h @@ -32,8 +32,7 @@ struct cg_workspace { struct cg_workspace * full_screen_workspace(struct cg_output *output); int -full_screen_workspace_tiles(struct wlr_output_layout *layout, - struct cg_workspace *workspace, +full_screen_workspace_tiles(struct cg_workspace *workspace, uint32_t *tiles_curr_id); void workspace_free_tiles(struct cg_workspace *workspace); diff --git a/xdg_shell.c b/xdg_shell.c index fa15ad0..41abbf2 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -20,53 +20,35 @@ #include "workspace.h" #include "xdg_shell.h" -static struct cg_view * -popup_get_view(struct wlr_xdg_popup *popup) { - while(true) { - if(popup->parent == NULL) { - return NULL; - } - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_try_from_wlr_surface(popup->parent); - if(xdg_surface == NULL) { - return NULL; - } - switch(xdg_surface->role) { - case WLR_XDG_SURFACE_ROLE_TOPLEVEL: - return xdg_surface->data; - case WLR_XDG_SURFACE_ROLE_POPUP: - popup = xdg_surface->popup; - break; - case WLR_XDG_SURFACE_ROLE_NONE: - return NULL; - } - } -} - static void -xdg_decoration_handle_destroy(struct wl_listener *listener, void *data) { +xdg_decoration_handle_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_xdg_decoration *xdg_decoration = wl_container_of(listener, xdg_decoration, destroy); wl_list_remove(&xdg_decoration->destroy.link); wl_list_remove(&xdg_decoration->request_mode.link); + wl_list_remove(&xdg_decoration->link); free(xdg_decoration); } static void -xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { +xdg_decoration_handle_request_mode(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xdg_decoration *xdg_decoration = wl_container_of(listener, xdg_decoration, request_mode); - enum wlr_xdg_toplevel_decoration_v1_mode mode; - mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; - wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration, - mode); + if(xdg_decoration->wlr_decoration->toplevel->base->initialized) { + wlr_xdg_toplevel_decoration_v1_set_mode( + xdg_decoration->wlr_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } } static void -popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup) { - struct wlr_box *popup_box = &popup->current.geometry; +popup_unconstrain(struct cg_xdg_shell_popup *popup) { + struct cg_view *view = popup->view; + struct wlr_box *popup_box = &popup->wlr_popup->current.geometry; struct wlr_output_layout *output_layout = view->server->output_layout; struct wlr_output *wlr_output = wlr_output_layout_output_at( @@ -83,7 +65,7 @@ popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup) { .width = output_box.width, .height = output_box.height}; - wlr_xdg_popup_unconstrain_from_box(popup, &output_toplevel_box); + wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box); } static struct cg_xdg_shell_view * @@ -109,42 +91,38 @@ static char * get_title(const struct cg_view *view) { const struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_const_view(view); - return xdg_shell_view->xdg_surface->toplevel->title; + return xdg_shell_view->toplevel->title; } static bool is_primary(const struct cg_view *view) { const struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_const_view(view); - struct wlr_xdg_toplevel *parent = - xdg_shell_view->xdg_surface->toplevel->parent; + struct wlr_xdg_toplevel *parent = xdg_shell_view->toplevel->parent; return parent == NULL; } static void activate(struct cg_view *view, bool activate) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_toplevel_set_activated(xdg_shell_view->xdg_surface->toplevel, - activate); + wlr_xdg_toplevel_set_activated(xdg_shell_view->toplevel, activate); } static void close(struct cg_view *view) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - struct wlr_xdg_surface *surface = xdg_shell_view->xdg_surface; - if(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { - wlr_xdg_toplevel_send_close(surface->toplevel); + if(view->type == CG_XDG_SHELL_VIEW) { + wlr_xdg_toplevel_send_close(xdg_shell_view->toplevel); } } static void maximize(struct cg_view *view, int width, int height) { struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); - wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface->toplevel, width, - height); + wlr_xdg_toplevel_set_size(xdg_shell_view->toplevel, width, height); enum wlr_edges edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM; - wlr_xdg_toplevel_set_tiled(xdg_shell_view->xdg_surface->toplevel, edges); + wlr_xdg_toplevel_set_tiled(xdg_shell_view->toplevel, edges); } static void @@ -154,29 +132,33 @@ destroy(struct cg_view *view) { } static void -handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, - void *data) { +handle_xdg_shell_surface_request_fullscreen( + struct wl_listener *listener, __attribute__((unused)) void *data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_fullscreen); /** * Certain clients do not like figuring out their own window geometry if - * they display in fullscreen mode, so we set it here. + * they display in fullscreen mode, so we set it here (if the view was + * already mapped). */ - struct wlr_box layout_box; - wlr_output_layout_get_box( - xdg_shell_view->view.server->output_layout, - xdg_shell_view->view.workspace->output->wlr_output, &layout_box); - wlr_xdg_toplevel_set_size(xdg_shell_view->xdg_surface->toplevel, - layout_box.width, layout_box.height); + if(xdg_shell_view->view.workspace != NULL) { + struct wlr_box layout_box; + wlr_output_layout_get_box( + xdg_shell_view->view.server->output_layout, + xdg_shell_view->view.workspace->output->wlr_output, &layout_box); + wlr_xdg_toplevel_set_size(xdg_shell_view->toplevel, layout_box.width, + layout_box.height); + } wlr_xdg_toplevel_set_fullscreen( - xdg_shell_view->xdg_surface->toplevel, - xdg_shell_view->xdg_surface->toplevel->requested.fullscreen); + xdg_shell_view->toplevel, + xdg_shell_view->toplevel->requested.fullscreen); } static void -handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *_data) { +handle_xdg_shell_surface_unmap(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, unmap); struct cg_view *view = &xdg_shell_view->view; @@ -184,19 +166,33 @@ handle_xdg_shell_surface_unmap(struct wl_listener *listener, void *_data) { view_unmap(view); } +struct cg_xdg_decoration * +xdg_decoration_from_surface(struct wlr_surface *surface, + struct cg_server *server) { + struct cg_xdg_decoration *deco; + wl_list_for_each(deco, &server->xdg_decorations, link) { + if(deco->wlr_decoration->toplevel->base->surface == surface) { + return deco; + } + } + return NULL; +} + static void -handle_xdg_shell_surface_map(struct wl_listener *listener, void *_data) { +handle_xdg_shell_surface_map(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, map); struct cg_view *view = &xdg_shell_view->view; - view_map(view, xdg_shell_view->xdg_surface->surface, + view_map(view, xdg_shell_view->toplevel->base->surface, view->server->curr_output ->workspaces[view->server->curr_output->curr_workspace]); } static void -handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *_data) { +handle_xdg_shell_surface_destroy(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, destroy); struct cg_view *view = &xdg_shell_view->view; @@ -204,8 +200,9 @@ handle_xdg_shell_surface_destroy(struct wl_listener *listener, void *_data) { wl_list_remove(&xdg_shell_view->map.link); wl_list_remove(&xdg_shell_view->unmap.link); wl_list_remove(&xdg_shell_view->destroy.link); + wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); - xdg_shell_view->xdg_surface = NULL; + xdg_shell_view->toplevel = NULL; view_destroy(view); } @@ -220,81 +217,169 @@ static const struct cg_view_impl xdg_shell_view_impl = {.get_pid = get_pid, .destroy = destroy}; void -handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) { - struct cg_server *server = - wl_container_of(listener, server, new_xdg_shell_surface); - struct wlr_xdg_surface *xdg_surface = data; - - switch(xdg_surface->role) { - case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; - struct cg_xdg_shell_view *xdg_shell_view = - calloc(1, sizeof(struct cg_xdg_shell_view)); - if(!xdg_shell_view) { - wlr_log(WLR_ERROR, "Failed to allocate XDG Shell view"); - return; +handle_xdg_shell_toplevel_commit(struct wl_listener *listener, + __attribute__((unused)) void *data) { + struct cg_xdg_shell_view *xdg_shell_view = + wl_container_of(listener, xdg_shell_view, commit); + struct cg_view *view = &xdg_shell_view->view; + struct wlr_xdg_surface *xdg_surface = xdg_shell_view->toplevel->base; + if(xdg_surface->initial_commit) { + struct cg_xdg_decoration *decoration = + xdg_decoration_from_surface(xdg_surface->surface, view->server); + if(decoration != NULL) { + wlr_xdg_toplevel_decoration_v1_set_mode( + decoration->wlr_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); } + wlr_xdg_surface_schedule_configure(xdg_surface); + wlr_xdg_toplevel_set_wm_capabilities( + xdg_shell_view->toplevel, XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); + } +} - view_init(&xdg_shell_view->view, CG_XDG_SHELL_VIEW, - &xdg_shell_view_impl, server); - - xdg_shell_view->xdg_surface = xdg_surface; - - xdg_shell_view->map.notify = handle_xdg_shell_surface_map; - wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map); - xdg_shell_view->unmap.notify = handle_xdg_shell_surface_unmap; - wl_signal_add(&xdg_surface->surface->events.unmap, - &xdg_shell_view->unmap); - xdg_shell_view->destroy.notify = handle_xdg_shell_surface_destroy; - wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); - xdg_shell_view->request_fullscreen.notify = - handle_xdg_shell_surface_request_fullscreen; - wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, - &xdg_shell_view->request_fullscreen); - - xdg_surface->data = xdg_shell_view; - break; - case WLR_XDG_SURFACE_ROLE_POPUP:; - struct wlr_xdg_popup *popup = xdg_surface->popup; - struct cg_view *view = popup_get_view(popup); - if(view == NULL) { - return; - } +void +handle_xdg_shell_toplevel_new(struct wl_listener *listener, void *data) { + struct cg_server *server = + wl_container_of(listener, server, new_xdg_shell_toplevel); + struct wlr_xdg_toplevel *xdg_toplevel = data; + wlr_xdg_surface_ping(xdg_toplevel->base); - struct wlr_scene_tree *parent_scene_tree = NULL; - struct wlr_xdg_surface *parent = - wlr_xdg_surface_try_from_wlr_surface(popup->parent); - if(parent == NULL) { - return; - } - switch(parent->role) { - case WLR_XDG_SURFACE_ROLE_TOPLEVEL:; - parent_scene_tree = view->scene_tree; - break; - case WLR_XDG_SURFACE_ROLE_POPUP: - parent_scene_tree = parent->data; - break; - case WLR_XDG_SURFACE_ROLE_NONE: - break; - } - if(parent_scene_tree == NULL) { - return; - } + struct cg_xdg_shell_view *xdg_shell_view = + calloc(1, sizeof(struct cg_xdg_shell_view)); + if(!xdg_shell_view) { + wlr_log(WLR_ERROR, "Failed to allocate XDG Shell view"); + return; + } - struct wlr_scene_tree *popup_scene_tree = - wlr_scene_xdg_surface_create(parent_scene_tree, xdg_surface); - if(popup_scene_tree == NULL) { - wlr_log(WLR_ERROR, - "Failed to allocate scene-graph node for XDG popup"); - return; - } + view_init(&xdg_shell_view->view, CG_XDG_SHELL_VIEW, &xdg_shell_view_impl, + server); + + xdg_shell_view->toplevel = xdg_toplevel; + + xdg_shell_view->new_popup.notify = handle_xdg_shell_popup_new; + wl_signal_add(&xdg_toplevel->base->events.new_popup, + &xdg_shell_view->new_popup); + xdg_shell_view->commit.notify = handle_xdg_shell_toplevel_commit; + wl_signal_add(&xdg_toplevel->base->surface->events.commit, + &xdg_shell_view->commit); + xdg_shell_view->map.notify = handle_xdg_shell_surface_map; + wl_signal_add(&xdg_toplevel->base->surface->events.map, + &xdg_shell_view->map); + xdg_shell_view->unmap.notify = handle_xdg_shell_surface_unmap; + wl_signal_add(&xdg_toplevel->base->surface->events.unmap, + &xdg_shell_view->unmap); + xdg_shell_view->destroy.notify = handle_xdg_shell_surface_destroy; + wl_signal_add(&xdg_toplevel->base->events.destroy, + &xdg_shell_view->destroy); + xdg_shell_view->request_fullscreen.notify = + handle_xdg_shell_surface_request_fullscreen; + wl_signal_add(&xdg_toplevel->events.request_fullscreen, + &xdg_shell_view->request_fullscreen); + + wlr_scene_xdg_surface_create(xdg_shell_view->view.scene_tree, + xdg_toplevel->base); + xdg_toplevel->base->data = xdg_shell_view; + return; +} + +static void +handle_xdg_shell_popup_destroy(struct wl_listener *listener, + __attribute__((unused)) void *data) { + struct cg_xdg_shell_popup *popup = + wl_container_of(listener, popup, destroy); + + wl_list_remove(&popup->new_popup.link); + wl_list_remove(&popup->destroy.link); + wl_list_remove(&popup->commit.link); + wl_list_remove(&popup->reposition.link); + wlr_scene_node_destroy(&popup->scene_tree->node); + free(popup); +} + +static void +handle_xdg_shell_popup_commit(struct wl_listener *listener, + __attribute__((unused)) void *data) { + struct cg_xdg_shell_popup *popup = wl_container_of(listener, popup, commit); + if(popup->wlr_popup->base->initial_commit) { + popup_unconstrain(popup); + } +} - popup_unconstrain(view, popup); +static void +handle_xdg_shell_popup_reposition(struct wl_listener *listener, + __attribute__((unused)) void *data) { + struct cg_xdg_shell_popup *popup = wl_container_of(listener, popup, commit); + popup_unconstrain(popup); +} + +static struct cg_xdg_shell_popup * +create_xdg_popup(struct wlr_xdg_popup *wlr_popup, struct cg_view *view, + struct wlr_scene_tree *parent_tree); + +void +handle_xdg_shell_popup_new_popup(struct wl_listener *listener, void *data) { + struct cg_xdg_shell_popup *popup = + wl_container_of(listener, popup, new_popup); + struct wlr_xdg_popup *wlr_popup = data; + create_xdg_popup(wlr_popup, popup->view, popup->xdg_surface_tree); +} + +static struct cg_xdg_shell_popup * +create_xdg_popup(struct wlr_xdg_popup *wlr_popup, struct cg_view *view, + struct wlr_scene_tree *parent_tree) { + + struct wlr_xdg_surface *xdg_surface = wlr_popup->base; + struct cg_xdg_shell_popup *popup = calloc(1, sizeof(*popup)); + if(!popup) { + return NULL; + } - xdg_surface->data = popup_scene_tree; - break; - case WLR_XDG_SURFACE_ROLE_NONE: - assert(false); // unreachable + popup->wlr_popup = wlr_popup; + popup->view = view; + struct cg_xdg_shell_view *xdg_view = wl_container_of(view, xdg_view, view); + xdg_surface->data = xdg_view; + popup->scene_tree = wlr_scene_tree_create(parent_tree); + if(!popup->scene_tree) { + free(popup); + return NULL; } + + popup->xdg_surface_tree = + wlr_scene_xdg_surface_create(popup->scene_tree, xdg_surface); + if(!popup->xdg_surface_tree) { + wlr_scene_node_destroy(&popup->scene_tree->node); + free(popup); + return NULL; + } + + wl_signal_add(&xdg_surface->surface->events.commit, &popup->commit); + popup->commit.notify = handle_xdg_shell_popup_commit; + wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); + popup->new_popup.notify = handle_xdg_shell_popup_new_popup; + wl_signal_add(&wlr_popup->events.reposition, &popup->reposition); + popup->reposition.notify = handle_xdg_shell_popup_reposition; + wl_signal_add(&wlr_popup->events.destroy, &popup->destroy); + popup->destroy.notify = handle_xdg_shell_popup_destroy; + return popup; +} + +void +handle_xdg_shell_popup_new(struct wl_listener *listener, void *data) { + + struct cg_xdg_shell_view *xdg_shell_view = + wl_container_of(listener, xdg_shell_view, new_popup); + struct wlr_xdg_popup *xdg_popup = data; + + struct cg_xdg_shell_popup *popup = create_xdg_popup( + xdg_popup, &xdg_shell_view->view, xdg_shell_view->view.scene_tree); + if(!popup) { + return; + } + + int lx, ly; + wlr_scene_node_coords(&popup->view->scene_tree->node, &lx, &ly); + wlr_scene_node_set_position(&popup->scene_tree->node, lx, ly); + return; } void @@ -309,6 +394,8 @@ handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) { return; } + wl_list_insert(&server->xdg_decorations, &xdg_decoration->link); + xdg_decoration->wlr_decoration = wlr_decoration; xdg_decoration->server = server; @@ -317,7 +404,4 @@ handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) { xdg_decoration->request_mode.notify = xdg_decoration_handle_request_mode; wl_signal_add(&wlr_decoration->events.request_mode, &xdg_decoration->request_mode); - - xdg_decoration_handle_request_mode(&xdg_decoration->request_mode, - wlr_decoration); } diff --git a/xdg_shell.h b/xdg_shell.h index 5f9456c..52cba0f 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -8,23 +8,41 @@ struct cg_xdg_shell_view { struct cg_view view; - struct wlr_xdg_surface *xdg_surface; + struct wlr_xdg_toplevel *toplevel; struct wl_listener destroy; + struct wl_listener commit; struct wl_listener unmap; struct wl_listener map; + struct wl_listener new_popup; struct wl_listener request_fullscreen; }; +struct cg_xdg_shell_popup { + struct cg_view *view; + struct wlr_xdg_popup *wlr_popup; + struct wlr_scene_tree *scene_tree; + struct wlr_scene_tree *xdg_surface_tree; + + struct wl_listener commit; + struct wl_listener new_popup; + struct wl_listener reposition; + struct wl_listener destroy; +}; + struct cg_xdg_decoration { struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration; struct cg_server *server; struct wl_listener destroy; struct wl_listener request_mode; + struct wl_list link; // server::xdg_decorations }; void -handle_xdg_shell_surface_new(struct wl_listener *listener, void *data); +handle_xdg_shell_toplevel_new(struct wl_listener *listener, void *data); + +void +handle_xdg_shell_popup_new(struct wl_listener *listener, void *data); void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data); diff --git a/xwayland.c b/xwayland.c index 5755148..3eafc4f 100644 --- a/xwayland.c +++ b/xwayland.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #if CG_HAS_XWAYLAND @@ -69,7 +70,7 @@ static void activate(struct cg_view *view, bool activate) { struct cg_xwayland_view *xwayland_view = xwayland_view_from_view(view); wlr_xwayland_surface_activate(xwayland_view->xwayland_surface, activate); - if(activate) { + if(activate && !xwayland_view->xwayland_surface->override_redirect) { wlr_xwayland_surface_restack(xwayland_view->xwayland_surface, NULL, XCB_STACK_MODE_ABOVE); } @@ -112,7 +113,7 @@ destroy(struct cg_view *view) { static void handle_xwayland_surface_request_fullscreen(struct wl_listener *listener, - void *data) { + __attribute__((unused)) void *data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, request_fullscreen); struct wlr_xwayland_surface *xwayland_surface = @@ -122,7 +123,8 @@ handle_xwayland_surface_request_fullscreen(struct wl_listener *listener, } static void -handle_xwayland_surface_unmap(struct wl_listener *listener, void *_data) { +handle_xwayland_surface_unmap(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, unmap); struct cg_view *view = &xwayland_view->view; @@ -131,7 +133,8 @@ handle_xwayland_surface_unmap(struct wl_listener *listener, void *_data) { } static void -handle_xwayland_surface_map(struct wl_listener *listener, void *_data) { +handle_xwayland_surface_map(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, map); struct cg_view *view = &xwayland_view->view; @@ -145,10 +148,13 @@ handle_xwayland_surface_map(struct wl_listener *listener, void *_data) { view_map(view, xwayland_view->xwayland_surface->surface, view->server->curr_output ->workspaces[view->server->curr_output->curr_workspace]); + xwayland_view->scene_tree = wlr_scene_subsurface_tree_create( + view->scene_tree, xwayland_view->xwayland_surface->surface); } static void -handle_xwayland_surface_destroy(struct wl_listener *listener, void *_data) { +handle_xwayland_surface_destroy(struct wl_listener *listener, + __attribute__((unused)) void *_data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, destroy); struct cg_view *view = &xwayland_view->view; @@ -171,7 +177,8 @@ static const struct cg_view_impl xwayland_view_impl = { }; static void -handle_xwayland_surface_associate(struct wl_listener *listener, void *data) { +handle_xwayland_surface_associate(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, associate); struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface; @@ -182,7 +189,8 @@ handle_xwayland_surface_associate(struct wl_listener *listener, void *data) { } static void -handle_xwayland_surface_dissociate(struct wl_listener *listener, void *data) { +handle_xwayland_surface_dissociate(struct wl_listener *listener, + __attribute__((unused)) void *data) { struct cg_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, dissociate); wl_list_remove(&xwayland_view->map.link); @@ -202,6 +210,8 @@ handle_xwayland_surface_new(struct wl_listener *listener, void *data) { return; } + xwayland_view->scene_tree = NULL; + view_init(&xwayland_view->view, CG_XWAYLAND_VIEW, &xwayland_view_impl, server); xwayland_view->xwayland_surface = xwayland_surface; diff --git a/xwayland.h b/xwayland.h index 6661f0e..d58af58 100644 --- a/xwayland.h +++ b/xwayland.h @@ -9,6 +9,7 @@ struct cg_xwayland_view { struct cg_view view; struct wlr_xwayland_surface *xwayland_surface; + struct wlr_scene_tree *scene_tree; struct wl_listener destroy; struct wl_listener unmap;