From 83835d51cfcc8c4ddf3e0362fcd469d6ab72720c Mon Sep 17 00:00:00 2001 From: Cagebreak Signing Key 3 Date: Wed, 3 Jun 2020 18:16:52 +0200 Subject: [PATCH] Release 1.3.1 - Improve README - Reference AUR Package - Add security bug contact - Add appropriate GPG keys - Fix issue 7 - Fix issue 8 --- Bugs.md | 22 + README.md | 240 +++++--- cagebreak.c | 5 +- fuzz/fuzz-lib.c | 554 ++++++++++++++++++ fuzz/fuzz-lib.h | 49 ++ fuzz/fuzz-parse.c | 391 +----------- fuzz/meson.build | 2 + keys/cagebreak@project-repo.co.pub | 75 +++ keys/cagebreak_signing_key_1.asc | 65 -- keys/cagebreak_signing_key_1@cagebreak.pub | 88 +++ ... => cagebreak_signing_key_2@cagebreak.pub} | 0 ...agebreak_signing_key_3@project-repo.co.pub | 76 +++ ...agebreak_signing_key_4@project-repo.co.pub | 64 ++ man/cagebreak-config.5.md | 2 +- man/cagebreak.1.md | 2 +- meson.build | 6 +- render.c | 25 + signatures/1.3.0.sig | Bin 0 -> 566 bytes signatures/cagebreak.sig | Bin 566 -> 566 bytes view.c | 46 +- view.h | 1 + xdg_shell.c | 24 +- 22 files changed, 1187 insertions(+), 550 deletions(-) create mode 100644 fuzz/fuzz-lib.c create mode 100644 fuzz/fuzz-lib.h create mode 100644 keys/cagebreak@project-repo.co.pub delete mode 100644 keys/cagebreak_signing_key_1.asc create mode 100644 keys/cagebreak_signing_key_1@cagebreak.pub rename keys/{cagebreak_signing_key_2.asc => cagebreak_signing_key_2@cagebreak.pub} (100%) create mode 100644 keys/cagebreak_signing_key_3@project-repo.co.pub create mode 100644 keys/cagebreak_signing_key_4@project-repo.co.pub create mode 100644 signatures/1.3.0.sig diff --git a/Bugs.md b/Bugs.md index f39de1c..dc238c4 100644 --- a/Bugs.md +++ b/Bugs.md @@ -97,3 +97,25 @@ difficult to reproduce. Our fuzzing framework up to and including release 1.2.0 does not limit line lengths. This can crash the fuzzing framework with a segfault due to running out of memory. + +### Issue 7 + + * github issue number: N/A + * Fixed: 1.3.1 + +Cagebreak up to and including release 1.3.0 does not ensure that windows +are resized correctly. The download save dialog in firefox +demonstrates this issue, as it may be rendered larger than the current +monitor. As of release 1.3.1 the size of every window is checked on +rendering and adjusted if necessary. + +### Issue 8 + + * github issue number: N/A + * Fixed: 1.3.1 + +Cagebreak up to and including release 1.3.0 does not force windows +to resize to the appropriate size. Calling `vsplit` on inkscape +demonstrates this issue, since it causes adjacent tiles to overlap +(contrary to the idea of a tiling compositor). + diff --git a/README.md b/README.md index 19a1f02..f4da22e 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,41 @@ provide a successor to ratpoison for Wayland users. However, this is no reimplementation of ratpoison. Should you like to know if a feature will be implemented, open an issue or get in touch with the development team. -This README is only relevant for development resources and instructions. For a -description of Cagebreak and installation instructions for end-users, please see -the man page supplied in the `man/` directory and the [Wiki](https://github.com/project-repo/cagebreak/wiki/). +This README is only relevant for development resources and instructions. For +documentation of Cagebreak, please see +the man pages for [cagebreak](man/cagebreak.1.md) and cagebreak +[configuration](man/cagebreak-config.5.md) and the +[Wiki](https://github.com/project-repo/cagebreak/wiki/). Cagebreak is based on [Cage](https://github.com/Hjdskes/cage), a Wayland kiosk compositor. -## Experimenting with Cagebreak - -Cagebreak is currently being developed under arch linux and uses the libraries +Cagebreak is currently being developed under Arch Linux and uses the libraries as they are obtained through pacman. However, cagebreak should also work on other distributions given the proper library versions. +## Installation + +If you are using archlinux, just clone the [PKGBUILD](https://aur.archlinux.org/cagebreak.git) from the aur. + +See [cagebreak-pkgbuild](https://github.com/project-repo/cagebreak-pkgbuild) for details. + +### Obtaining Source Code + +There are different ways to obtain cagebreak source: + + * git clone (for all releases) + * download release asset tarballs (starting at release 1.2.1) + +### Verifying Source Code + +There are corresponding methods of verifying that you obtained the correct code: + + * our git history includes signed tags for releases + * release assets starting at release 1.2.1 contain a signature for the tarball + +### Building Cagebreak + You can build Cagebreak with the [meson](https://mesonbuild.com/) build system. It requires wayland, wlroots and xkbcommon to be installed. Note that Cagebreak is developed against the latest tag of wlroots, in order not to constantly chase @@ -30,12 +52,12 @@ $ meson build $ ninja -C build ``` -### Release Build +#### Release Build By default, this builds a debug build. To build a release build, use `meson build --buildtype=release`. -### Xwayland Support +#### Xwayland Support Cagebreak comes with compile-time support for XWayland. To enable this, first make sure that your version of wlroots is compiled with this @@ -61,34 +83,7 @@ Nonetheless, don't be intimidated by the (slightly lengthy) release checklist or part of this file. Do what you can, open an issue and we will collaborate toward a solution. -### GCC and -fanalyzer - -Cagebreak should compile with any reasonably new gcc or clang. Consider -a gcc version of at least [10.1](https://gcc.gnu.org/gcc-10/changes.html) if -you want to get the benefit of the brand-new -[-fanalyzer](https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html) -flag. However, this new flag sometimes produces false-postives and we -selectively disable warnings for affected code segments as described below. - -Meson is configured to set `CG_HAS_FANALYZE` if `-fanalyzer` is available. -Therefore, to maintain portability, false-positive fanalyzer warnings are to be -disabled using the following syntax: - -``` -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "WARNING OPTION" -#endif -``` -and after - -``` -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif -``` - -### Branching strategy +### Branching Strategy and Versioning All features are to be developed on feature branches, named after the feature. @@ -98,73 +93,73 @@ are merged for final testing. Once `development` is ready for a release, meaning that the release checklist is fulfilled, it is merged into `master`, creating a new release, which is tagged and signed. -Merging into master is always done by +All releases are tagged according to [semantic versioning](https://semver.org) guidelines. -``` -git checkout development -git pull origin development -git checkout master -git merge --squash development -git tag -u keyid version HEAD -git tag -v version -git push --tags origin master -``` - -and a log message roughly describing the features added in the commit is -included. - -In the past, our git history did not always reflect this scheme. +In the past, our git history did not perfectly reflect this scheme. ### Releases -Release checklist +The release checklist must be completely fulfilled in one run for a release to +occur. Once any failure occurs the entire checklist must be completed from scratch. - * [ ] Cursory testing - * [ ] libfuzzer testing - * [ ] ninja -C build clang-format + * [ ] `git checkout development` + * [ ] `git pull origin development` + * [ ] `git push origin development` + * [ ] Cage has no reasonable code merges + * [ ] `ninja -C build clang-format` makes no changes + * [ ] New version number determined according to [semantic versioning](https://semver.org) guidelines + * [ ] Relevant Documentation completed + * [ ] New features + * [ ] man pages + * [ ] man/cagebreak + * [ ] man/cagebreak-config + * [ ] wiki + * [ ] README.md Changelog for major and minor releases but not patches + * [ ] Fixed bugs documented in Bugs.md + * [ ] Testing + * [ ] Manual testing + * [ ] Libfuzzer testing * [ ] Version Number * [ ] meson.build * [ ] git tag * [ ] man pages - * [ ] Relevant Documentation - * [ ] New features documented - * [ ] man page - * [ ] wiki - * [ ] New configuration documented - * [ ] man page - * [ ] wiki - * [ ] Changelog in README - * [ ] Document fixed bugs in Bugs.md - * [ ] Update hashes of the binary - * [ ] Update signature of the binary - * [ ] Signature - * [ ] Branching Strategy - * [ ] git archive --prefix=cagebreak/ -o release_version.tar.gz tags/version . - * [ ] gpg --detach-sign -u keyid release_version.tar.gz - * [ ] upload build assets - -### Signing Key - -All releases are signed by at least one of the following collection of -keys. - - * E79F6D9E113529F4B1FFE4D5C4F974D70CEC2C5B - * 4739D329C9187A1C2795C20A02ABFDEC3A40545F - -Should we at any point retire a key, we will only replace it with keys signed -by at least one of the above collection. - -Should we at any point have official mail addresses, their keys will be signed by -a valid key noted above. - -The full public keys can be found in `keys/` along with any revocation certificates. + * [ ] `git add` relevant files + * [ ] `git commit` + * [ ] `git push origin development` + * [ ] meson.build reproducible build versions are current archlinux libraries and gcc + * [ ] Cagebreak is reproducible on multiple machines + * [ ] Documented reproducible build artefacts + * [ ] Hashes of the binary + * [ ] Renamed cagebreak.sig to previous_release_tag.sig + * [ ] Signature of the binary as cagebreak.sig with appropriate signing key + * [ ] Determined commit and tag message (Start with "Release version_number\n\n") + * [ ] `git checkout master` + * [ ] `git merge --squash development` + * [ ] `git commit` and insert message + * [ ] `git tag -u keyid version HEAD` and insert message + * [ ] `git tag -v version` and check signing key + * [ ] `git push --tags origin master` + * [ ] `git checkout development` + * [ ] `git merge master` + * [ ] `git push --tags origin development` + * [ ] `git archive --prefix=cagebreak/ -o release_version.tar.gz tags/version .` + * [ ] Checked archive + * [ ] tar -xvf release_version.tar.gz + * [ ] cd cagebreak + * [ ] meson build --buildtype=release + * [ ] ninja -C build + * [ ] gpg --verify ../signatures/cagebreak.sig build/cagebreak + * [ ] cd .. + * [ ] rm -rf cagebreak + * [ ] `gpg --detach-sign -u keyid release_version.tar.gz` + * [ ] Upload archive and signature as release assets ### Reproducible Builds Cagebreak offers reproducible builds given the exact library versions specified in `meson.build`. Should a version mismatch occur, a warning will be emitted. We have decided on this compromise to allow flexibility and security. In general we will -adapt the versions to the packages available under arch linux at the time of +adapt the versions to the packages available under Arch Linux at the time of release. There are reproducibility issues up to and including release `1.2.0`. See @@ -183,6 +178,11 @@ ninja -C build For every release after 1.0.5, hashes will be provided. +1.3.1 + + * sha 256: 71be224cd99d20da4f039675ec5c48213dd14ef027b804501fa3241886b2b08b + * sha 512: d094b786e5a74b01699997a85747943e6de3544cc903dd1c5dba449c66bd925b6378de800d3734969dabf8a20c7004dc3402e3c59577db09ce107b68a1f7bd21 + 1.3.0 * sha 256: aecc5292f56f7250d777110cee1f11a92018a9eb2117d7d37cd51d7d3a5cbae0 @@ -215,6 +215,53 @@ For every release after 1.0.5, a GPG signature will be provided in `signatures`. The current signature is called `cagebreak.sig`, whereas all older signatures will be named after their release version. +#### Signing Keys + +All releases are signed by at least one of the following collection of +keys. + + * E79F6D9E113529F4B1FFE4D5C4F974D70CEC2C5B + * 4739D329C9187A1C2795C20A02ABFDEC3A40545F + * 7535AB89220A5C15A728B75F74104CC7DCA5D7A8 + * 827BC2320D535AEAD0540E6E2E66F65D99761A6F + +Should we at any point retire a key, we will only replace it with keys signed +by at least one of the above collection. + +We registered project-repo.co and added mail addresses after release `1.3.0`. + +We now have a mail address and its key is signed by signing keys. See Security +Bugs for details. + +The full public keys can be found in `keys/` along with any revocation certificates. + +### GCC and -fanalyzer + +Cagebreak should compile with any reasonably new gcc or clang. Consider +a gcc version of at least [10.1](https://gcc.gnu.org/gcc-10/changes.html) if +you want to get the benefit of the brand-new +[-fanalyzer](https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html) +flag. However, this new flag sometimes produces false-postives and we +selectively disable warnings for affected code segments as described below. + +Meson is configured to set `CG_HAS_FANALYZE` if `-fanalyzer` is available. +Therefore, to maintain portability, false-positive fanalyzer warnings are to be +disabled using the following syntax: + +``` +#if CG_HAS_FANALYZE +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "WARNING OPTION" +#endif +``` +and after + +``` +#if CG_HAS_FANALYZE +#pragma GCC diagnostic pop +#endif +``` + ### Fuzzing Along with the project source code, a fuzzing framework based on `libfuzzer` is @@ -250,6 +297,23 @@ issue](https://github.com/project-repo/cagebreak/issues/new) on Fixed bugs are to be assigned a number and summarized inside Bugs.md for future reference independent of github, in case this service is unavailable. +### Security Bugs + +Should you want to get in touch with the developers of cagebreak to report a +security vulnerability or a different issue confidentially, contact +`cagebreak @ project-repo . co`. + +We will try to respond to everything that is not obvious spam. + +Please encrypt your email with the appropriate [GPG key](keys/cagebreak@project-repo.co.pub). + + * B15B92642760E11FE002DE168708D42451A94AB5 + +Note that the key is signed by cagebreak signing keys. + +If you want us to respond via GPG-encrypted mail, please include your own +public key or provide the fingerprint and directions to obtain the key. + ## Changelog ### Release 1.0.0 diff --git a/cagebreak.c b/cagebreak.c index f908117..0591591 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -88,13 +88,14 @@ sig_chld_handler(int signal) { static bool drop_permissions(void) { if(getuid() != geteuid() || getgid() != getegid()) { - if(setuid(getuid()) != 0 || setgid(getgid()) != 0) { + // Set gid before uid + if(setgid(getgid()) != 0 || setuid(getuid()) != 0) { wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); return false; } } - if(setuid(0) != -1) { + if(setgid(0) != -1 || setuid(0) != -1) { wlr_log(WLR_ERROR, "Unable to drop root (we shouldn't be able to " "restore it after setuid), refusing to start"); return false; diff --git a/fuzz/fuzz-lib.c b/fuzz/fuzz-lib.c new file mode 100644 index 0000000..e99a21f --- /dev/null +++ b/fuzz/fuzz-lib.c @@ -0,0 +1,554 @@ +/* + * Cagebreak: A Wayland tiling compositor. + * + * Copyright (C) 2018-2020 Jente Hidskes + * + * See the LICENSE file accompanying this file. + */ + +#define _POSIX_C_SOURCE 200812L + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if CG_HAS_XWAYLAND +#include +#endif +#include +#include +#include +#include +#if CG_HAS_XWAYLAND +#include +#endif + +#include "../idle_inhibit_v1.h" +#include "../keybinding.h" +#include "../output.h" +#include "../parse.h" +#include "../seat.h" +#include "../server.h" +#include "../xdg_shell.h" +#if CG_HAS_XWAYLAND +#include "../xwayland.h" +#endif + +#include "fuzz-lib.h" + +static bool +drop_permissions(void) { + if(getuid() != geteuid() || getgid() != getegid()) { + if(setuid(getuid()) != 0 || setgid(getgid()) != 0) { + wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); + return false; + } + } + + if(setuid(0) != -1) { + wlr_log(WLR_ERROR, "Unable to drop root (we shouldn't be able to " + "restore it after setuid), refusing to start"); + return false; + } + + return true; +} + +static bool +parse_args(struct cg_server *server, int argc, char *argv[]) { + server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; +#ifdef DEBUG + server->debug_damage_tracking = false; +#endif + return true; +} + +void +cleanup() { + server.running = false; +#if CG_HAS_XWAYLAND + if(xwayland != NULL) { + wlr_xwayland_destroy(xwayland); + } + if(xcursor_manager != NULL) { + wlr_xcursor_manager_destroy(xcursor_manager); + } +#endif + wl_display_destroy_clients(server.wl_display); + + for(unsigned int i = 0; server.modes[i] != NULL; ++i) { + free(server.modes[i]); + } + free(server.modes); + + keybinding_list_free(server.keybindings); + + seat_destroy(server.seat); + /* This function is not null-safe, but we only ever get here + with a proper wl_display. */ + wl_display_destroy(server.wl_display); + wlr_output_layout_destroy(server.output_layout); +} + +int +LLVMFuzzerInitialize(int *argc, char ***argv) { + struct wl_event_loop *event_loop = NULL; + struct wlr_backend *backend = NULL; + struct wlr_renderer *renderer = NULL; + struct wlr_compositor *compositor = NULL; + struct wlr_data_device_manager *data_device_manager = NULL; + struct wlr_server_decoration_manager *server_decoration_manager = NULL; + struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL; + struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL; + struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; + struct wlr_xdg_output_manager_v1 *output_manager = NULL; + struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; + int ret = 0; + + if(!parse_args(&server, *argc, *argv)) { + return 1; + } + +#ifdef DEBUG + wlr_log_init(WLR_DEBUG, NULL); +#else + wlr_log_init(WLR_ERROR, NULL); +#endif + + /* Wayland requires XDG_RUNTIME_DIR to be set. */ + if(!getenv("XDG_RUNTIME_DIR")) { + wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment"); + return 1; + } + + server.wl_display = wl_display_create(); + if(!server.wl_display) { + wlr_log(WLR_ERROR, "Cannot allocate a Wayland display"); + return 1; + } + + server.running = true; + + server.modes = malloc(4 * sizeof(char *)); + server.modes[0] = strdup("top"); + server.modes[1] = strdup("root"); + server.modes[2] = strdup("resize"); + server.modes[3] = NULL; + + server.nws = 1; + server.message_timeout = 2; + + event_loop = wl_display_get_event_loop(server.wl_display); + server.event_loop = event_loop; + + backend = wlr_multi_backend_create(server.wl_display); + if(!backend) { + wlr_log(WLR_ERROR, "Unable to create the wlroots multi backend"); + ret = 1; + goto end; + } + server.backend = backend; + + struct wlr_backend *headless_backend = + wlr_headless_backend_create(server.wl_display, NULL); + if(!headless_backend) { + wlr_log(WLR_ERROR, "Unable to create the wlroots headless backend"); + ret = 1; + goto end; + } + wlr_headless_add_output(headless_backend, 600, 300); + + if(!wlr_multi_backend_add(backend, headless_backend)) { + wlr_log(WLR_ERROR, + "Unable to insert headless backend into multi backend"); + ret = 1; + goto end; + }; + + if(!drop_permissions()) { + ret = 1; + goto end; + } + + server.keybindings = keybinding_list_init(); + if(server.keybindings == NULL || server.keybindings->keybindings == NULL) { + wlr_log(WLR_ERROR, "Unable to allocate keybindings"); + ret = 1; + goto end; + } + + wl_list_init(&server.output_config); + + renderer = wlr_backend_get_renderer(backend); + wlr_renderer_init_wl_display(renderer, server.wl_display); + + server.bg_color = malloc(4 * sizeof(float)); + server.bg_color[0] = 0; + server.bg_color[1] = 0; + server.bg_color[2] = 0; + server.bg_color[3] = 1; + wl_list_init(&server.outputs); + + server.output_layout = wlr_output_layout_create(); + if(!server.output_layout) { + wlr_log(WLR_ERROR, "Unable to create output layout"); + ret = 1; + goto end; + } + + data_device_manager = wlr_data_device_manager_create(server.wl_display); + if(!data_device_manager) { + wlr_log(WLR_ERROR, "Unable to create the data device manager"); + ret = 1; + goto end; + } + + /* Configure a listener to be notified when new outputs are + * available on the backend. We use this only to detect the + * first output and ignore subsequent outputs. */ + server.new_output.notify = handle_new_output; + wl_signal_add(&backend->events.new_output, &server.new_output); + + server.seat = seat_create(&server, backend); + if(!server.seat) { + wlr_log(WLR_ERROR, "Unable to create the seat"); + ret = 1; + goto end; + } + + server.idle = wlr_idle_create(server.wl_display); + if(!server.idle) { + wlr_log(WLR_ERROR, "Unable to create the idle tracker"); + ret = 1; + goto end; + } + + server.idle_inhibit_v1 = wlr_idle_inhibit_v1_create(server.wl_display); + if(!server.idle_inhibit_v1) { + wlr_log(WLR_ERROR, "Cannot create the idle inhibitor"); + ret = 1; + goto end; + } + server.new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1_new; + wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, + &server.new_idle_inhibitor_v1); + wl_list_init(&server.inhibitors); + + xdg_shell = wlr_xdg_shell_create(server.wl_display); + 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); + + xdg_decoration_manager = + wlr_xdg_decoration_manager_v1_create(server.wl_display); + if(!xdg_decoration_manager) { + wlr_log(WLR_ERROR, "Unable to create the XDG decoration manager"); + ret = 1; + goto end; + } + wl_signal_add(&xdg_decoration_manager->events.new_toplevel_decoration, + &server.xdg_toplevel_decoration); + server.xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; + + server_decoration_manager = + wlr_server_decoration_manager_create(server.wl_display); + if(!server_decoration_manager) { + wlr_log(WLR_ERROR, "Unable to create the server decoration manager"); + ret = 1; + goto end; + } + wlr_server_decoration_manager_set_default_mode( + server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + + export_dmabuf_manager = + wlr_export_dmabuf_manager_v1_create(server.wl_display); + if(!export_dmabuf_manager) { + wlr_log(WLR_ERROR, "Unable to create the export DMABUF manager"); + ret = 1; + goto end; + } + + screencopy_manager = wlr_screencopy_manager_v1_create(server.wl_display); + if(!screencopy_manager) { + wlr_log(WLR_ERROR, "Unable to create the screencopy manager"); + ret = 1; + goto end; + } + + output_manager = wlr_xdg_output_manager_v1_create(server.wl_display, + server.output_layout); + if(!output_manager) { + wlr_log(WLR_ERROR, "Unable to create the output manager"); + ret = 1; + goto end; + } + + gamma_control_manager = + wlr_gamma_control_manager_v1_create(server.wl_display); + if(!gamma_control_manager) { + wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); + ret = 1; + goto end; + } + + compositor = wlr_compositor_create(server.wl_display, renderer); + if(!compositor) { + wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); + ret = 1; + goto end; + } + +#if CG_HAS_XWAYLAND + xwayland = wlr_xwayland_create(server.wl_display, compositor, true); + if(!xwayland) { + wlr_log(WLR_ERROR, "Cannot create XWayland server"); + ret = 1; + goto end; + } + server.new_xwayland_surface.notify = handle_xwayland_surface_new; + wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface); + + xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE); + if(!xcursor_manager) { + wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager"); + ret = 1; + goto end; + } + + if(setenv("DISPLAY", xwayland->display_name, true) < 0) { + 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", + xwayland->display_name); + } + + if(wlr_xcursor_manager_load(xcursor_manager, 1)) { + wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme"); + } + struct wlr_xcursor *xcursor = + wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1); + if(xcursor) { + struct wlr_xcursor_image *image = xcursor->images[0]; + wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4, + image->width, image->height, image->hotspot_x, + image->hotspot_y); + } + +#endif + + const char *socket = wl_display_add_socket_auto(server.wl_display); + if(!socket) { + wlr_log_errno(WLR_ERROR, "Unable to open Wayland socket"); + ret = 1; + goto end; + } + + if(!wlr_backend_start(backend)) { + wlr_log(WLR_ERROR, "Unable to start the wlroots backend"); + ret = 1; + goto end; + } + + if(setenv("WAYLAND_DISPLAY", socket, true) < 0) { + wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.", + "Clients may not be able to connect"); + } else { + wlr_log(WLR_DEBUG, + "Cagebreak " CG_VERSION " is running on Wayland display %s", + socket); + } + + /* Place the cursor to the topl left of the output layout. */ + wlr_cursor_warp(server.seat->cursor, NULL, 0, 0); + atexit(cleanup); + // server.wl_display->run = 1; + return 0; +end: + cleanup(); + return ret; +} + +void +move_cursor(char *line, struct cg_server *server) { + return; // TODO + long del = 0; + char *delstr = strtok_r(NULL, ";", &line); + enum wlr_axis_orientation orientation = + (*(line++) == '0') ? WLR_AXIS_ORIENTATION_VERTICAL + : WLR_AXIS_ORIENTATION_HORIZONTAL; + if(delstr == NULL) { + return; + } + del = strtol(delstr, NULL, 10); + struct wlr_event_pointer_axis event = {.device = NULL, + .time_msec = 0, + .source = WLR_AXIS_SOURCE_WHEEL, + .orientation = orientation, + .delta = del * 15, + .delta_discrete = del}; + // TODO dispatch_cursor_axis(server->seat->cursor, &event); +} + +void +add_output_callback(struct wlr_backend *backend, void *data) { + long *dims = data; + wlr_headless_add_output(backend, dims[0], dims[1]); +} + +void +create_output(char *line, struct cg_server *server) { + char *widthstr = strtok_r(NULL, ";", &line); + long dims[2] = {600, 200}; + if(widthstr != NULL) { + dims[0] = strtol(widthstr, NULL, 10); + if(line[0] != '\0') { + ++line; + } + } + char *heightstr = strtok_r(NULL, ";", &line); + if(heightstr != NULL) { + dims[1] = strtol(heightstr, NULL, 10); + } + long max_dim = 10000; + if(dims[0] > max_dim || dims[0] <= 0) { + wlr_log(WLR_ERROR, "height out of range."); + return; + } else if(dims[1] > max_dim || dims[1] <= 0) { + wlr_log(WLR_ERROR, "width out of range."); + return; + } + wlr_multi_for_each_backend(server->backend, add_output_callback, dims); +} + +void +add_input_device_callback(struct wlr_backend *backend, void *data) { + enum wlr_input_device_type *type = data; + wlr_headless_add_input_device(backend, *type); +} + +void +create_input_device(char *line, struct cg_server *server) { + enum wlr_input_device_type type; + if(*line != '\0') { + if(strncmp(line, "kbd", 3) == 0) { + type = WLR_INPUT_DEVICE_KEYBOARD; + wlr_multi_for_each_backend(server->backend, + add_input_device_callback, &type); + } else if(strncmp(line, "ptr", 3) == 0) { + type = WLR_INPUT_DEVICE_POINTER; + wlr_multi_for_each_backend(server->backend, + add_input_device_callback, &type); + } else if(strncmp(line, "tch", 3) == 0) { + type = WLR_INPUT_DEVICE_TOUCH; + wlr_multi_for_each_backend(server->backend, + add_input_device_callback, &type); + } + } +} + +void +destroy_input_device(char *line, struct cg_server *server) { + long devn = 0; + if(line[0] != '\0') { + devn = strtol(line + 1, NULL, 10); + } + if(line != NULL) { + if(strncmp(line, "k", 1) == 0) { + if(wl_list_empty(&server->seat->keyboard_groups)) { + return; + } + devn = devn % wl_list_length(&server->seat->keyboard_groups); + struct cg_keyboard_group *group, *group_tmp; + wl_list_for_each_safe(group, group_tmp, + &server->seat->keyboard_groups, link) { + if(devn == 0) { + wl_list_remove(&group->link); + wlr_keyboard_group_destroy(group->wlr_group); + wl_event_source_remove(group->key_repeat_timer); + free(group); + break; + } + --devn; + } + } else if(strncmp(line, "p", 1) == 0) { + if(wl_list_empty(&server->seat->pointers)) { + return; + } + devn = devn % wl_list_length(&server->seat->pointers); + struct cg_pointer *pointer, *pointer_tmp; + wl_list_for_each_safe(pointer, pointer_tmp, &server->seat->pointers, + link) { + if(devn == 0) { + pointer->destroy.notify(&pointer->destroy, NULL); + break; + } + --devn; + } + } else if(strncmp(line, "t", 1) == 0) { + if(wl_list_empty(&server->seat->touch)) { + return; + } + devn = devn % wl_list_length(&server->seat->touch); + struct cg_touch *touch, *touch_tmp; + wl_list_for_each_safe(touch, touch_tmp, &server->seat->touch, + link) { + if(devn == 0) { + touch->destroy.notify(&touch->destroy, NULL); + break; + } + --devn; + } + } + } +} + +void +destroy_output(char *line, struct cg_server *server) { + if(wl_list_length(&server->outputs) < 2) { + return; + } + char *outpnstr = strtok_r(NULL, ";", &line); + long outpn = 0; + if(outpnstr != NULL) { + outpn = strtol(outpnstr, NULL, 10); + } + outpn = outpn % wl_list_length(&server->outputs); + struct cg_output *it; + wl_list_for_each(it, &server->outputs, link) { + if(outpn == 0) { + break; + } else { + --outpn; + } + } + it->damage_destroy.notify(&it->damage_destroy, NULL); +} diff --git a/fuzz/fuzz-lib.h b/fuzz/fuzz-lib.h new file mode 100644 index 0000000..0ea499b --- /dev/null +++ b/fuzz/fuzz-lib.h @@ -0,0 +1,49 @@ +/* + * Cagebreak: A Wayland tiling compositor. + * + * Copyright (C) 2018-2020 Jente Hidskes + * + * See the LICENSE file accompanying this file. + */ + +#ifndef CG_FUZZ_LIB_H +#define CG_FUZZ_LIB_H + +#define _POSIX_C_SOURCE 200812L + +#include "../server.h" + +#ifndef WAIT_ANY +#define WAIT_ANY -1 +#endif + +struct cg_server server; +struct wlr_xdg_shell *xdg_shell; + +struct wlr_xwayland *xwayland; +#if CG_HAS_XWAYLAND +struct wlr_xcursor_manager *xcursor_manager; +#endif + +void +cleanup(); + +int +LLVMFuzzerInitialize(int *argc, char ***argv); + +void +move_cursor(char *line, struct cg_server *server); + +void +create_output(char *line, struct cg_server *server); + +void +create_input_device(char *line, struct cg_server *server); + +void +destroy_input_device(char *line, struct cg_server *server); + +void +destroy_output(char *line, struct cg_server *server); + +#endif diff --git a/fuzz/fuzz-parse.c b/fuzz/fuzz-parse.c index 45e74da..8aded78 100644 --- a/fuzz/fuzz-parse.c +++ b/fuzz/fuzz-parse.c @@ -8,48 +8,14 @@ #define _POSIX_C_SOURCE 200812L -#include "../keybinding.h" -#include "../output.h" -#include "../parse.h" -#include "../seat.h" -#include "../server.h" -#include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if CG_HAS_XWAYLAND -#include -#endif -#include -#include +#include #include #include -#if CG_HAS_XWAYLAND -#include -#endif -#include "../idle_inhibit_v1.h" #include "../keybinding.h" #include "../message.h" #include "../output.h" @@ -58,347 +24,13 @@ #include "../server.h" #include "../view.h" #include "../workspace.h" -#include "../xdg_shell.h" +#include "config.h" #if CG_HAS_XWAYLAND #include "../xwayland.h" #endif -#ifndef WAIT_ANY -#define WAIT_ANY -1 -#endif +#include "fuzz-lib.h" -static bool -drop_permissions(void) { - if(getuid() != geteuid() || getgid() != getegid()) { - if(setuid(getuid()) != 0 || setgid(getgid()) != 0) { - wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); - return false; - } - } - - if(setuid(0) != -1) { - wlr_log(WLR_ERROR, "Unable to drop root (we shouldn't be able to " - "restore it after setuid), refusing to start"); - return false; - } - - return true; -} - -static bool -parse_args(struct cg_server *server, int argc, char *argv[]) { - server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; -#ifdef DEBUG - server->debug_damage_tracking = false; -#endif - return true; -} - -struct cg_server server = {0}; -struct wlr_xwayland *xwayland = NULL; -#if CG_HAS_XWAYLAND -struct wlr_xcursor_manager *xcursor_manager = NULL; -#endif - -void -cleanup() { - server.running = false; -#if CG_HAS_XWAYLAND - if(xwayland != NULL) { - wlr_xwayland_destroy(xwayland); - } - if(xcursor_manager != NULL) { - wlr_xcursor_manager_destroy(xcursor_manager); - } -#endif - wl_display_destroy_clients(server.wl_display); - - for(unsigned int i = 0; server.modes[i] != NULL; ++i) { - free(server.modes[i]); - } - free(server.modes); - - keybinding_list_free(server.keybindings); - - seat_destroy(server.seat); - /* This function is not null-safe, but we only ever get here - with a proper wl_display. */ - wl_display_destroy(server.wl_display); - wlr_output_layout_destroy(server.output_layout); -} - -int -LLVMFuzzerInitialize(int *argc, char ***argv) { - struct wl_event_loop *event_loop = NULL; - struct wlr_backend *backend = NULL; - struct wlr_renderer *renderer = NULL; - struct wlr_compositor *compositor = NULL; - struct wlr_data_device_manager *data_device_manager = NULL; - struct wlr_server_decoration_manager *server_decoration_manager = NULL; - struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL; - struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL; - struct wlr_screencopy_manager_v1 *screencopy_manager = 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; - int ret = 0; - - if(!parse_args(&server, *argc, *argv)) { - return 1; - } - -#ifdef DEBUG - wlr_log_init(WLR_DEBUG, NULL); -#else - wlr_log_init(WLR_ERROR, NULL); -#endif - - /* Wayland requires XDG_RUNTIME_DIR to be set. */ - if(!getenv("XDG_RUNTIME_DIR")) { - wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment"); - return 1; - } - - server.wl_display = wl_display_create(); - if(!server.wl_display) { - wlr_log(WLR_ERROR, "Cannot allocate a Wayland display"); - return 1; - } - - server.running = true; - - server.modes = malloc(4 * sizeof(char *)); - server.modes[0] = strdup("top"); - server.modes[1] = strdup("root"); - server.modes[2] = strdup("resize"); - server.modes[3] = NULL; - - server.nws = 1; - server.message_timeout = 2; - - event_loop = wl_display_get_event_loop(server.wl_display); - server.event_loop = event_loop; - - backend = wlr_backend_autocreate(server.wl_display, NULL); - if(!backend) { - wlr_log(WLR_ERROR, "Unable to create the wlroots backend"); - ret = 1; - goto end; - } - server.backend = backend; - - if(!drop_permissions()) { - ret = 1; - goto end; - } - - server.keybindings = keybinding_list_init(); - if(server.keybindings == NULL || server.keybindings->keybindings == NULL) { - wlr_log(WLR_ERROR, "Unable to allocate keybindings"); - ret = 1; - goto end; - } - - wl_list_init(&server.output_config); - - renderer = wlr_backend_get_renderer(backend); - wlr_renderer_init_wl_display(renderer, server.wl_display); - - server.bg_color = malloc(4 * sizeof(float)); - server.bg_color[0] = 0; - server.bg_color[1] = 0; - server.bg_color[2] = 0; - server.bg_color[3] = 1; - wl_list_init(&server.outputs); - - server.output_layout = wlr_output_layout_create(); - if(!server.output_layout) { - wlr_log(WLR_ERROR, "Unable to create output layout"); - ret = 1; - goto end; - } - - compositor = wlr_compositor_create(server.wl_display, renderer); - if(!compositor) { - wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); - ret = 1; - goto end; - } - - data_device_manager = wlr_data_device_manager_create(server.wl_display); - if(!data_device_manager) { - wlr_log(WLR_ERROR, "Unable to create the data device manager"); - ret = 1; - goto end; - } - - /* Configure a listener to be notified when new outputs are - * available on the backend. We use this only to detect the - * first output and ignore subsequent outputs. */ - server.new_output.notify = handle_new_output; - wl_signal_add(&backend->events.new_output, &server.new_output); - - server.seat = seat_create(&server, backend); - if(!server.seat) { - wlr_log(WLR_ERROR, "Unable to create the seat"); - ret = 1; - goto end; - } - - server.idle = wlr_idle_create(server.wl_display); - if(!server.idle) { - wlr_log(WLR_ERROR, "Unable to create the idle tracker"); - ret = 1; - goto end; - } - - server.idle_inhibit_v1 = wlr_idle_inhibit_v1_create(server.wl_display); - if(!server.idle_inhibit_v1) { - wlr_log(WLR_ERROR, "Cannot create the idle inhibitor"); - ret = 1; - goto end; - } - server.new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1_new; - wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, - &server.new_idle_inhibitor_v1); - wl_list_init(&server.inhibitors); - - xdg_shell = wlr_xdg_shell_create(server.wl_display); - 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); - - xdg_decoration_manager = - wlr_xdg_decoration_manager_v1_create(server.wl_display); - if(!xdg_decoration_manager) { - wlr_log(WLR_ERROR, "Unable to create the XDG decoration manager"); - ret = 1; - goto end; - } - wl_signal_add(&xdg_decoration_manager->events.new_toplevel_decoration, - &server.xdg_toplevel_decoration); - server.xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; - - server_decoration_manager = - wlr_server_decoration_manager_create(server.wl_display); - if(!server_decoration_manager) { - wlr_log(WLR_ERROR, "Unable to create the server decoration manager"); - ret = 1; - goto end; - } - wlr_server_decoration_manager_set_default_mode( - server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - - export_dmabuf_manager = - wlr_export_dmabuf_manager_v1_create(server.wl_display); - if(!export_dmabuf_manager) { - wlr_log(WLR_ERROR, "Unable to create the export DMABUF manager"); - ret = 1; - goto end; - } - - screencopy_manager = wlr_screencopy_manager_v1_create(server.wl_display); - if(!screencopy_manager) { - wlr_log(WLR_ERROR, "Unable to create the screencopy manager"); - ret = 1; - goto end; - } - - output_manager = wlr_xdg_output_manager_v1_create(server.wl_display, - server.output_layout); - if(!output_manager) { - wlr_log(WLR_ERROR, "Unable to create the output manager"); - ret = 1; - goto end; - } - - gamma_control_manager = - wlr_gamma_control_manager_v1_create(server.wl_display); - if(!gamma_control_manager) { - wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); - ret = 1; - goto end; - } - -#if CG_HAS_XWAYLAND - xwayland = wlr_xwayland_create(server.wl_display, compositor, true); - if(!xwayland) { - wlr_log(WLR_ERROR, "Cannot create XWayland server"); - ret = 1; - goto end; - } - server.new_xwayland_surface.notify = handle_xwayland_surface_new; - wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface); - - xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE); - if(!xcursor_manager) { - wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager"); - ret = 1; - goto end; - } - - if(setenv("DISPLAY", xwayland->display_name, true) < 0) { - 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", - xwayland->display_name); - } - - if(wlr_xcursor_manager_load(xcursor_manager, 1)) { - wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme"); - } - struct wlr_xcursor *xcursor = - wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1); - if(xcursor) { - struct wlr_xcursor_image *image = xcursor->images[0]; - wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4, - image->width, image->height, image->hotspot_x, - image->hotspot_y); - } -#endif - - const char *socket = wl_display_add_socket_auto(server.wl_display); - if(!socket) { - wlr_log_errno(WLR_ERROR, "Unable to open Wayland socket"); - ret = 1; - goto end; - } - - if(!wlr_backend_start(backend)) { - wlr_log(WLR_ERROR, "Unable to start the wlroots backend"); - ret = 1; - goto end; - } - - if(setenv("WAYLAND_DISPLAY", socket, true) < 0) { - wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.", - "Clients may not be able to connect"); - } else { - wlr_log(WLR_DEBUG, - "Cagebreak " CG_VERSION " is running on Wayland display %s", - socket); - } - -#if CG_HAS_XWAYLAND - wlr_xwayland_set_seat(xwayland, server.seat->seat); -#endif - - /* Place the cursor to the topl left of the output layout. */ - wlr_cursor_warp(server.seat->cursor, NULL, 0, 0); - atexit(cleanup); - return 0; -end: - cleanup(); - return ret; -} - -/* Parse config file. Lines longer than "max_line_size" are ignored */ int set_configuration(struct cg_server *server, char *content) { char *line; @@ -407,6 +39,7 @@ set_configuration(struct cg_server *server, char *content) { line[strcspn(line, "\n")] = '\0'; if(*line != '\0' && *line != '#') { char *errstr; + server->running = true; if(parse_rc_line(server, line, &errstr) != 0) { if(errstr != NULL) { free(errstr); @@ -435,21 +68,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { (union keybinding_params){.i = 1}); run_action(KEYBINDING_LAYOUT_FULLSCREEN, &server, (union keybinding_params){.c = NULL}); - wl_display_flush_clients(server.wl_display); - wl_display_destroy_clients(server.wl_display); struct cg_output *output; - wl_list_for_each(output, &server.outputs, link) { - message_clear(output); - struct cg_view *view; - wl_list_for_each(view, &(*output->workspaces)->views, link) { - view_unmap(view); - view_destroy(view); - } - wl_list_for_each(view, &(*output->workspaces)->unmanaged_views, link) { - view_unmap(view); - view_destroy(view); - } - } + wl_list_for_each(output, &server.outputs, link) { message_clear(output); } for(unsigned int i = 3; server.modes[i] != NULL; ++i) { free(server.modes[i]); } @@ -463,6 +83,5 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { free(output_config->output_name); free(output_config); } - return 0; } diff --git a/fuzz/meson.build b/fuzz/meson.build index 8ff982a..b5ba1be 100644 --- a/fuzz/meson.build +++ b/fuzz/meson.build @@ -1,9 +1,11 @@ fuzz_sources = [ 'fuzz-parse.c', + 'fuzz-lib.c', ] fuzz_headers = [ '../parse.h', + 'fuzz-lib.h', ] inc = include_directories(['..','../build/']) diff --git a/keys/cagebreak@project-repo.co.pub b/keys/cagebreak@project-repo.co.pub new file mode 100644 index 0000000..2642c1e --- /dev/null +++ b/keys/cagebreak@project-repo.co.pub @@ -0,0 +1,75 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBF7Te/sBEADhW2ZdermfH8qbOrClJFiH33yrygi/GjcaQ+T+3co6GGpIGne7 +m5+7h2qTBaGkolAv+qIPm7XlWg6spbPynxG3GLqX5/gpvp23yCw9zm56mNXkVxAK +4YiKUVbO7Nq927U3iTM/+wbgeo4wq0gyY9E4wgYo7vjiCPnfpA1WK7KBSr3VwvJc +NxIwmSEkL7UOOsw0t0y01fdiEekHcopISpty70ZzMs0XFx9G5USe4O8W71E7isKx +s7XiG17HDCG46vumuRoBOC1NuWmag3VD7T0XFQtjXyqSObqRKwA3r7S2buakK3tp +FwqxQETTplx+Xo7Z/bO5TfoR0W0rTOaZXigtGVJ1k7nQrq45fqEJVV4vWOHA+Q4a +8CQJsZPWjFj3QujJvp2+l1M0C+h73GEAvw7pvPytAeqzoPgRDjm6SUVVkvG7jNMR +iqjqS6QyuwfK0e88un6Z8/MsYVHvt+dOMnvRKND57BL2ufWMIow1QdOR249/38FA +FP3oXldUJIKKi8emC/JZKqGomZFZtWZCYJtzBqWhnEtr3G9X8VfNdMkOaPRNNRkz +125i2kgzziXgII0rVatTPM+n3LPd9A8VSwXQPHUfd8aVv7uO7v/4LNXYqyjg+rUL +AJCS5dIYhDgHhBSHOxuZ379ZDPSVNBSoy5L1geHpO2lCLNnaCsWwSOkNkQARAQAB +tCVDYWdlYnJlYWsgPGNhZ2VicmVha0Bwcm9qZWN0LXJlcG8uY28+iQJUBBMBCAA+ +FiEEsVuSZCdg4R/gAt4WhwjUJFGpSrUFAl7Te/sCGwMFCQHhM4AFCwkIBwIGFQoJ +CAsCBBYCAwECHgECF4AACgkQhwjUJFGpSrUPERAAvr4fuZqXrM2FOEI1h0n1lUA4 +DpRwdK92VmqhJA1zQ375pXnmorSSWK1RZbxjqGS/PzBldTA/GCRsA+omsD4EC45L +nIabt2dKLmC8CZi8wI1R0nUng6ABs/o97euZ4Srgryi5hc2ViMDxXnJecTS1baoj +ajot9oOZlB0MSF0LIxGaaE8rcq8C26Q/6ibbD9KszS2Khzpsood2Oukx4rN/0VMC +UiN9UsjMH2EcXLzVBKTTDhcCWxJw/z00YS7iQzLrSZer0/+b8UqOy8tC7TRdjoUm +fzr84Ims6HG4GEeb1/OlHPELI8D5BKRAQCVDhOARzW47zrxKQbWfUONq7XaaxZVk +qvwhMXjoQ9SC8NhukCNJqkDZsIdi3e0hQ5HoJbUnS5aTnQnKfhdoYtmW+NB1XPIS +ZvPl0Fj5r5LfDWCalyo8riT8tuMWPy0kkbauYSA1gG6Hv5h8A/+3VD6YSws1e5is +UcY6joPZ0zzjn4RCCdpEmEIbPO8Wa8GsOn+0u+blA9D+mr8kCYBP5Xxtzn8y8uM3 +hVzpxYC872aTtHpq/VNFoQnVK7aKdPpQDak3l8iPrDcMsZwX3SVTI5lsFbxPfiYn +HEkcY0GhNE1hm8CMIrQSF0CiUhCGKTzb6BJXjr9T0GUI9LVPu5rGQSiDDYjrgY/4 +VIwguPJieWDlZMlroliJAjMEEAEIAB0WIQTnn22eETUp9LH/5NXE+XTXDOwsWwUC +XtOAmwAKCRDE+XTXDOwsWxGXD/98QVtd84G8ZOz/I+LE7Lvsz6XxAUJqInuYkQzq +8MGV/U3kVvsr8TF/ACGaktSr7ys/MRN83CYNsjLysJskm2x8uBbEZLgmamR2DoKj +vJH4ZDaMsepoE0qrFl5Sys6XvtG1BkpifCZrsnLtUoSFo9hdnfhkeAYwQdjSTk+Z +Nv4s4hlW4bqHcnV4E7Sy6sgDpyMYVWWuI104vRP7dcjIzv0dWOIc3PRGunB3fNuv +R649RVjCWnAsBAlM5KfhvEYjgA+0+NDayYiOxwKpdHV58BsWu6PXL4vpzOHjwNF1 +lWX3a6J8XSy8EgRP4pN+bGvOfjuMVm1PzHvf4Ij8uIE2piR1n3/BAQLuLSaU82mK +729pR+tuRRndv937rZ5LcfwSeevfzMBlYtef/xPX/H872Pwk9BCjs2ppIDRZWqml +iBde3oQjZl09UIx2GvKFJt5pkhZyP8ybV4qipDcJtHaKxMQ3BzbP6qnSTJbAbwPh +/qV4ysy/10dibxPk77DK7Flmnf5Hqdnf+uiKD1sappe4wuhdZqqPKneh2vCmbVlr +HkrnUpV6YlVHXyZCJw/0B2vBZGHAhgQElg3wvJUFftTTop646MR8NDITnYadyrNF +4DtABCfSMfHFVUyRr4Or/0SBxa0uKftgNy7n4/nFBQ1PicYKr+x25pTqGSbbLXAS +UO1NT4kCMwQQAQgAHRYhBHU1q4kiClwVpyi3X3QQTMfcpdeoBQJe04DRAAoJEHQQ +TMfcpdeoswQP/0BaaeCVFlaCPHTHJnb1I77R2nX8Y4ma/cxLTpKPcbk+yQ2211AL +rC3F6F4ta59l4opQzBBNKpl948Ts3QrOhj0TcIzpULkjipmhXk/kq9dTLudi6q23 +jZC5qaIYmzCI1+a0RL4bPo15/JjKEbWt6N/HoUL/rHfCa0b4mcfkC0iwOBWlUDl9 +tWv1VcEHgZOhtTnkpHnsp41QitTEN2Sr3CSef9/mmmWbwqPVNOjNh9/G/ci41ce1 +p4mz0/f471z5tNIRhOWDkbVo0XDVBvP1y7A47+8L/Ea4ep1f3/i9QwGyBt0Izaon +s8GMRWXI9KSN7SudjBXF8wonxIiIDF7u2PHzhbmdAfZTssr1jbwn7AVlxhDFSR8z +f4FlX7Mn6YAG94h6HN3qRo/c+E47XBqj9XmvFe0e+bWg9oar3rWGkVN+YzUaSgp3 +iNXRYQfQZbCHf7vTDzQZ8lWix7IBcAdoBgHl7d0RW4VNqbXISZvKMMTZK8WQVYYz +wcW9+Ll/fEwE8PGs5FolnynEg9YLLzj0OADSfaly/woqXUul14mWpM/gFsxQTyuQ +7n7xyAu5PImTjC7WzVMF9OAH35ng9u76bDkmwVfrMzGvKZ2DRsJQeNRUAd4EIM8S +6+ipTKNASzj4mCnURgS2zMplReE30icE8Vpol/ZYgC2qouS89nq29kLOuQINBF7T +e/sBEADSdSZVGEumZeeXzM1uPp1OUWHCkmCiPu6jfP2M2GI4VnSCcsxM4XcbR26O +sqMmMo9f4Fuie/+K6oyqE1LMeGTpasWJrd8w2TME0V5Nqsszp+PtKJBTIskk2c7b +ctQDeZDTcuIGPi03SxLCn+ZeDpVscBKbuc78twNYl0xXM86P67D73cA5WZPqQIKS +Me+8iRzpzB/Hk/lcDun3QlrXq+bMwSPSMD0ikcPdpiGf+RuQH/ZB5JVQqgA92Vt3 +QFA4RAgKyQCdS0DOaScAvXotriFWbZdGt/iTGzzQ8e1O0C9COhgNms4r5bwRVzH5 +k/kQ1BC1S+Me5shNUO8DabRWPh+CgZjtYV5oHY1jik1p72DnTTajIMYwhcLOJXRl +l+zlq20qqqdp05DSloIYEizsgNTQ0F7XP0uXyVaDsUxGv4ZucRHJVuedilEhz9MW +k/iqeQ2hWRuR3vuiknj3F8O/Z7kJNfx8Hi6PgfCMyCv3YZxpkXhXwXRbYndhbQHK +F/9gVvDxx0yw+BCYj+iDdo0mwdI0LFh+ddpwWBFhzJpMdUsDEHmG5yOmbUIZDCmt +GCLSBDPl61FUaGUljSFWtW7b3bgv+a6RUTbkw3ZuvyxV9lMbLDAPSZmRjQHGydZJ +cdRmxX262CjpxP707c51EhlhsL5Q1cBXcBgwlbQ3ltC4VFRI1wARAQABiQI8BBgB +CAAmFiEEsVuSZCdg4R/gAt4WhwjUJFGpSrUFAl7Te/sCGwwFCQHhM4AACgkQhwjU +JFGpSrWLGQ//f07ynATQpyyichXwMQDZhOS2/jocTNHaUfecO2OoPjc69wldyvN6 +wv0HDUmom1rJK/v25KxGnKKKg/UX9XxCSK2G85UX4niT/jTKcI5D9OiOwlFbs917 +VYYU/8u45KDDqDLqhhepAa5QttKXMDU2nx9V82W/gVjEcLIseKeIg4i24bJHi6ax +WySklo1Vwo+RGtwfhT+/UxLv9bDOWRxHRsOnlTZo+PSMgescgWDkYOR33wxmLw6P +Ckv/Sb/kIXrXuFey7bs3zciM1hL4+/iIAr2DSQi5bGUBnBCrwsV4wnVru06Ua013 +sPqHTMgucbhYDS4sTPOXD7szQAzze1dxez55h5ziaf7tFilvaulSs2bubGuAWgKm +VCeZINzEbA4bYUAyuWtMu+vbXWimcg54BGVCS7IdVGF78FjgVTqjH8nkiGtrzGRW +94ebx61EcuNdcRuri3OgrO009fzJy8sswQmuanyF4gyXml9FUVc93HO8mDnNyFZd +O5FHgYFLn+ymd2Ra5cUvFYsJ5b2ydkX7CigcqyyysMoYpc1PpJN1kpX0e1D6JDp9 +Xk02SoUP9t/y6C/h7f14WUefgZnDwK2/YCYogyrgMSSLw54j85kS/Ycr2OlJ3If5 +MHObamGEWsqr6H240IxeT4xrsMUuSFYHEEGnKuPfiSPVF2QjVbOTeSw= +=QlUC +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_1.asc b/keys/cagebreak_signing_key_1.asc deleted file mode 100644 index 835d485..0000000 --- a/keys/cagebreak_signing_key_1.asc +++ /dev/null @@ -1,65 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -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 -Rw== -=IZJF ------END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_1@cagebreak.pub b/keys/cagebreak_signing_key_1@cagebreak.pub new file mode 100644 index 0000000..b6ff569 --- /dev/null +++ b/keys/cagebreak_signing_key_1@cagebreak.pub @@ -0,0 +1,88 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=Z3hL +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_2.asc b/keys/cagebreak_signing_key_2@cagebreak.pub similarity index 100% rename from keys/cagebreak_signing_key_2.asc rename to keys/cagebreak_signing_key_2@cagebreak.pub diff --git a/keys/cagebreak_signing_key_3@project-repo.co.pub b/keys/cagebreak_signing_key_3@project-repo.co.pub new file mode 100644 index 0000000..855c32f --- /dev/null +++ b/keys/cagebreak_signing_key_3@project-repo.co.pub @@ -0,0 +1,76 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +vOQMlRsEbbSw+T2OA2gGXUPK7yzF +=kqmE +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_4@project-repo.co.pub b/keys/cagebreak_signing_key_4@project-repo.co.pub new file mode 100644 index 0000000..50b92c4 --- /dev/null +++ b/keys/cagebreak_signing_key_4@project-repo.co.pub @@ -0,0 +1,64 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +/qf52E0= +=zGAB +-----END PGP PUBLIC KEY BLOCK----- diff --git a/man/cagebreak-config.5.md b/man/cagebreak-config.5.md index 96aff5f..4e8f542 100644 --- a/man/cagebreak-config.5.md +++ b/man/cagebreak-config.5.md @@ -1,4 +1,4 @@ -% CAGEBREAK-CONFIG(1) Version 1.3.0 | Cagebreak Manual +% CAGEBREAK-CONFIG(1) Version 1.3.1 | Cagebreak Manual # NAME diff --git a/man/cagebreak.1.md b/man/cagebreak.1.md index c72323f..6777cd7 100644 --- a/man/cagebreak.1.md +++ b/man/cagebreak.1.md @@ -1,4 +1,4 @@ -% CAGEBREAK(1) Version 1.3.0 | Cagebreak Manual +% CAGEBREAK(1) Version 1.3.1 | Cagebreak Manual # NAME diff --git a/meson.build b/meson.build index 2a2d0ba..c6676ea 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('cagebreak', 'c', - version: '1.3.0', + version: '1.3.1', license: 'MIT', default_options: [ 'c_std=c11', @@ -224,9 +224,7 @@ reproducible_build_compiler_version = '10.1.0' if cc.get_id() != reproducible_build_compiler warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in the README section "Reproducible Builds" (' + reproducible_build_compiler + ').') -endif - -if cc.version() != reproducible_build_compiler_version +elif cc.version() != reproducible_build_compiler_version warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" ' + reproducible_build_compiler_version + '.') endif diff --git a/render.c b/render.c index 43da1da..e1ca1c1 100644 --- a/render.c +++ b/render.c @@ -51,6 +51,7 @@ scissor_output(struct wlr_output *output, pixman_box32_t *rect) { struct render_data { pixman_region32_t *damage; + int tile_width, tile_height; }; static void @@ -101,6 +102,14 @@ render_surface_iterator(struct cg_output *output, struct wlr_surface *surface, wlr_matrix_project_box(matrix, box, transform, 0.0F, wlr_output->transform_matrix); + if(data->tile_width != 0) { + box->width = + box->width > data->tile_width ? data->tile_width : box->width; + } + if(data->tile_height != 0) { + box->height = + box->height > data->tile_height ? data->tile_height : box->height; + } render_texture(wlr_output, output_damage, texture, box, matrix); } @@ -109,6 +118,8 @@ render_drag_icons(struct cg_output *output, pixman_region32_t *damage, struct wl_list *drag_icons) { struct render_data data = { .damage = damage, + .tile_width = 0, + .tile_height = 0, }; output_drag_icons_for_each_surface(output, drag_icons, render_surface_iterator, &data); @@ -122,7 +133,19 @@ render_view_toplevels(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage) { struct render_data data = { .damage = damage, + .tile_width = 0, + .tile_height = 0, }; + // TODO: improve run time behaviour of view_get_tile + struct cg_tile *view_tile = view_get_tile(view); + if(view_tile != NULL) { + if(view_tile->tile.width != view->wlr_surface->current.width || + view_tile->tile.height != view->wlr_surface->current.height) { + view_damage_whole(view); + } + data.tile_width = view_tile->tile.width; + data.tile_height = view_tile->tile.height; + } double ox, oy; ox = view->ox; @@ -147,6 +170,8 @@ render_view_popups(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage) { struct render_data data = { .damage = damage, + .tile_width = 0, + .tile_height = 0, }; output_view_for_each_popup(output, view, render_popup_iterator, &data); } diff --git a/signatures/1.3.0.sig b/signatures/1.3.0.sig new file mode 100644 index 0000000000000000000000000000000000000000..3c5c35930506e97301e9cae291cc396d25a231cf GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j-ZpKYEIH7WG5|K!!g`E=I|>?~Ua0$$89-2e&+5XAX( z*9`0|TaZ-`|8B19v8nWt+`yQRe_>?zV9R$KNOZ;Ao6nXhbU1&)=v=`5F>DZu{#kbT z6{L}V-K$1hB}cOf3-I#7y8ey(rb(#xaKdnFJwit<~c5^ zy(6d3S7kaKru_arzzNe&FI^df3y^)W4(q7)ut|E4Yd@8gL#=G+%RJ4oYzqQo!Ca*| zYTG657GHJfgsvX1G-WMAdsBmmg5k{0syR#>)?ww$#5RZ1FXzP>NFzzhY!;7zpW1cH zDm(B;8$w2{r%`p^6~{ov5bGl#QYIU^Czo_T=Lv{28SD&bSUw`cD<{9<47AbN4&Bp$ zOMgn_N+2(SmX9}qeQEW8mHy2_5;89c&MZH`z=+Ur5kQk8G3q40f5Ks$Qz_s{x?ikf z8*{BZGRradK@((T({PDy_ROCp)ruC!{oqhVTpQ`xX|kCjE3+XlgG=J~)v{FNR}4FC zt12}>Gi^x`e%zrAdC=4$!aNrj0HVVw&dO13pbKTvHRI^88+Vvtd@{6I5z#EMncg+c zG^gK2^REW3ovSE;Qc01T(ybNn=b(_NwQn1X$z}>-Zi;OjKXZLyfD60pAnR?4bH@OG EH)i?|)&Kwi literal 0 HcmV?d00001 diff --git a/signatures/cagebreak.sig b/signatures/cagebreak.sig index 3c5c35930506e97301e9cae291cc396d25a231cf..288094e0abe6c0c0c5f8f02f02e4b23453297d07 100644 GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j+6HLHmt3S1SZD7Rm95KPD1rPrth0$$h31po>O5Ofes z$K0jYsDzyl|7~X-L$LyQ?Cxv9MrwnDpN7!^p^iuQrsJ(88|V@D3~kLFc}6NeoA9e6 zXW#~a-j?!2tQX)>{Bqlf&!xMiXccM**s^axv7>-p%vdrlDOltSYBe1h5A@GSV#Zj9 zU7X|i|6c0ILEZsxlD@<|GOJfbV!~O^_AF1NJLz(Lj`O?&UNX9_&ZnC_Q3`f{XdT|G zkE*6#Py>LNs1v5|t2w>cIei|%8aP2j4v_-?#=R;LLTA99%}3&U;2{v! zS}{(`TdKe;h!3pno3keDIz@I;NPbSnVVKEPUXVA22pc=(`1kic*<=oR7h+9=1Qam( z(^f(rCukN0@FWpA(2Dg<;usl{;=qMIi=g}Vrz>|XBlUd}&dQ>JUQ>Jis|Y{%Sdp43 EWwj;=*Z=?k literal 566 zcmV-60?GY}0y6{v0SEvc79j-ZpKYEIH7WG5|K!!g`E=I|>?~Ua0$$89-2e&+5XAX( z*9`0|TaZ-`|8B19v8nWt+`yQRe_>?zV9R$KNOZ;Ao6nXhbU1&)=v=`5F>DZu{#kbT z6{L}V-K$1hB}cOf3-I#7y8ey(rb(#xaKdnFJwit<~c5^ zy(6d3S7kaKru_arzzNe&FI^df3y^)W4(q7)ut|E4Yd@8gL#=G+%RJ4oYzqQo!Ca*| zYTG657GHJfgsvX1G-WMAdsBmmg5k{0syR#>)?ww$#5RZ1FXzP>NFzzhY!;7zpW1cH zDm(B;8$w2{r%`p^6~{ov5bGl#QYIU^Czo_T=Lv{28SD&bSUw`cD<{9<47AbN4&Bp$ zOMgn_N+2(SmX9}qeQEW8mHy2_5;89c&MZH`z=+Ur5kQk8G3q40f5Ks$Qz_s{x?ikf z8*{BZGRradK@((T({PDy_ROCp)ruC!{oqhVTpQ`xX|kCjE3+XlgG=J~)v{FNR}4FC zt12}>Gi^x`e%zrAdC=4$!aNrj0HVVw&dO13pbKTvHRI^88+Vvtd@{6I5z#EMncg+c zG^gK2^REW3ovSE;Qc01T(ybNn=b(_NwQn1X$z}>-Zi;OjKXZLyfD60pAnR?4bH@OG EH)i?|)&Kwi diff --git a/view.c b/view.c index 609b01e..142ac36 100644 --- a/view.c +++ b/view.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -44,10 +45,15 @@ view_get_prev_view(struct cg_view *view) { return prev; } +void +view_damage_child(struct cg_view_child *child, int x, int y, bool whole); + static void view_child_handle_commit(struct wl_listener *listener, void *_data) { struct cg_view_child *child = wl_container_of(listener, child, commit); - view_damage_part(child->view); + int x, y; + child->get_coords(child, &x, &y); + view_damage_child(child, child->view->ox + x, child->view->oy + y, false); } static void @@ -67,7 +73,9 @@ view_child_finish(struct cg_view_child *child) { return; } - view_damage_whole(child->view); + int x, y; + child->get_coords(child, &x, &y); + view_damage_child(child, child->view->ox + x, child->view->oy + y, true); wl_list_remove(&child->link); wl_list_remove(&child->commit.link); @@ -108,6 +116,27 @@ subsurface_handle_destroy(struct wl_listener *listener, void *_data) { subsurface_destroy(view_child); } +static void +subsurface_get_coords(struct cg_view_child *child, int *x, int *y) { + + struct wlr_surface *surface = child->wlr_surface; + *x = 0; + *y = 0; + + if(!(child->view && child->view->impl)) { + while(surface && wlr_surface_is_subsurface(surface)) { + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + if(subsurface == NULL) { + break; + } + *x += subsurface->current.x; + *y += subsurface->current.y; + surface = subsurface->parent; + } + } +} + static void subsurface_create(struct cg_view *view, struct wlr_subsurface *wlr_subsurface) { struct cg_subsurface *subsurface = calloc(1, sizeof(struct cg_subsurface)); @@ -117,6 +146,7 @@ subsurface_create(struct cg_view *view, struct wlr_subsurface *wlr_subsurface) { view_child_init(&subsurface->view_child, view, wlr_subsurface->surface); subsurface->view_child.destroy = subsurface_destroy; + subsurface->view_child.get_coords = subsurface_get_coords; subsurface->wlr_subsurface = wlr_subsurface; subsurface->destroy.notify = subsurface_handle_destroy; @@ -170,10 +200,22 @@ view_is_visible(const struct cg_view *view) { void view_damage(struct cg_view *view, bool whole) { + struct cg_tile *view_tile = view_get_tile(view); + if(view_tile != NULL && + (view->wlr_surface->current.width != view_tile->tile.width || + view->wlr_surface->current.height != view_tile->tile.height)) { + view_maximize(view, &view_tile->tile); + } output_damage_surface(view->workspace->output, view->wlr_surface, view->ox, view->oy, whole); } +void +view_damage_child(struct cg_view_child *child, int x, int y, bool whole) { + output_damage_surface(child->view->workspace->output, child->wlr_surface, x, + y, whole); +} + void view_damage_part(struct cg_view *view) { view_damage(view, false); diff --git a/view.h b/view.h index 150e79b..8b405da 100644 --- a/view.h +++ b/view.h @@ -59,6 +59,7 @@ struct cg_view_child { struct wl_listener new_subsurface; void (*destroy)(struct cg_view_child *child); + void (*get_coords)(struct cg_view_child *child, int *x, int *y); }; struct cg_subsurface { diff --git a/xdg_shell.c b/xdg_shell.c index fd9ef3d..59b3334 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -7,6 +7,8 @@ * See the LICENSE file accompanying this file. */ +#define _POSIX_C_SOURCE 200809L + #include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include #include #include "output.h" @@ -117,6 +120,22 @@ popup_unconstrain(struct cg_xdg_popup *popup) { wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box); } +static void +xdg_popup_get_coords(struct cg_view_child *child, int *x, int *y) { + if(!child) { + return; + } + struct cg_xdg_popup *popup = (struct cg_xdg_popup *)child; + struct wlr_xdg_surface *surface = popup->wlr_popup->base; + + int x_offset = -surface->geometry.x; + int y_offset = -surface->geometry.y; + + wlr_xdg_popup_get_toplevel_coords( + surface->popup, x_offset + surface->popup->geometry.x, + y_offset + surface->popup->geometry.y, x, y); +} + static void xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup) { struct cg_xdg_popup *popup = calloc(1, sizeof(struct cg_xdg_popup)); @@ -125,6 +144,7 @@ xdg_popup_create(struct cg_view *view, struct wlr_xdg_popup *wlr_popup) { } popup->wlr_popup = wlr_popup; + popup->view_child.get_coords = xdg_popup_get_coords; view_child_init(&popup->view_child, view, wlr_popup->base->surface); popup->view_child.destroy = xdg_popup_destroy; popup->destroy.notify = handle_xdg_popup_destroy; @@ -195,7 +215,9 @@ 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, width, height); - wlr_xdg_toplevel_set_maximized(xdg_shell_view->xdg_surface, true); + 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, edges); } static void