diff --git a/Bugs.md b/Bugs.md index 4075383..970edf4 100644 --- a/Bugs.md +++ b/Bugs.md @@ -1187,3 +1187,137 @@ being copied to the `status` element of the resultant structure. The script introduced with 2.1.1 `scripts/install-development-environment` had some missing dependencies. This has been resolved and tested with bare arch containers. + +## Issue 62 + + * github issue number: #46 + * Fixed: 2.2.0 + +When the readable flag of the IPC socket was set with 0 readable bytes +available, cagebreak entered an infinite loop which caused high CPU +usage before the first event was sent over the IPC socket. + +## Issue 63 + + * github issue number: N/A + * Fixed: 2.2.0 + +A file path in the environment-variables unit test was wrongly set, +causing this test to fail. + +## Issue 64 + + * github issue number: N/A + * Fixed: 2.2.0 + +Cagebreak did not update the pointer focus when focussing the +background. This means that the first pointer event after focussing the +background was sent to the previously focussed window. + +Steps to reproduce: + + * Open an application and hover the mouse over a clickable area. + * Switch to an empty desktop using a keybinding without moving the + mouse. + * Click the mouse without moving it. + * Observe that the element in the previously focussed window was + clicked. + +## Issue 65 + + * github issue number: N/A + * Fixed: 2.2.1 + +Up until cagebreak 2.2.0, the configuration for the calibration matrix of +a libinput device was not propagated correctly when internally copying +the configuration. This meant that effectively, the calibration matrix +configuration was a NoOp. Starting with version 2.2.1, the calibration +matrix can be set as documented. + +Thanks to Oliver Friedmann for providing a pull request. + +## Issue 66 + + * github issue number: #65 + * Fixed 2.2.3 + +In Cagebreak 2.2.2 the compatible wlroots versions were wrongly specified. +To stop this from reoccurring, we have added a check to our release checks. + +## Issue 67 + + * github issue number: #66 + * Fixed 2.2.3 + +In Cagebreak 2.2.2 dual monitors were mirrored instead of extended, changing +established behaviour. + +## Issue 68 + + * github issue number: #38 + * Fixed: 2.3.0 + +After extensive discussion of how to deal with turning off outputs, the +output command was ammended by two settings (permanent & peripheral). +See man pages for details. + +Thanks to sodface for the great cooperation. + +## Issue 69 + + * github issue number: #68 + * Fixed: 2.3.0 + +The config man page (5) was badly formatted up to version 2.3.0. + +Particularly unescaped html tags caused not all information to be +shown in the web browser view of our repo. + +## Issue 70 + + * github issue number: #62 + * Fixed: 2.3.0 + +The README contained a few non-intuitive phrases up to version 2.3.0. + +To alleviate this, the following changes were made: + +- Rephrase README.md (for more clarity) +- Add CONTRIBUTING.md (to remove dev detail from README) +- Add PR template (to present relevant info during a PR) + +## Issue 71 + + * github issue number: #60 + * Fixed: 2.3.0 + +Cagebreak up to 2.3.0 did not have configuration for the message location. + +This has been added through the initiative of unsigned-enby to improve +accessibility. + +## Issue 72 + + * github issue number: N/A + * Fixed: 2.3.0 + +A Cagebreak version before 2.3.0 broke the gamma toolkit used to tune the +monitor colors. + +## Issue 73 + + * github issue number: #73 + * Fixed: 2.3.1 + +After 2.3.0 cagebreak did not build on FreeBSD. Since the fix was trivial, +this is fixed in 2.3.1. Thank to Jan Beich for pointing this out. + +## Issue 74 + + * github issue number: #71 + * Fixed. 2.3.0 + +Before 2.3.0 there was an issue with rendering fullscreen applications, particularly +under setups with multiple outputs applications spanned both outputs. Output ordering +also did not work as advertised. + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4da2ae2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,464 @@ +# Contributing + + * [Open an issue](https://github.com/project-repo/cagebreak/issues/new) and state your feature request. + We will get back to you. + * Read this document, [README.md](README.md) and [docs/dev-FAQ.md](docs/dev-FAQ.md). + * Ask before opening a pull request. We might not accept your + code and it would be sad to waste the effort. + * Respect the [Code of Conduct](CODE_OF_CONDUCT.md) (To date, we never + had to intervene - Please keep it that way!) + +## Good First Contributions + + * Reviews are always welcome. + * Read the code. + * Read the documentation. + * Test whether the documentation matches the code. + * Test Cagebreak in more esoteric setups (many monitors, for instance). + * Compile the code. + * Ideas on improving the testing and quality assurance are particularly + welcome. + * You can share your cagebreak scripts and we might include them with Cagebreak + provided you agree to release them under MIT and we agree with the + use case and coding style. + * If you are happy with Cagebreak under Arch Linux, you may vote for + [Cagebreak in the AUR](https://aur.archlinux.org/packages/cagebreak). + * The points from the Contributing section above still apply. + +## Philosophy + +Cagebreak is currently developed to fit the needs of its creators. + +The feature set is intentionally limited - we removed +support for a desktop background image for example. + +Nonetheless, don't be intimidated by any other part of this file. +Do your best and we will collaborate toward a solution. + +# Development + +## Compatibility & Development Distribution + +Cagebreak supports [Arch Linux](https://archlinux.org/) and uses the libraries +versions as they are obtained from extra and core +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.)). + +[![Packaging status](https://repology.org/badge/vertical-allrepos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) + +You should use Arch Linux if you want to modify Cagebreak +for yourself. + +## Review Requirements + +Project-repo will review your proposal before your implementation for feasibility +and desirability. After your pull request, the code will be reviewed in conjunction +with all other changes before the release as per the release procedure. + +All reviews performed by project-repo are verified by at least two people internally. + +## Developer Certificate of Origin (DCO) + +On any pull requests please include a + +``` +signed-off-by: YOUR IDENTIFIER OR NAME +``` + +DCO statement. + +By doing this you claim that you are legally allowed to contribute the +code and agree to let project-repo publish it under the MIT License. + +### Development Environment + +CAVEAT: This script works exclusively on Arch Linux, which, as outlined above, +is the development distribution of Cagebreak. + +Cloning the Cagebreak repository and building it is sufficient as a starting point. + +All other dependencies can be installed by invoking + +``` +meson compile devel-install -C build +``` + +if meson is already available or + +``` +./scripts/install-development-environment +``` + +otherwise. + +### Scripts + +Cagebreak provides a few convenience tools to facilitate development. + +#### Fuzzing + +If your fuzzing corpus is located in the directory `fuzz_corpus` you can +just call: + +``` +meson compile fuzz -C build +``` + +If you want to use a different directory, configure cagebreak with +`-Dcorpus=OTHERDIRECTORY` or call `./scripts/fuzz OTHERDIRECTORY`. + +#### Adjusting Epoch + +To facilitate the creation of reproducible man pages an arbitrary release +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 +a release tag you can call: + +``` +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` +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: + +``` +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 + +``` +meson compile set-ver -C build +``` + +to set the version number in the man pages and README repology minversion. + +Use of the script without meson is discouraged because meson.build is +not touched by the script. + +#### Create Release Artefacts + +The following command generates the release artefacts which must be created +once a release is completely ready to be published (the commit is tagged with +the version of the master branch, etc.): + +``` +meson compile create-artefacts -C build +``` + +Use of the script version is discouraged. + +## 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 +[-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 +``` + +## Test Suite + +``` +meson test -C build +``` + +invokes all tests. This is required for a release to occur. + +There are four test suites: + + * basic: tests actual outward-facing functionality + * Note optional dependencies for efficient socket interaction + * nc (openbsd-netcat) + * jq + * devel: tests internal properties of the repository + * Note potentially heavier dependencies such as + * shellcheck + * clang-format + * devel-long: applies more costly testing + * Note potentially heavier dependencies such as + * scan-build (static analysis (including security-relevant issues)) + * release: tests release specific considerations + * Note that this is only expected to pass just before + a release. This checks mostly administrative things + to check that a release is ready. + * Note that non-auto tests are files in `release-non-auto-checks` + and have to contain the release version and current date in + YYYY-mm-dd format on seperate lines. This is our imperfect attempt + to guarantee some hard-to-automate checks are carried out before + a release is undertaken. + +Every commit should pass at least the basic and devel suites. + +It is expected that cagebreak passes at least the +basic, devel and devel-long suites when commits are pushed: + +``` +meson test -C build --suite basic --suite devel +``` + +The basic suite can be used to test a binary. This is +useful for PKGBUILDs and their equivalents in other +systems. + +``` +meson test -C build --suite basic +``` + +## Fuzzing + +Along with the project source code, a fuzzing framework based on `libfuzzer` is +supplied. This allows for the testing of the parsing code responsible for reading +the `cagebreak` configuration file. When `libfuzzer` is available (please +use the `clang` compiler to enable it), building the fuzz-testing software can +be enabled by passing `-Dfuzz=true` to meson. This generates a `build/fuzz/fuzz-parse` +binary according to the `libfuzzer` specifications. Further documentation on +how to run this binary can be found [here](https://llvm.org/docs/LibFuzzer.html). + +Here is an example workflow: + +``` +rm -rf build +CC=clang meson setup build -Dfuzz=true -Db_sanitize=address,undefined -Db_lundef=false +ninja -C build/ +mkdir build/fuzz_corpus +cp examples/config build/fuzz_corpus/ +WLR_BACKENDS=headless ./build/fuzz-parse -jobs=12 -max_len=50000 -close_fd_mask=3 build/fuzz_corpus/ +``` + +You may want to tweak `-jobs` or add other options depending on your own setup. +We have found code path discovery to increase rapidly when the fuzzer is supplied +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 +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 +release. + +There are reproducibility issues up to and including release `1.2.0`. See +`Issue 5` in [Bugs.md](Bugs.md). + +### Reproducible Build Instructions + +All hashes and signatures are provided for the following build instructions. + +``` +meson setup build -Dxwayland=true -Dman-pages=true --buildtype=release +ninja -C build +``` + +### Hashes for Builds + +For every release after 1.0.5, hashes will be provided. + +For every release after 1.7.0, hashes will be provided for man pages too. + +See [Hashes.md](Hashes.md) + +### GPG Signatures + +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. + +Due to errors in the release process, the releases 1.7.1 and 1.7.2 did not include the release +signatures in the appropriate folder of the git repository. However, signatures were provided +as release-artefacts at the time of release. The signatures were introduced into the +repository with 1.7.3. The integrity of cagebreak is still the same because the signatures were +provided as release-artefacts (which were themselves signed) and the hashes in Hashes.md +are part of a signed release tag. + +### Signing Keys + +All releases are signed by at least one of the following collection of +keys. + + * E79F6D9E113529F4B1FFE4D5C4F974D70CEC2C5B (expired) + * 4739D329C9187A1C2795C20A02ABFDEC3A40545F (expired) + * 7535AB89220A5C15A728B75F74104CC7DCA5D7A8 (expired) + * 827BC2320D535AEAD0540E6E2E66F65D99761A6F (expired) + * A88D7431E5BAAD0B6EAE550AC8D61D8BD4FA3C46 (expired) + * 8F872885968EB8C589A32E9539ACC012896D450F (expired) + * 896B92AF738C974E0065BF42F2576BD366156BB9 (expired) + * AA927AFD50AF7C6810E69FE8274F2C605359E31B (expired) + * BE2DED372287BC4EB2213E13A0C743848A638955 (expired) + * 0F3476E4B2404F95EC41600683D5810F7911B020 (expired) + * [4E82C72C6B3E58A7BC4FF8554909F84CA83BB867](keys/cagebreak_signing_key_11@project-repo.co.pub) + * [5AEB1A2EB0D13F67E306AC59DC0CC81BE006FD85](keys/cagebreak_signing_key_12@project-repo.co.pub) + * [438C27DDB5D174673DF4D67B451205B3528C7C63](keys/cagebreak_signing_key_13@project-repo.co.pub) + * [81372DDB8124349F0303B77448D7E2EE3343E3AA](keys/cagebreak_signing_key_14@project-repo.co.pub) + +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.md](SECURITY.md) +for details. + +The full public keys can be found in `keys/` along with any revocation certificates. + +## Versioning & Branching Strategy + +Cagebreak uses [semantic versioning](https://semver.org). + +There are three permanent branches in cagebreak: + + * `master` (for releases) + * `development` (for polishing code between releases) + * `hotfix` (for small emergent releases, usually up-to-date with master) + +Releases are merged to master as per the release procedure, with +reasonable exceptions as the situation requires. + +The release commit is tagged with the release version. + +In the past, our git history did not perfectly reflect this scheme. + +## Release Procedure + +The release procedure outlines the process for a release to occur. + + * [ ] `git checkout development` + * [ ] `git pull origin development` + * [ ] `git push origin development` + * [ ] Arch Build System is up to date + * [ ] `meson test -C build/` just to get an overview + * [ ] Update internal wiki + * [ ] Adjust version number in meson.build + * [ ] `meson compile set-ver -C build` + * [ ] Add new files to meson.build or hardcoded testing variable + * [ ] Commit changes + * [ ] `git push origin development` + * [ ] Complete relevant documentation + * [ ] New features + * [ ] tests added and old test scripts adjusted + * [ ] man pages + * [ ] cagebreak + * [ ] cagebreak-config + * [ ] cagebreak-socket + * [ ] example config + * [ ] FAQ.md + * [ ] Changelog.md for major and minor releases but not patches + * [ ] Check changes for SECURITY.md relevance (changes to socket scope for example) + * [ ] Synchronize any socket changes to cagebreak-socket man page + * [ ] Document fixed bugs in Bugs.md + * [ ] Include issue discussion from github, where applicable + * [ ] `meson compile adjust-epoch -C build` + * [ ] Commit changes + * [ ] `git push origin development` + * [ ] Testing + * [ ] Manual testing + * [ ] `meson compile fuzz -C build` for at least one hour + * [ ] Adjust Hashes.md - Use `meson compile output-hashes -C build` to add Hashes or aid in repro check + * [ ] Commit changes + * [ ] `git push origin development` + * [ ] Complete release-non-auto-checks + * [ ] `meson compile create-sigs -C build` + * [ ] Commit and push signatures, hashes and non-auto-check files + * [ ] `meson test -C build` passes everything except some release tests + * [ ] `git add` relevant files + * [ ] `git commit` + * [ ] `git push origin development` + * [ ] `git checkout master` + * [ ] `git pull --tags origin master` + * [ ] `git merge --squash development` + * [ ] `git commit` and insert message + * [ ] `meson compile git-tag -C build` + * [ ] `meson compile create-artefacts -C build` + * [ ] `meson test -C build` THIS MUST PASS WITHOUT ANY FAILURES WHATSOEVER + * [ ] `git push --tags origin master` + * [ ] `git checkout development` (merge to development depends on whether release was a hotfix) + * [ ] `git merge master` + * [ ] `git push --tags origin development` + * [ ] `git checkout hotfix` (hotfix is to be kept current with master after releases) + * [ ] `git merge master` + * [ ] `git push --tags origin hotfix` + * [ ] Upload archives and signatures as release assets + * [ ] Delete feature branches if appropriate + * [ ] Manage package release + diff --git a/Changelog.md b/Changelog.md index c33e179..a3223e5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,40 +1,100 @@ # Changelog -## Release 1.0.0 +## Release 2.3.0 -Adds basic tiling window manager functionality to cage. +Functionality: + * Add configuration to anchor position of messages (#60, 71 in Bugs.md). + * Add output priorisation (#38, 68 in Bugs.md). + * Print whether output is active in dump. -## Release 1.1.0 +Bug Fixes: + * Fix gamma control (72 in Bugs.md). + * Add missing commands to example config. + * Add message_config to dump output. -Unifies commands and actions. See Issue 4 in Bugs.md. +Example Scripts: + * Add screenshot script. + * Make example scripts standalone. -## Release 1.2.0 +Documentation: + * Escape html tags in config man page. (#68, 69 in Bugs.md) + * Improve README.md (#62, 70 in Bugs.md). + * Improve SECURITY.md. + * Add CONTRIBUTING.md (#62, 70 in Bugs.md). + * FAQ: Add Firefox screenshare instructions for wayland. + * FAQ: Add wlroots downgrading instructions for workaround in case of temporary wlroots incompatibility. + * Update copyright notices to 2024. -Adds output configuration as described in the man pages. +Development Tooling: + * Add new gpg keys (signed by the old ones). + * Add PR template. + * Add dev-FAQ. + * Remove now-unnecessary fanalyzer pragmas. -## Release 1.3.0 +## Release 2.2.0 -Adds IPC as described in the man pages. + * Add custom events + * Fix Issue 62 (#46 Github) + * Fix Issue 63 (environment variables test) + * Fix Issue 64 (pointer focus bug) -## Release 1.4.0 +## Release 2.1.0 -Adds close command for windows as described in the man pages. + * Add -bs (bad security) option + * Fix Issue 57 (SPDX spelling error #39) + * Fix Issue 59 (meson install settings) + * Fix Issue 55 (npd) + * Fix Issue 56 (npd) + * Fix Issue 58 (#40 config) + * Improve release procedure + * Add miniscule test suite + * Adjust Cagebreak to wlroots 0.16.2 + * New GPG Keys -## Release 1.5.0 +## Release 2.0.0 -Adds options to disable or enable outputs. See Issue 22 in Bugs.md and Issue #2 on github. +This is a major release and includes BREAKING changes! -## Release 1.6.0 +Breaking Changes: -Adds support for non-build dependencies and an option for builds without pandoc. + * More intuitive switch of focus, next, prev and exchange (#20, 40 in Bugs.md) + Cagebreak will probably still feel broadly the same though. + * Remove -r flag - This is replaced by output configuration. + * Socket disabled by default - The socket is enabled by invoking Cagebreak with the -e flag. + * Socket permissions restricted to the user of the Cagebreak process (700) + This may require modification of scripts interacting with the socket with + different UIDs than the UID of the Cagebreak process. + * Rename "Current frame" indicator to "Current tile" -## Release 1.7.0 +Changelog: -Improves window ordering. - -## Release 1.8.0 - -Adds libinput configuration and virtual keyboard and pointer support. + * Move to wlr_scene + * Add events displaying change over the socket + * this enables scripting tools + * Add support for scaling outputs (thanks to Oliver Friedmann) + * Remove -r flag + * Add rotation to output configuration + * Add cursor enable|disable flag + * Add input keyboard configuration + * Custom path flag for configuration file + * Restrict socket permissions to the user running cagebreak (700) + * Fix Issue #31 (resolve some terminology) 38 in Bugs.md + * Fix Issue #30 - 39 in Bugs.md + * Fix Issue #20 - 40 in Bugs.md + * Fix Issue #12 - 41 in Bugs.md (dump + events over socket) + * Fix Bugs found via scan-build static analysis (42 - 45 in Bugs.md) + * Fix Issue #33 - 46 in Bugs.md + * Fix Issue #32 - 47 in Bugs.md + * Fix Issue #16 - 48 in Bugs.md + * Fix Issue #3 - 49 in Bugs.md (disabling keybinding interpretation for specific keyboards is now possible) + * Fix Issue #26 - 50 in Bugs.md + * Fix Issue #7 - 51 in Bugs.md (Change cursor to square while Cagebreak is waiting for a key) + * Fix config bug for some commands - 52 in Bugs.md + * Fix Issue #35 - 53 in Bugs.md (update to wlroots 0.16.1) + * Improve FAQ.md (related to some Issues) + * Disable outputs when unable to set any mode (crashed previously) + * Add Code of Conduct + * Print version number on startup ## Release 1.9.0 @@ -64,58 +124,39 @@ Adds libinput configuration and virtual keyboard and pointer support. - Add new cagebreak email contact gpg key - Add new project-repo AUR gpg key (relevant for cagebreak-pkgbuild) -## Release 2.0.0 +## Release 1.8.0 -This is a major release and includes BREAKING changes! +Adds libinput configuration and virtual keyboard and pointer support. -Breaking Changes: - * More intuitive switch of focus, next, prev and exchange (#20, 40 in Bugs.md) - Cagebreak will probably still feel broadly the same though. - * Remove -r flag - This is replaced by output configuration. - * Socket disabled by default - The socket is enabled by invoking Cagebreak with the -e flag. - * Socket permissions restricted to the user of the Cagebreak process (700) - This may require modification of scripts interacting with the socket with - different UIDs than the UID of the Cagebreak process. - * Rename "Current frame" indicator to "Current tile" +## Release 1.7.0 -Changelog: - * Move to wlr_scene - * Add events displaying change over the socket - * this enables scripting tools - * Add support for scaling outputs (thanks to Oliver Friedmann) - * Remove -r flag - * Add rotation to output configuration - * Add cursor enable|disable flag - * Add input keyboard configuration - * Custom path flag for configuration file - * Restrict socket permissions to the user running cagebreak (700) - * Fix Issue #31 (resolve some terminology) 38 in Bugs.md - * Fix Issue #30 - 39 in Bugs.md - * Fix Issue #20 - 40 in Bugs.md - * Fix Issue #12 - 41 in Bugs.md (dump + events over socket) - * Fix Bugs found via scan-build static analysis (42 - 45 in Bugs.md) - * Fix Issue #33 - 46 in Bugs.md - * Fix Issue #32 - 47 in Bugs.md - * Fix Issue #16 - 48 in Bugs.md - * Fix Issue #3 - 49 in Bugs.md (disabling keybinding interpretation for specific keyboards is now possible) - * Fix Issue #26 - 50 in Bugs.md - * Fix Issue #7 - 51 in Bugs.md (Change cursor to square while Cagebreak is waiting for a key) - * Fix config bug for some commands - 52 in Bugs.md - * Fix Issue #35 - 53 in Bugs.md (update to wlroots 0.16.1) - * Improve FAQ.md (related to some Issues) - * Disable outputs when unable to set any mode (crashed previously) - * Add Code of Conduct - * Print version number on startup +Improves window ordering. -## Release 2.1.0 +## Release 1.6.0 + +Adds support for non-build dependencies and an option for builds without pandoc. + +## Release 1.5.0 + +Adds options to disable or enable outputs. See Issue 22 in Bugs.md and Issue #2 on github. + +## Release 1.4.0 + +Adds close command for windows as described in the man pages. + +## Release 1.3.0 + +Adds IPC as described in the man pages. + +## Release 1.2.0 + +Adds output configuration as described in the man pages. + +## Release 1.1.0 + +Unifies commands and actions. See Issue 4 in Bugs.md. + +## Release 1.0.0 + +Adds basic tiling window manager functionality to cage. - * Add -bs (bad security) option - * Fix Issue 57 (SPDX spelling error #39) - * Fix Issue 59 (meson install settings) - * Fix Issue 55 (npd) - * Fix Issue 56 (npd) - * Fix Issue 58 (#40 config) - * Improve release procedure - * Add miniscule test suite - * Adjust Cagebreak to wlroots 0.16.2 - * New GPG Keys diff --git a/FAQ.md b/FAQ.md index d8918a0..83fd29b 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2,14 +2,9 @@ ## How do I do a particular thing with cagebreak? - * Check the man pages - * [cagebreak config](man/cagebreak-config.5.md) (probably where you find the answer) - * [cagebreak](man/cagebreak.1.md) (command line options etc.) - * [cagebreak-socket](man/cagebreak-socket.7.md) (socket information, mostly useful for scritping) - * Check the rest of this FAQ - * [Open an issue](https://github.com/project-repo/cagebreak/issues/new) or otherwise get in touch with the development team (See section Email Contact in [SECURITY.md](SECURITY.md)). - -Note that the feature set of cagebreak is intentionally limited. + * Check the [man pages](manuals.md). + * Check the rest of this file. + * [Open an issue](https://github.com/project-repo/cagebreak/issues/new) or get in touch (See section Email Contact in [SECURITY.md](SECURITY.md)). ## How do I remap Caps Lock? @@ -17,6 +12,21 @@ Remapping Caps Lock globally seems to be the best option. Follow instructions [here](https://wiki.archlinux.org/title/Linux_console/Keyboard_configuration) to achieve this (should be roughly distribution-agnostic). +## What do I do if Cagebreak does not work with the current wlroots version? + +You can probably downgrade wlroots with + +``` +$ pacman -U /var/cache/pacman/pkg/old-version +``` + +If you have cleared your package cache, see instructions in the [ArchWiki](https://wiki.archlinux.org/title/downgrading_packages#Return_to_an_earlier_package_version). + +Cagebreak should start working again after the downgrade. + +After a new release, the downgrading will no longer be necessary (in fact, +downgrading will probably break your setup). + ## How do I get firefox to run under wayland? Set the following environment variables @@ -26,6 +36,17 @@ Set the following environment variables to activate wayland support for firefox. +## How do I get firefox to screenshare properly? + +Execute the following commands with the appropriate env vars: + +``` +export XDG_SESSION_TYPE=wayland +export XDG_CURRENT_DESKTIP=sway +/usr/lib/xdg-desktop-portal -r +/usr/lib/xdg-desktop-portal-wlr +``` + ## How do I map characters which are not on the Keyboard? Suppose you want to use a command like `bind` for a character diff --git a/Hashes.md b/Hashes.md index a6ceae1..7f0018a 100644 --- a/Hashes.md +++ b/Hashes.md @@ -1,5 +1,125 @@ # Hashes +2.3.1 cagebreak + + * sha 256: 51d76608726a6251690d6dd1371cdfaa6eae5188a08798cda9c9280b3fcbe3fa + * sha 512: 648c61958f5920b3377f53706f7a820750a2b7dd1d486db4a93d803fe38be4aa728058e82d404fde4e7f1627b9809050a5760c4193562a6c23e39d0851f1ddf0 + +2.3.1 cagebreak.1 + + * sha 256: c58390d641514b2eb623a803dc665116d60079b8aac39219b939cc36ffb72038 + * sha 512: 82c0248764026666e6fbe3e29bf48062db07d6a86c787258474312a0eae23a73898bcc2fd6c407fbac0a25d6414f9ca9a56e5d17d7c8adfe9e7ce903e6ed5978 + +2.3.1 cagebreak-config.5 + + * sha 256: 5cf2f8c883ce89563bbae1fa4f0e00bda42c4ba01f680fc75fc71ab3f6e1f2a8 + * sha 512: 10d72ca588f5e2123dc59ede89dafd0e6fb9cd6cbc83922ada751c37f9000c86f68e5e6bf9f68298380ec0f9cbce1f22d0a0f712d0004b168a0b039a41f32358 + +2.3.1 cagebreak-socket.7 + + * sha 256: 0363113a32533a6fb4a1e7030cff880f001db5e0c29bb8bd74f8f11067dce3d1 + * sha 512: f957ebad717456901a028344211609d009d9b8c2a68ef88a0d60fca8dc91cc1fe1aba58a9e84d16782190b59b9fcd1d45ecc154c020018609c8fcdf940aa18e4 + +2.3.0 cagebreak + + * sha 256: 549e82f6bb1af87c9272fb92d39c6f235b0f780885b066c32db5a5c7588da378 + * sha 512: d05e5ac9e4295bed93b8872a815b1f8aaf8ddc2448c01f84d5d29b4d5610bb5c0c50f87b15653bb663a9f772a899dc7b8215042db3ac86aa1ba3000ccb9757d2 + +2.3.0 cagebreak.1 + + * sha 256: 11cbe6ea82fa19064ee5b9d8346dbaa8ca8251948c5f5eee7387516edcfbeab0 + * sha 512: 76f15788aeebb2cab5a0a477f1427646964c6011c20d64f43f6c445bf08e5371971607a7565017fd05f4f2d75c66da5d79948643618eeb4d3619bc7e6128cffe + +2.3.0 cagebreak-config.5 + + * sha 256: dc8755bbed108cd0cf76f05eee0c6d08550373eab5f75895755abddb7b86e84c + * sha 512: b93caa7cd4ec9085409472982ce72a8e55a369cb830a7d3132801b24db0660e4259a3e9b229dbaf960bc28c4d8a384a19f7bbb11e74f7c4e3f90b04d2b5280ee + +2.3.0 cagebreak-socket.7 + + * sha 256: f33abe5f18cb087ab421c3b647437c31a01e5c731638cac859a9b9ea1f88099e + * sha 512: f973bd2a67d9ca8b4bf2d150c4f1151163f379c7048e1e4be098d8032a424c77bd4dfaa98635bb8cdefa0b2da147b9b6a87bcbcaa87c378b5040e708f8ca5a97 + +2.2.3 cagebreak + + * sha 256: 265a9d09622272ca6ea79ddcdbdc6003704106814eb05a2b7547a77a982263de + * sha 512: 757f837a7e6ddd71fed88c4e1aab5cab9d4d07e8b76f280eed9afa35a2eaee23c0553299fe49a0139c754179d0df68c1303725f1f909921d078516e14ba3f21f + +2.2.3 cagebreak.1 + + * sha 256: 275698641476efa40fc1b33a8025e6dbba3ec931fbaf0a627c0748dad987ed4d + * sha 512: 617891ded06657e31daefee84a03191ad6e03892118f1790a5ebaa6e847c4d18d4b6849edc00841bd68abc9e0e0a111153efe102db02ce3d408c903b0d045927 + +2.2.3 cagebreak-config.5 + + * sha 256: 5967e9131d1ee16ffa046a732911c902e41f2e18f3170d11a47b9be596b4978a + * sha 512: 6d3c5fbb2b95a75d7c5a8ed8b5922cfcc4135857b389652572c5d9c211c6da9cf8ef0b5dc0e8eaa540c6b1c2dd215f512df2ef49ce80c34e8e5ad170bfb7134e + +2.2.3 cagebreak-socket.7 + + * sha 256: cb1bde8a6fb2a1fa2b7b8db7fdef9b933cd471ca604e15d1dd9133859fa6eea3 + * sha 512: 1d99672cb7ac7323790d47986d206bf8c392698db0cd52978963deb6e85118c6822e2d45c7fa66e8636e95214f8893d963a3157ca24239d2fd2d78b1e26f11e7 + +2.2.2 cagebreak + + * sha 256: 98e0dfe870a7242fdf7c6fb1a5c520cfe7d1154b3f139560da6cb86b2430b2a0 + * sha 512: c335f8f6e226203e797e232caead74db9b1e7f24d5edf80dd99a0c00c5f4e81351a5ddcad4f601a12618ebed5c62be547462c4f06ae4ccb6a622a869ee8741ec + +2.2.2 cagebreak.1 + + * sha 256: c655fff018377b5ee541854ee428559ba4c5080d44f87247fe608f18651b0764 + * sha 512: 7cbef17cbe3c59cde21466d6c76e1a34ffce748d2d9011a77bd7703f605b737e344cabaad1e3a599316321481524cb860b2533ab6bef2e7714c00b2641fe962c + +2.2.2 cagebreak-config.5 + + * sha 256: b799e0252d7224befc92bdd143d00dc3f42a38e39f510f3ace575b03f293a788 + * sha 512: 3778db9ff07429efb74b4b07476193844698e07ea91a742aac078391ba38fb07987dc61ba312c30b6eb04ad2d847ee552826e7a09be8dc572be5626c27059df3 + +2.2.2 cagebreak-socket.7 + + * sha 256: dd10359fd1840909bb817858668e67bdd433f367b0ed199328e4b29c99529322 + * sha 512: 67f8c39864472c9b2396946a943ce249297b1b9fc5e452a4051f0512fd61b4a22906e1a16aee1c2bf6cacb3b9cd7a11da19c5d760c192020402008eab379eee1 + +2.2.1 cagebreak + + * sha 256: 96469a78eeaddf9476c82e0ab8a0e35a95b3119bf83633a54feb8f3f5780df2f + * sha 512: 41135e9d81c79519a1db4955c742f50a375c4e4db80b51a02d618eb1520452c059a3df48013d11f17410a590ac43634da606daf6e95d0987af19284964bbcb5e + +2.2.1 cagebreak.1 + + * sha 256: 458259b066def0571b7604f4a87105f0ce608106abd7946e4697aa5ec5028ccf + * sha 512: aeed13e27e78ea8b30ee21f6ef41725f2808f484f0a3e6125cf70c601705954eb4a4a67ba9d6898ff994a79c20a0213557332d7f06a42098084aff3fe47ca21a + +2.2.1 cagebreak-config.5 + + * sha 256: 4ec5a18fae8d1170ff9d67126133a12ca7b1f7adae318d77f6fca8092c138761 + * sha 512: 9b35fde46191979dee5839873eaab4a673256f75dce533df141f43f7d8282381e1e3820d1cf97403c50846b1f4ddf1924271e961d519029ed58e76e31aef4c04 + +2.2.1 cagebreak-socket.7 + + * sha 256: 51911ee02637261e46164d861c4327ec338904221795a03895684582c361ef81 + * sha 512: db848faefbf5f1eff6d4f0ad1fc4e2169beb7fd0ada620b39fe64a319376e4c7e672c48a3e446943af40d23055467b001b8e1c38b4b72648258b6f7b14c1034d + +2.2.0 cagebreak + + * sha 256: 67660297290a18b7822a818d1d43343e4e6f4dc27427ed9099ff803f218aa9b4 + * sha 512: 9837e3901b2b10453db2663f5a3da6ec2393610c82984cbabe1c64a6d575e32b492cd3326a6fbb91faa912d14c58dfd1160168280b66417ce7f7f2306c5a501c + +2.2.0 cagebreak.1 + + * sha 256: 79caf055cb1c75f3751863718728cca5ea6231891d21b4364c877d5e4888e727 + * sha 512: 843e15e51f01ed25d0630eee8b6e12ebcc68934da49d6fb66e86f6a46d512145d9be22081b0c2b5f0356c2d0e15b9f13170f7ba1d34d5fba69c7e05a069db337 + +2.2.0 cagebreak-config.5 + + * sha 256: 7047333f5600d3b05caf04caf9910da1468efe49c1418ca3fcdc6163bade9e89 + * sha 512: 35203d3959594fe5130a561c440bf85a978384bc874fcce773bb02fa5c637ccc375f1b0ce1ad05603266dcdefed2570815363bc2c8ef81df7ff7be865de2cac5 + +2.2.0 cagebreak-socket.7 + + * sha 256: bf9bd35a17ab78cb93f0f5209daef27908bf02d0e31ae627ae05fabab162c984 + * sha 512: 023fb99c3a2c47543ae2870f19e8fd6fd8069834dc4fbeee93e890333b4ac24b4613d0e8dfd2bdffb2d5dc7f907868410b0c61f2e1346c76498955e15d0f3b89 + 2.1.2 cagebreak * sha 256: 7d07864a837ee577a52b2727bfbfe8834fe599712144f0685f458d508717e451 diff --git a/LICENSE b/LICENSE index e0aba93..462eccf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2020-2023 The Cagebreak authors +Copyright (c) 2020-2024 The Cagebreak authors Copyright (c) 2018-2020 Jente Hidskes Copyright (c) 2019 The Sway authors diff --git a/README.md b/README.md index 004239a..c4ce338 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,55 @@ -# Cagebreak: A Wayland Tiling Compositor +# 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.1.2)](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.3.1)](https://repology.org/project/cagebreak/versions) -## Quick Introduction +[![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) -Cagebreak is a [Wayland](https://wayland.freedesktop.org/) tiling compositor -based on [Cage](https://github.com/Hjdskes/cage) and inspired by [ratpoison](https://www.nongnu.org/ratpoison/). +## Introduction -### Purpose +Cagebreak provides a [ratpoison](https://www.nongnu.org/ratpoison/)-inspired, [cage](https://github.com/Hjdskes/cage)-based, tiling [Wayland](https://wayland.freedesktop.org/) compositor. -The goal of this project is to provide a successor to ratpoison for Wayland. -However, this is no reimplementation of ratpoison. - -#### New Features, Bugs and Contact Information - -Should you want to know if a feature will be implemented, file a bug or -get in touch, [open an issue](https://github.com/project-repo/cagebreak/issues/new) -or write an e-mail (See [SECURITY.md](SECURITY.md) for details.). - -The Roadmap section outlines what is planned for the future. - -#### Compatibility & Development Distribution - -Cagebreak supports [Arch Linux](https://archlinux.org/) and uses the libraries -(and software versions) as they are obtained through [pacman](https://wiki.archlinux.org/title/Pacman) -at the time of release. Any other use is out of scope. - -Most other setups probably work with a bit of luck. We -make no guarantees. - -### Quick Installation - -This assumes Arch Linux: - -1. Use the [cagebreak PKGBUILD](https://aur.archlinux.org/packages/cagebreak). -2. Add an example config such as [config](examples/config) to `$USER/.config/cagebreak/config` -3. Execute cagebreak like any other binary. - -See the [ArchWiki](https://wiki.archlinux.org/title/Cagebreak#Getting_started) for -details on getting started and the documentation for everything else. - -### Documentation - - * the rest of this file - * the man pages: - * [cagebreak](man/cagebreak.1.md) - * [configuration](man/cagebreak-config.5.md) - * [socket](man/cagebreak-socket.7.md) - * the [FAQ](FAQ.md) - * [SECURITY.md](SECURITY.md) - -#### What's new? - -See the [Changelog](Changelog.md). - -### Uninstallation - -`pacman -R cagebreak` should be sufficient. - -### Contributing - - * Just [open an issue](https://github.com/project-repo/cagebreak/issues/new) and state your idea. - We will consider the proposal and get back to you. - * Don't open a pull request. We might not accept your code and - it would be sad to waste the effort. - * Respect the [Code of Conduct](CODE_OF_CONDUCT.md) (To date, we never - had to intervene - Keep it that way!) - -### Name - -Cagebreak is based on [Cage](https://github.com/Hjdskes/cage), a Wayland kiosk -compositor. Since it breaks the kiosk into tiles the name -Cagebreak seemed appropriate. + * Bugs, Contact Information and New Features: + * [Open an issue](https://github.com/project-repo/cagebreak/issues/new). + * Write an e-mail (See [SECURITY.md](SECURITY.md)). + * The Roadmap below outlines our plans. + * Compatibility & Development Distribution: + * Cagebreak supports [Arch Linux](https://archlinux.org/) and uses the library + versions from extra and core at the time of release. + Most other setups work with a [bit of luck](https://repology.org/project/cagebreak/versions). + * Quick Installation (on ArchLinux, more [here (ArchWiki)](https://wiki.archlinux.org/title/Cagebreak)): + 1. Use the [cagebreak PKGBUILD](https://aur.archlinux.org/packages/cagebreak). + 2. Add an example config such as [config](examples/config) to `$USER/.config/cagebreak/config` + 3. Execute cagebreak like any other binary. + * Documentation: + * [man pages](manuals.md) + * [README](README.md), [FAQ](FAQ.md) & [SECURITY.md](SECURITY.md) + * What's new?: [Changelog](Changelog.md) + * Uninstallation: `pacman -R cagebreak` + * Contributing: + * [Open an issue](https://github.com/project-repo/cagebreak/issues/new) and state your idea. + We will get back to you. + * Ask before you open a pull request. We might not accept your code and + it would be sad to waste the effort. + * Respect the [Code of Conduct](CODE_OF_CONDUCT.md) (To date, we've never + had to intervene. - Keep it that way!) + * Name: Cagebreak breaks the kiosk of [Cage](https://github.com/Hjdskes/cage) into tiles, hence the name. ## Installation -On Arch Linux, just use the PKGBUILDs from the [AUR](https://aur.archlinux.org/): +On [Arch Linux](https://archlinux.org/), use the [AUR](https://aur.archlinux.org/) [PKGBUILDs](https://wiki.archlinux.org/title/PKGBUILD): * Using [cagebreak](https://aur.archlinux.org/packages/cagebreak), Cagebreak is - compiled on the target system (since release 1.3.0) + built on the target system (since release 1.3.0) * Using [cagebreak-bin](https://aur.archlinux.org/packages/cagebreak-bin), - the pre-built binaries are extracted to - appropriate paths on the target system (since release 1.3.2) + pre-built binaries are extracted + to the target system (since release 1.3.2) See [cagebreak-pkgbuild](https://github.com/project-repo/cagebreak-pkgbuild) for details. +You may check out other distros here: + +[![Packaging status](https://repology.org/badge/vertical-allrepos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) + ### Obtaining Source Code There are different ways to obtain cagebreak source: @@ -94,61 +59,69 @@ There are different ways to obtain cagebreak source: #### Verifying Source Code -There are corresponding methods of verifying that you obtained the correct code: +There are ways to verify that you obtained the correct source (See `keys/` +and [CONTRIBUTING](CONTRIBUTING.md)): - * our git history includes signed tags for releases - * release assets starting at release 1.2.1 contain a signature for the tarball + * signature for the tarball of release assets starting at release 1.2.1 + * signed tags for releases in the git history ## 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 -breaking changes as soon as they occur. +Cagebreak uses the [meson](https://mesonbuild.com/) build system. -Simply execute the following steps to build Cagebreak: +Cagebreak is developed against the latest tag of wlroots, so as not to constantly +chase breaking changes. + +Execute the following commands to build Cagebreak: ``` -$ meson setup build +$ meson setup build -Dxwayland=true -Dman-pages=true --buildtype=release $ ninja -C build ``` -#### Release Build +### Man Pages -By default, this builds a debug build. To build a release build, use `meson -setup build --buildtype=release`. +Remove `-Dman-pages=true` to disable man page generation. -##### Xwayland Support +To generate man pages, make sure that you have [scdoc](https://archlinux.org/packages/extra/x86_64/scdoc/) installed. -Cagebreak comes with compile-time support for XWayland. To enable this, -first make sure that your version of wlroots is compiled with this -option. Then, add `-Dxwayland=true` to the `meson` command above. Note -that you'll need to have the XWayland binary installed on your system -for this to work. +### Release Build -##### Man Pages +To obtain a debug build, remove `--buildtype=release`. -Cagebreak has man pages. To use them, make sure that you have `scdoc` -installed. Then, add `-Dman-pages=true` to the `meson` command. +The release build is reproducible under conditions outlined in [CONTRIBUTING](CONTRIBUTING.md). -### Running Cagebreak +### Xwayland Support -You can start Cagebreak by running `./build/cagebreak`. If you run it from -within an existing X11 or Wayland session, it will open in a virtual output as -a window in your existing session. If you run it in a TTY, it'll run with the -KMS+DRM backend. Note that a configuration file is required. For more -configuration options, see the man pages. +To build Cagebreak without XWayland support, remove `-Dxwayland=true`. -Please see `example_scripts/` for example scripts and a basis to customize -from. +To use XWayland make sure that your version of wlroots is compiled with +XWayland support. -#### Usage Philosophy +You'll need to have [XWayland](https://archlinux.org/packages/extra/x86_64/xorg-xwayland/) installed for XWayland support to work. -Cagebreak was originally built to suit the needs of its creators. This section outlines +## Running Cagebreak + +``` +$ ./build/cagebreak +``` + +If you run Cagebreak within an existing X11 or Wayland session, it will +open in a virtual output as a window in your existing session. + +If you run it in a TTY, it'll run with the KMS+DRM backend. + +Note that a configuration file is required. For more configuration options, see the [man pages](manuals.md). + +Please see `example_scripts/` for a basis to customize from. + +### Usage Philosophy + +Cagebreak was built to suit the needs of its creators. This outlines how we intended some parts of cagebreak and might ease learning how to use cagebreak a -little bit. Please note that this does not replace the man pages or the FAQ. -Also, this is in no way intended as a guide on how cagebreak must be used but rather -as a source of inspiration and explanations for certain particularities. +little bit. Please note that this does not replace the [man pages](manuals.md) or the [FAQ](FAQ.md). +Also, this is not intended as a guide on how cagebreak must be used but +as a source of inspiration and explanation for certain particularities. 1. Cagebreak is keyboard-based. Everything regarding cagebreak can be done through the keyboard and it is our view that it should be. This does not mean @@ -205,467 +178,6 @@ as a source of inspiration and explanations for certain particularities. > Example scripts can be found in the repository under `example_scripts/`. -## Contributing - - * Read this document. - * Just [open an issue](https://github.com/project-repo/cagebreak/issues/new) and state your feature request. - We will consider the proposal and get back to you. - * Don't open a pull request without asking first. We might not accept your - code and it would be sad to waste the effort. - * Respect the [Code of Conduct](CODE_OF_CONDUCT.md) (To date, we never - had to intervene - Please keep it that way!) - -### Good First Contributions - - * Reviewing the project is always welcome. - * Read the code. - * Read the documentation. - * Test whether the documentation matches the code. - * Test Cagebreak in more esoteric setups (many monitors, for instance). - * Compile the code. - * Ideas on improving the testing and quality assurance are particularly - welcome. - * If you want, you can share your cagebreak scripts and we might include them - in the repository provided you agree to release them under MIT and we agree - with the use case and coding style. - * Iff you are happy with Cagebreak and use Arch Linux, you may vote for - [Cagebreak in the AUR](https://aur.archlinux.org/packages/cagebreak). - * The points above still apply. - -### Philosophy - -Cagebreak is currently developed to fit the needs of its creators. - -The feature set is intentionally limited - we removed -support for a desktop background image for example. - -Nonetheless, don't be intimidated by any other part of this file. -Do your best and we will collaborate toward a solution. - -## Development - -### Compatibility & Development Distribution - -Cagebreak supports [Arch Linux](https://archlinux.org/) and uses the libraries -(and software versions) as they are obtained through [pacman](https://wiki.archlinux.org/title/Pacman) -at the time of release. Any other use is out of scope. - -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.)). - -[![Packaging status](https://repology.org/badge/vertical-allrepos/cagebreak.svg)](https://repology.org/project/cagebreak/versions) - -You should use Arch Linux if you want to modify Cagebreak -for yourself. - -### Review Requirements - -Project-repo will review your proposal before your implementation for feasibility -and desirability. After your pull request, the code will be reviewed in conjunction -with all other changes before the release as per the release procedure. - -All reviews performed by project-repo are verified by at least two people internally. - -### Developer Certificate of Origin (DCO) - -On any pull requests please include a - -``` -signed-off-by: YOUR IDENTIFIER OR NAME -``` - -DCO statement. - -By doing this you claim that you are legally allowed to contribute the -code and agree to let project-repo publish it under the MIT License. - -#### Development Environment - -CAVEAT: This script works exclusively on Arch Linux, which, as outlined above, -is the development distribution of Cagebreak. - -Cloning the Cagebreak repository and building it is sufficient as a starting point. - -All other dependencies can be installed by invoking - -``` -meson compile devel-install -C build -``` - -if meson is already available or - -``` -./scripts/install-development-environment -``` - -otherwise. - -#### Scripts - -Cagebreak provides a few convenience tools to facilitate development. - -##### Fuzzing - -If your fuzzing corpus is located in the directory `fuzz_corpus` you can -just call: - -``` -meson compile fuzz -C build -``` - -If you want to use a different directory, configure cagebreak with -`-Dcorpus=OTHERDIRECTORY` or call `./scripts/fuzz OTHERDIRECTORY`. - -##### Adjusting Epoch - -To facilitate the creation of reproducible man pages an arbitrary release -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 -a release tag you can call: - -``` -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` -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: - -``` -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 - -``` -meson compile set-ver -C build -``` - -to set the version number in the man pages and README repology minversion. - -Use of the script without meson is discouraged because meson.build is -not touched by the script. - -##### Create Release Artefacts - -The following command generates the release artefacts which must be created -once a release is completely ready to be published (the commit is tagged with -the version of the master branch, etc.): - -``` -meson compile create-artefacts -C build -``` - -Use of the script version is discouraged. - -### 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 -``` - -### Test Suite - -``` -meson test -C build -``` - -invokes all tests. This is required for a release to occur. - -There are four test suites: - - * basic: tests actual outward-facing functionality - * Note optional dependencies for efficient socket interaction - * nc (openbsd-netcat) - * jq - * devel: tests internal properties of the repository - * Note potentially heavier dependencies such as - * shellcheck - * clang-format - * devel-long: applies more costly testing - * Note potentially heavier dependencies such as - * scan-build (static analysis (including security-relevant issues)) - * release: tests release specific considerations - * Note that this is only expected to pass just before - a release. This checks mostly administrative things - to check that a release is ready. - * Note that non-auto tests are files in `release-non-auto-checks` - and have to contain the release version and current date in - YYYY-mm-dd format on seperate lines. This is our imperfect attempt - to guarantee some hard-to-automate checks are carried out before - a release is undertaken. - -Every commit should pass at least the basic and devel suites. - -It is expected that cagebreak passes at least the -basic, devel and devel-long suites when commits are pushed: - -``` -meson test -C build --suite basic --suite devel -``` - -The basic suite can be used to test a binary. This is -useful for PKGBUILDs and their equivalents in other -systems. - -``` -meson test -C build --suite basic -``` - -### Fuzzing - -Along with the project source code, a fuzzing framework based on `libfuzzer` is -supplied. This allows for the testing of the parsing code responsible for reading -the `cagebreak` configuration file. When `libfuzzer` is available (please -use the `clang` compiler to enable it), building the fuzz-testing software can -be enabled by passing `-Dfuzz=true` to meson. This generates a `build/fuzz/fuzz-parse` -binary according to the `libfuzzer` specifications. Further documentation on -how to run this binary can be found [here](https://llvm.org/docs/LibFuzzer.html). - -Here is an example workflow: - -``` -rm -rf build -CC=clang meson setup build -Dfuzz=true -Db_sanitize=address,undefined -Db_lundef=false -ninja -C build/ -mkdir build/fuzz_corpus -cp examples/config build/fuzz_corpus/ -WLR_BACKENDS=headless ./build/fuzz-parse -jobs=12 -max_len=50000 -close_fd_mask=3 build/fuzz_corpus/ -``` - -You may want to tweak `-jobs` or add other options depending on your own setup. -We have found code path discovery to increase rapidly when the fuzzer is supplied -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 -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 -release. - -There are reproducibility issues up to and including release `1.2.0`. See -`Issue 5` in [Bugs.md](Bugs.md). - -#### Reproducible Build Instructions - -All hashes and signatures are provided for the following build instructions. - -``` -meson setup build -Dxwayland=true -Dman-pages=true --buildtype=release -ninja -C build -``` - -#### Hashes for Builds - -For every release after 1.0.5, hashes will be provided. - -For every release after 1.7.0, hashes will be provided for man pages too. - -See [Hashes.md](Hashes.md) - -#### GPG Signatures - -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. - -Due to errors in the release process, the releases 1.7.1 and 1.7.2 did not include the release -signatures in the appropriate folder of the git repository. However, signatures were provided -as release-artefacts at the time of release. The signatures were introduced into the -repository with 1.7.3. The integrity of cagebreak is still the same because the signatures were -provided as release-artefacts (which were themselves signed) and the hashes in Hashes.md -are part of a signed release tag. - -#### Signing Keys - -All releases are signed by at least one of the following collection of -keys. - - * E79F6D9E113529F4B1FFE4D5C4F974D70CEC2C5B - * 4739D329C9187A1C2795C20A02ABFDEC3A40545F - * 7535AB89220A5C15A728B75F74104CC7DCA5D7A8 - * 827BC2320D535AEAD0540E6E2E66F65D99761A6F - * A88D7431E5BAAD0B6EAE550AC8D61D8BD4FA3C46 - * 8F872885968EB8C589A32E9539ACC012896D450F - * 896B92AF738C974E0065BF42F2576BD366156BB9 - * AA927AFD50AF7C6810E69FE8274F2C605359E31B - * BE2DED372287BC4EB2213E13A0C743848A638955 - * 0F3476E4B2404F95EC41600683D5810F7911B020 - * 4E82C72C6B3E58A7BC4FF8554909F84CA83BB867 - * 5AEB1A2EB0D13F67E306AC59DC0CC81BE006FD85 - -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. - -### Versioning & Branching Strategy - -Cagebreak uses [semantic versioning](https://semver.org). - -There are three permanent branches in cagebreak: - - * `master` (for releases) - * `development` (for polishing code between releases) - * `hotfix` (for small emergent releases, usually up-to-date with master) - -Releases are merged to master as per the release procedure, with -reasonable exceptions as the situation requires. - -The release commit is tagged with the release version. - -In the past, our git history did not perfectly reflect this scheme. - -### Release Procedure - -The release procedure outlines the process for a release to occur. - - * [ ] `git checkout development` - * [ ] `git pull origin development` - * [ ] `git push origin development` - * [ ] Arch Build System is up to date - * [ ] `meson test -C build/` just to get an overview - * [ ] Update internal wiki - * [ ] Adjust version number in meson.build - * [ ] `meson compile set-ver -C build` - * [ ] Add new files to meson.build or hardcoded testing variable - * [ ] Commit changes - * [ ] `git push origin development` - * [ ] Complete relevant documentation - * [ ] New features - * [ ] tests added and old test scripts adjusted - * [ ] man pages - * [ ] cagebreak - * [ ] cagebreak-config - * [ ] cagebreak-socket - * [ ] example config - * [ ] FAQ.md - * [ ] Changelog.md for major and minor releases but not patches - * [ ] Check changes for SECURITY.md relevance (changes to socket scope for example) - * [ ] Synchronize any socket changes to cagebreak-socket man page - * [ ] Document fixed bugs in Bugs.md - * [ ] Include issue discussion from github, where applicable - * [ ] `meson compile adjust-epoch -C build` - * [ ] Commit changes - * [ ] `git push origin development` - * [ ] Testing - * [ ] Manual testing - * [ ] `meson compile fuzz -C build` for at least one hour - * [ ] Adjust Hashes.md - Use `meson compile output-hashes -C build` to add Hashes or aid in repro check - * [ ] Commit changes - * [ ] `git push origin development` - * [ ] Complete release-non-auto-checks - * [ ] `meson compile create-sigs -C build` - * [ ] Commit and push signatures, hashes and non-auto-check files - * [ ] `meson test -C build` passes everything except some release tests - * [ ] `git add` relevant files - * [ ] `git commit` - * [ ] `git push origin development` - * [ ] `git checkout master` - * [ ] `git merge --squash development` - * [ ] `git commit` and insert message - * [ ] `meson compile git-tag -C build` - * [ ] `meson compile create-artefacts -C build` - * [ ] `meson test -C build` THIS MUST PASS WITHOUT ANY FAILURES WHATSOEVER - * [ ] `git push --tags origin master` - * [ ] `git checkout development` (merge to development depends on whether release was a hotfix) - * [ ] `git merge master` - * [ ] `git push --tags origin development` - * [ ] `git checkout hotfix` (hotfix is to be kept current with master after releases) - * [ ] `git merge master` - * [ ] `git push --tags origin hotfix` - * [ ] Upload archives and signatures as release assets - * [ ] Delete feature branches if appropriate - * [ ] Manage package release - ## Roadmap Cagebreak plans to do or keep doing the following things @@ -673,20 +185,24 @@ in the future: * React to all issues. * Add or modify features, which the authors find convenient or important. - * Improve the [OpenSSF Best Practices Badge Program](https://bestpractices.coreinfrastructure.org/en) level + * Improve the [OpenSSF Best Practices Badge Program](https://bestpractices.coreinfrastructure.org/en) level. ## Governance Cagebreak is managed by project-repo. +Consider project-repo a single benevolent dictator for life that happens +to occupy at least two brains. + Project-repo is a pseudonym of at least two individuals acting as benevolent dictators for the project by the others mutual consent. The individuals comprising project-repo are not otherwise associated by payment from any organisation or grant. -For all intents and purposes consider project-repo as a single -benevolent dictator for life that happens to occupy at least two brains. +### Governance Issues + +Use [SECURITY.md](SECURITY.md) to contact project-repo. ### Roles @@ -696,37 +212,20 @@ There are no specific roles forced unto anyone. ### Bus Factor +The current bus factor for Cagebreak is: 1 + The Bus Factor is a measure of how many people have to be incapacitated for a project to be unable to continue. -The current bus factor for Cagebreak is: 1 - -Project-repo could still react to issues (even confidential +Project-repo could react to issues (even confidential e-mails) and fix easier issues if any one individual were incapacitated. However, not all aspects of the code or release engineering are fully resilient to the loss of any one individual. -We strive to improve the Bus Factor to at least two in all -aspects of Cagebreak. - -### Governance Issues - -Anyone can use the information in [SECURITY.md](SECURITY.md) to -contact the members of project-repo and bring governance -issues to their attention. - -## Bugs - -For any bug, please [create an issue](https://github.com/project-repo/cagebreak/issues/new) on -[GitHub](https://github.com/project-repo/cagebreak). - -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. - -For other means of contacting the Cagebreak authors and for security issues -see [SECURITY.md](SECURITY.md). +We strive to increase the bus factor to at least 2 in all +aspects. ## Accessibility @@ -739,6 +238,14 @@ see [SECURITY.md](SECURITY.md). would work and cagebreak does not preclude the use of a screen reader for any software run with it. +## Bugs + +[Open an issue](https://github.com/project-repo/cagebreak/issues/new) is you find something. + +See [SECURITY.md](SECURITY.md) for other means of contacting the Cagebreak authors and security issues. + +Fixed bugs are assigned a number and summarized in [Bugs.md](Bugs.md) for future reference. + ## Contributors * Aisha Tammy @@ -747,12 +254,18 @@ see [SECURITY.md](SECURITY.md). * Oliver Friedmann * [Add output scaling](https://github.com/project-repo/cagebreak/pull/34), released in 2.0.0 with slight modifications + * [Fix: calibration matrix](https://github.com/project-repo/cagebreak/pull/49), + released in 2.2.1 with slight modifications * Tom Greig * Fix bug in merge_output_configs in 2.1.2 + * sodface + * Add a screenshot example script in 2.3.0 + * Luca Kennedy (unsigned-enby) + * [Add option to configure the anchor position of messages](https://github.com/project-repo/cagebreak/pull/61) in 2.3.0 ## License -Copyright (c) 2020-2023 The Cagebreak authors +Copyright (c) 2020-2024 The Cagebreak authors Copyright (c) 2018-2020 Jente Hidskes Copyright (c) 2019 The Sway authors diff --git a/SECURITY.md b/SECURITY.md index 2f33197..110d48d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,17 +1,33 @@ # Security -The main possibility for security bugs in cagebreak is by privilege -escalation through the socket. Any program with access to the socket -immediately gains arbitrary code execution rights. The socket -is restricted to the user of the cagebreak process (700) and has to -be explicitely enabled using the `-e` flag on invocation. +The main possibility for security bugs in cagebreak is privilege +escalation via the socket. Any program with access to the socket +immediately gains arbitrary code execution rights. The socket has to +be explicitely enabled using the `-e` flag on invocation and +is restricted to the user of the cagebreak process (700). -If you disagree with this threat model, you may contact us via email (See -section Email Contact below.) or [open an issue on github](https://github.com/project-repo/cagebreak/issues/new). +## Email Contact -Should any problem with the github issue system arise or any other reason -for (potentially confidential) contact with the Cagebreak authors appear, -you may contact us via email (See section Email Contact below.). +If you want to get in touch with project-repo via email, contact +`cagebreak @ project-repo . co`. + +We try to respond to everything that is not obvious spam. + +### GPG-Encrypted Emails + +If you can, please encrypt your email with the appropriate GPG key found +in `keys/` and sign your message with your own key. + +* B15B92642760E11FE002DE168708D42451A94AB5 (expired) +* F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C (expired) +* 3ACEA46CCECD59E4C8222F791CBEB493681E8693 (expired) +* 0A268C188D7949FEB39FD1462F2AD980247E4918 (soon to expire) +* [283D10F54201B0C6CCEE2C561DE04E4B056C749D](keys/cagebreak@project-repo.co.pub) + +Note that our keys are signed by cagebreak signing keys. + +If you want us to respond via GPG-encrypted email, please include your own +public key or provide the fingerprint and directions to obtain the key. ## Supported Versions @@ -24,77 +40,51 @@ Builds are reproducible under conditions outlined in [README.md](README.md). For normal bugs you may [open an issue on github](https://github.com/project-repo/cagebreak/issues/new). For everything else, an email contact (with gpg encryption and signature) -is available below. - -## Email Contact - -If you want to get in touch with the developers of cagebreak to report -a security vulnerability or anything else via email, contact -`cagebreak @ project-repo . co`. - -We try to respond to everything that is not obvious spam. - -### GPG-Encrypted Emails - -If you can, please encrypt your email with the appropriate GPG key found -in `keys/` and sign your message with your own key. - -* B15B92642760E11FE002DE168708D42451A94AB5 -* F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C -* 3ACEA46CCECD59E4C8222F791CBEB493681E8693 -* 0A268C188D7949FEB39FD1462F2AD980247E4918 - -Note that our keys are signed by cagebreak signing keys. - -If you want us to respond via GPG-encrypted email, please include your own -public key or provide the fingerprint and directions to obtain the key. +is available above. ## Threat Model -Cagebreak is a wayland compositor run by the user of the system -and thus has access to whichever resources this user has access to. -Cagebreak can restrict other programs in no way, because this would hamper -usability (consider a web browser unable to write a downloaded file to disk -for instance). +Cagebreak is a wayland compositor run by a user and has access to +the resources the user has access to. +Cagebreak cannot restrict other programs (consider a web browser +unable to write a downloaded file for instance). There is no transmission of information by cagebreak other than to the -screens, ipc and potentially other documented local channels. +screens, ipc (if enabled with `-e`) and potentially other documented local channels. ### STRIDE Threat List This is not a thorough analysis, just an overview of the ways in which cagebreak -has (no) attack surface. Please reference the man pages for details but especially -the -e and --bs options. +has (no) attack surface. Please reference the man pages (especially options -e and --bs ). #### Spoofing -Not applicable - Using Cagebreak already requires a login as a user. +Not applicable - Cagebreak is executed after user login. #### Tampering -Not applicable - Cagebreak must allow system manipulation for user software. +Not applicable - Cagebreak allows system manipulation for user software. #### Repudiation Not applicable - There are no prohibited operations (See Tampering above.). -While cagebreak does send events over documented channels there is no logging -activated by default, though, of course, this can be changed by the user -by logging socket output (if enabled) for example. +Cagebreak sends events over documented channels. There is no logging +activated by default - this can be changed by logging the socket for example. #### Information Disclosure -Not applicable - Information disclosure over documented channels is a feature -and any software run by the user may exfiltrate any data the user has access to. +Not applicable - Information disclosure over documented channels is a feature. +Any user software may exfiltrate any data the user has access to. #### Denial of Service -Not applicable - Cagebreak offers functionality to terminate itself, which is -available to all user software over the socket if the socket is enabled. +Not applicable - Cagebreak offers functionality to terminate itself. This is +available to user software over the socket. #### Elevation of Privilege -Software may gain arbitrary code execution rights if it has access to the -Cagebreak socket. Privilege escalation to root is unlikely since privileges +Software may gain arbitrary code execution if it has access to the +socket. Privilege escalation to root is unlikely since privileges are dropped before any user input is accepted. ## GPG Keys of the Cagebreak Repository diff --git a/cagebreak.c b/cagebreak.c index 4437331..9ce99b8 100644 --- a/cagebreak.c +++ b/cagebreak.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _DEFAULT_SOURCE @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +27,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -279,7 +280,6 @@ main(int argc, char *argv[]) { 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; wl_list_init(&server.input_config); wl_list_init(&server.output_config); @@ -356,6 +356,7 @@ main(int argc, char *argv[]) { server.message_config.display_time = 2; server.message_config.font = strdup("pango:Monospace 10"); + server.message_config.anchor = CG_MESSAGE_TOP_RIGHT; event_loop = wl_display_get_event_loop(server.wl_display); sigint_source = @@ -368,7 +369,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); + backend = wlr_backend_autocreate(server.wl_display, &server.session); + server.headless_backend = wlr_headless_backend_create(server.wl_display); if(!backend) { wlr_log(WLR_ERROR, "Unable to create the wlroots backend"); ret = 1; @@ -428,9 +430,10 @@ main(int argc, char *argv[]) { ret = 1; goto end; } - wlr_scene_attach_output_layout(server.scene, server.output_layout); + server.scene_output_layout = + wlr_scene_attach_output_layout(server.scene, server.output_layout); - compositor = wlr_compositor_create(server.wl_display, server.renderer); + compositor = wlr_compositor_create(server.wl_display, 6, server.renderer); if(!compositor) { wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); ret = 1; @@ -474,14 +477,8 @@ main(int argc, char *argv[]) { 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); + server.idle = wlr_idle_notifier_v1_create(server.wl_display); if(!server.idle_inhibit_v1) { wlr_log(WLR_ERROR, "Cannot create the idle inhibitor"); ret = 1; @@ -568,13 +565,17 @@ main(int argc, char *argv[]) { goto end; } - gamma_control_manager = + server.gamma_control = wlr_gamma_control_manager_v1_create(server.wl_display); - if(!gamma_control_manager) { + if(!server.gamma_control) { wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); ret = 1; goto end; } + server.gamma_control_set_gamma.notify = + handle_output_gamma_control_set_gamma; + wl_signal_add(&server.gamma_control->events.set_gamma, + &server.gamma_control_set_gamma); #if CG_HAS_XWAYLAND server.xwayland = wlr_xwayland_create(server.wl_display, compositor, true); @@ -676,6 +677,8 @@ main(int argc, char *argv[]) { wl_list_init(&server.outputs); struct cg_output *output, *output_tmp; wl_list_for_each_safe(output, output_tmp, &tmp_list, link) { + wl_list_remove(&output->link); + output_insert(&server, output); output_configure(&server, output); } server.curr_output = @@ -687,14 +690,16 @@ main(int argc, char *argv[]) { wl_display_run(server.wl_display); +#if CG_HAS_XWAYLAND + if(server.xwayland != NULL) { + wlr_xwayland_destroy(server.xwayland); + } +#endif + wl_display_destroy_clients(server.wl_display); end: if(server.modes != NULL) { -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-double-free" -#endif for(unsigned int i = 0; server.modes[i] != NULL; ++i) { free(server.modes[i]); } @@ -734,11 +739,6 @@ end: if(server.seat != NULL) { seat_destroy(server.seat); } -#if CG_HAS_XWAYLAND - if(server.xwayland != NULL) { - wlr_xwayland_destroy(server.xwayland); - } -#endif if(sigint_source != NULL) { wl_event_source_remove(sigint_source); @@ -765,6 +765,3 @@ end: return ret; } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif diff --git a/docs/dev-FAQ.md b/docs/dev-FAQ.md new file mode 100644 index 0000000..46c7669 --- /dev/null +++ b/docs/dev-FAQ.md @@ -0,0 +1,67 @@ +# FAQ for Development + +## How is cagebreak adjusted to a new wlroots version? + +There are three steps: + +1. Try to compile Cagebreak with the new wlroots. +2. Fix the compiler errors one-by-one using the wlroots + changelog for reference (https://gitlab.freedesktop.org/wlroots/wlroots/-/releases). +3. Debug until Cagebreak works again. + +## How do I add a new test? + +1. Add a shell script to `test/` +2. Optionally add test configs to `test/testing-configurations/` +3. Make sure the files have shebang, copyright and SPDX License identifiers + (use the other files for reference) +4. Add the test to `meson.build` as in the example below. +5. Add paths and env vars as shown in the other tests +6. Make sure the test is added to the correct suite + (check out CONTRIBUTING.md for details) + +``` +test('Scan-build (static analysis)', find_program('test/scan-build'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel-long') +``` + +## How do I add a new script? + +1. Add a shell script to `scripts/` +2. Make sure the files have shebang, copyright and SPDX License identifiers + (use the other files for reference) +3. Add the script to CONTRIBUTING.md +4. Add the script to meson.build as shown below + +``` +run_target('create-sigs', + command : ['scripts/create-signatures', get_option('gpg_id')]) +``` + +## How do I add an example script? + +Extrapolate from the examples in the `example_scripts` directory. + +The script should be executable standalone. See `test/script-header` for a possible +library. + +License, contributors etc. should be appropriate. + +Shellcheck must pass on any script (use of shellcheck pragmas is allowed but +discouraged). + +## How do I add a new gpg key? + +1. Check which gpg key versions are currently valid. +2. Generate keys with incremented numbers/emails/dates/passphrase. + * Use 4096 Bit RSA Keys +3. Sign the new keys with at least one then-old signing key. +4. Genereate new cagebreak@project-repo.co key +5. Sign the new mail key with the new signing keys. +6. Generate new pkgbuild key. +7. Sign the pkgbuild key with the new signing keys. +8. Add public keys to `keys/`. +9. Update meson_options.txt +10. Update [all man pages](../manuals.md), [CONTRIBUTING](../CONTRIBUTING.md), gpg-validity test & [SECURITY.md](../SECURITY.md) +11. Update the pkgbuild repo with the new key (key and readme). +12. Update git config email. +13. Securely distribute private keys and revocation certificates as per the internal wiki. diff --git a/docs/pull_request_template.md b/docs/pull_request_template.md new file mode 100644 index 0000000..589cd0c --- /dev/null +++ b/docs/pull_request_template.md @@ -0,0 +1,26 @@ +# Description + + + + +## Type of Change + + * [ ] Fix + * [ ] Backwards-compatible Feature + * [ ] Breaking Change + +## Considerations + + + + +## Credit + + * [ ] I want to be credited as YOUR_NAME_OR_PSEUDONYM in your contributor section + * [ ] I don't want to be credited. + + + + +signed-off-by: YOUR_NAME_OR_PSEUDONYM + diff --git a/example_scripts/screenshot_script b/example_scripts/screenshot_script new file mode 100755 index 0000000..59cf524 --- /dev/null +++ b/example_scripts/screenshot_script @@ -0,0 +1,44 @@ +#!/bin/bash +# Copyright 2023 - 2024, project-repo, sodface and the cagebreak contributors +# SPDX-License-Identifier: MIT +# +# Execute this script if you want to take a screenshot. +# Please supply your chosen cropping/editing tool as a +# command-line argument. The filepath to the temporary +# file will be given as an argument to your command. +# +# Example: +# screenshot_script "gwenview" + +named_pipe_send="$(mktemp -u)" +named_pipe_recv="$(mktemp -u)" +mkfifo "${named_pipe_send}" +mkfifo "${named_pipe_recv}" +nc -U "${CAGEBREAK_SOCKET}" < "${named_pipe_send}" > "${named_pipe_recv}"& +# The file descriptor 3 is set up to send commands to cagebreak and file +# descriptor 4 can be used to read events. Notice that events will pile up in +# file descriptor 4, so it is a good idea to continuously read from it or to +# clear it before starting a new transaction. +exec 3>"${named_pipe_send}" +exec 4<"${named_pipe_recv}" +# When the script exits, the os will clean up the pipe +rm "${named_pipe_recv}" +rm "${named_pipe_send}" + +if [[ ${#} -lt 1 ]] +then + echo "Expected a single command line argument specifying the command to edit the screenshot." + exit 1 +fi + +edit_cmd="${1}" + +echo "dump" >&3 +IFS= read -r -d $'\0' event <&4 + +co="$(echo "${event:6}"|jq -r ".curr_output")" +tmpfile="$(mktemp)" +grim -t png -o "${co}" "${tmpfile}" +bash -c "${edit_cmd} \"${tmpfile}\"" +wl-copy < "${tmpfile}" +rm "${tmpfile}" diff --git a/example_scripts/show_workspace_views.sh b/example_scripts/show_workspace_views old mode 100644 new mode 100755 similarity index 54% rename from example_scripts/show_workspace_views.sh rename to example_scripts/show_workspace_views index be6f0f9..33d76bc --- a/example_scripts/show_workspace_views.sh +++ b/example_scripts/show_workspace_views @@ -1,11 +1,23 @@ #!/bin/bash -# Copyright 2020 - 2023, project-repo and the cagebreak contributors +# Copyright 2020 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT - +# # This script displays the process names of the views on the current workspace. -# Start up the ipc link -source "$(dirname "${BASH_SOURCE[0]}")/cb_script_header.sh" +named_pipe_send="$(mktemp -u)" +named_pipe_recv="$(mktemp -u)" +mkfifo "${named_pipe_send}" +mkfifo "${named_pipe_recv}" +nc -U "${CAGEBREAK_SOCKET}" < "${named_pipe_send}" > "${named_pipe_recv}"& +# The file descriptor 3 is set up to send commands to cagebreak and file +# descriptor 4 can be used to read events. Notice that events will pile up in +# file descriptor 4, so it is a good idea to continuously read from it or to +# clear it before starting a new transaction. +exec 3>"${named_pipe_send}" +exec 4<"${named_pipe_recv}" +# When the script exits, the os will clean up the pipe +rm "${named_pipe_recv}" +rm "${named_pipe_send}" echo "dump" >&3 diff --git a/examples/config b/examples/config index 6708e42..b0883cb 100644 --- a/examples/config +++ b/examples/config @@ -1,8 +1,7 @@ -# Copyright 2020 - 2023, project-repo and the cagebreak contributors +# Copyright 2020 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT -###################### -# General settings an key bindings -###################### + +# General settings and key bindings exec xterm @@ -36,19 +35,21 @@ bind k focusup bind l focusright bind t exec xterm bind C-k close -#bind m message Hello World! +# bind m message Hello World! definekey resize h resizeleft definekey resize l resizeright definekey resize j resizedown definekey resize k resizeup definekey resize Escape setmode top -#unhide cursor (default) +# unhide cursor (default) cursor enable -###################### -#Workspaces -###################### +# send a custom event over the socket +# custom_event Hello World! + +## Workspaces + bind 1 screen 1 bind 2 screen 2 bind 3 screen 3 @@ -84,28 +85,33 @@ definekey top XF86_Switch_VT_4 switchvt 4 definekey top XF86_Switch_VT_5 switchvt 5 definekey top XF86_Switch_VT_6 switchvt 6 -###################### -#Bind Function keys -###################### +## Bind Function keys + definekey top XF86AudioMute exec pactl set-sink-mute 0 toggle definekey top XF86AudioLowerVolume exec pactl set-sink-mute 0 off&&amixer set Master 1%- definekey top XF86AudioRaiseVolume exec pactl set-sink-mute 0 off&&amixer set Master 1%+ definekey top XF86MonBrightnessDown exec xbacklight -dec 1 definekey top XF86MonBrightnessUp exec xbacklight -inc 1 -###################### -#Output configuration -###################### -#output eDP-1 pos 0 0 res 1366x768 rate 60 -#output eDP-1 disable -#output eDP-1 enable -#output eDP-1 prio 1 -#output eDP-2 pos 0 0 res 1366x768 rate 60 scale 2.0 +## Output configuration -##################### -#Input configuration -##################### +# output eDP-1 pos 0 0 res 1366x768 rate 60 +output eDP-1 disable +output eDP-1 enable +output eDP-1 permanent -#input 1234:0:Device_Ident click_method clickfinger -#input type:pointer scroll_method two_finger -#input * calibration_matrix 1 2 3 4 5 6 +output eDP-1 peripheral +# output eDP-1 prio 1 +# output eDP-2 pos 0 0 res 1366x768 rate 60 scale 2.0 + + +## Input configuration + +# input 1234:0:Device_Ident click_method clickfinger +# input type:pointer scroll_method two_finger +# input * calibration_matrix 1 2 3 4 5 6 + +## Message configuration + +# configure_message display_time 1 +# configure_message anchor top_center diff --git a/fuzz/execl_override.c b/fuzz/execl_override.c index 275d4f0..0f9a19f 100644 --- a/fuzz/execl_override.c +++ b/fuzz/execl_override.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT // This file is used by the fuzzer in order to prevent executing shell commands. diff --git a/fuzz/fuzz-lib.c b/fuzz/fuzz-lib.c index d331880..2d46e50 100644 --- a/fuzz/fuzz-lib.c +++ b/fuzz/fuzz-lib.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200812L @@ -25,10 +25,9 @@ #include #include #include -#include #include +#include #include -#include #include #include #include @@ -271,9 +270,10 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { ret = 1; goto end; } - wlr_scene_attach_output_layout(server.scene, server.output_layout); + server.scene_output_layout = + wlr_scene_attach_output_layout(server.scene, server.output_layout); - compositor = wlr_compositor_create(server.wl_display, server.renderer); + compositor = wlr_compositor_create(server.wl_display, 6, server.renderer); if(!compositor) { wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); ret = 1; @@ -310,7 +310,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) { goto end; } - server.idle = wlr_idle_create(server.wl_display); + server.idle = wlr_idle_notifier_v1_create(server.wl_display); if(!server.idle) { wlr_log(WLR_ERROR, "Unable to create the idle tracker"); ret = 1; diff --git a/fuzz/fuzz-lib.h b/fuzz/fuzz-lib.h index 46aefd2..2715978 100644 --- a/fuzz/fuzz-lib.h +++ b/fuzz/fuzz-lib.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_FUZZ_LIB_H diff --git a/fuzz/fuzz-parse.c b/fuzz/fuzz-parse.c index d0bd5ab..9c35010 100644 --- a/fuzz/fuzz-parse.c +++ b/fuzz/fuzz-parse.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200812L diff --git a/idle_inhibit_v1.c b/idle_inhibit_v1.c index b4f91f9..bc76ff7 100644 --- a/idle_inhibit_v1.c +++ b/idle_inhibit_v1.c @@ -1,9 +1,9 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include -#include #include +#include #include "idle_inhibit_v1.h" #include "server.h" @@ -15,20 +15,13 @@ struct cg_idle_inhibitor_v1 { struct wl_listener destroy; }; -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif static void idle_inhibit_v1_check_active(struct cg_server *server) { /* As of right now, this does not check whether the inhibitor * is visible or not.*/ bool inhibited = !wl_list_empty(&server->inhibitors); - wlr_idle_set_enabled(server->idle, NULL, !inhibited); + wlr_idle_notifier_v1_set_inhibited(server->idle, inhibited); } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif static void handle_destroy(struct wl_listener *listener, void *data) { diff --git a/idle_inhibit_v1.h b/idle_inhibit_v1.h index 74ae956..dc712bf 100644 --- a/idle_inhibit_v1.h +++ b/idle_inhibit_v1.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_IDLE_INHIBIT_H #define CG_IDLE_INHIBIT_H diff --git a/img/archwiki.svg b/img/archwiki.svg new file mode 100644 index 0000000..635b400 --- /dev/null +++ b/img/archwiki.svg @@ -0,0 +1 @@ + : Wiki \ No newline at end of file diff --git a/img/aur.svg b/img/aur.svg new file mode 100644 index 0000000..c8af6f3 --- /dev/null +++ b/img/aur.svg @@ -0,0 +1 @@ + : AUR \ No newline at end of file diff --git a/img/contributing.svg b/img/contributing.svg new file mode 100644 index 0000000..6d58a85 --- /dev/null +++ b/img/contributing.svg @@ -0,0 +1 @@ + : Contrib \ No newline at end of file diff --git a/img/faq.svg b/img/faq.svg new file mode 100644 index 0000000..41bfdfe --- /dev/null +++ b/img/faq.svg @@ -0,0 +1 @@ + : FAQ \ No newline at end of file diff --git a/img/mail.svg b/img/mail.svg new file mode 100644 index 0000000..78cfd12 --- /dev/null +++ b/img/mail.svg @@ -0,0 +1 @@ + : Mail \ No newline at end of file diff --git a/img/manuals.svg b/img/manuals.svg new file mode 100644 index 0000000..8aebe59 --- /dev/null +++ b/img/manuals.svg @@ -0,0 +1 @@ + : Manuals \ No newline at end of file diff --git a/img/web-artefacts.svg b/img/web-artefacts.svg new file mode 100644 index 0000000..00072e8 --- /dev/null +++ b/img/web-artefacts.svg @@ -0,0 +1 @@ + : Mirror \ No newline at end of file diff --git a/img/web-open-issue.svg b/img/web-open-issue.svg new file mode 100644 index 0000000..8c2de01 --- /dev/null +++ b/img/web-open-issue.svg @@ -0,0 +1 @@ + : + Issue \ No newline at end of file diff --git a/input.h b/input.h index f45e735..358c385 100644 --- a/input.h +++ b/input.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef _CG_INPUT_H diff --git a/input_manager.c b/input_manager.c index cfde2c9..47ce206 100644 --- a/input_manager.c +++ b/input_manager.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200812L @@ -229,6 +229,11 @@ input_manager_merge_input_configs(struct cg_input_config *cfg1, } else { out_cfg->repeat_rate = cfg1->repeat_rate; } + if(cfg1->calibration_matrix.configured == false) { + out_cfg->calibration_matrix = cfg2->calibration_matrix; + } else { + out_cfg->calibration_matrix = cfg1->calibration_matrix; + } return out_cfg; } diff --git a/input_manager.h b/input_manager.h index b3eb006..eb6f019 100644 --- a/input_manager.h +++ b/input_manager.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_INPUT_MANAGER_H diff --git a/ipc_server.c b/ipc_server.c index ced183a..37e59ad 100644 --- a/ipc_server.c +++ b/ipc_server.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _DEFAULT_SOURCE @@ -127,10 +127,6 @@ ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { return 0; } - if(client->write_buffer_len <= 0) { - return 0; - } - if(fcntl(client->fd, F_GETFD) == -1) { return 0; } diff --git a/ipc_server.h b/ipc_server.h index 41d7b88..a8ae3ef 100644 --- a/ipc_server.h +++ b/ipc_server.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_IPC_SERVER_H diff --git a/keybinding.c b/keybinding.c index 44ccffb..9878a58 100644 --- a/keybinding.c +++ b/keybinding.c @@ -1,8 +1,9 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L +#include #include #include #include @@ -11,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -91,11 +91,18 @@ keybinding_free(struct keybinding *keybinding, bool recursive) { if(keybinding->data.m_cfg->font != NULL) { free(keybinding->data.m_cfg->font); } + free(keybinding->data.m_cfg); break; case KEYBINDING_DISPLAY_MESSAGE: if(keybinding->data.c != NULL) { free(keybinding->data.c); } + break; + case KEYBINDING_SEND_CUSTOM_EVENT: + if(keybinding->data.c != NULL) { + free(keybinding->data.c); + } + break; default: break; } @@ -243,8 +250,7 @@ swap_tile(struct cg_tile *tile, "{\"event_name\":\"swap_tile\",\"tile_id\":%d,\"swap_" "tile_id\":%d,\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", tile->id, swap_tile->id, tile->workspace->num + 1, - tile->workspace->output->wlr_output->name, - output_get_num(tile->workspace->output)); + tile->workspace->output->name, output_get_num(tile->workspace->output)); } void @@ -394,8 +400,7 @@ resize(struct cg_tile *tile, const struct cg_tile *parent, int coord_offset, "\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", tile->id, old_x, old_y, old_height, old_width, tile->tile.x, tile->tile.y, tile->tile.height, tile->tile.width, - tile->workspace->num + 1, - tile->workspace->output->wlr_output->name, + tile->workspace->num + 1, tile->workspace->output->name, output_get_num(tile->workspace->output)); } @@ -450,18 +455,18 @@ resize_vertical(struct cg_tile *tile, struct cg_tile *parent, int y_offset, void resize_tile(struct cg_server *server, int hpixs, int vpixs) { struct cg_output *output = server->curr_output; - struct wlr_box output_box; - wlr_output_layout_get_box(output->server->output_layout, output->wlr_output, - &output_box); struct cg_tile *focused = output->workspaces[output->curr_workspace]->focused_tile; /* First do the horizontal adjustment */ - if(hpixs != 0 && focused->tile.width < output_box.width && - is_between_strict(0, output_box.width, focused->tile.width + hpixs)) { + if(hpixs != 0 && + focused->tile.width < output_get_layout_box(output).width && + is_between_strict(0, output_get_layout_box(output).width, + focused->tile.width + hpixs)) { int x_offset = 0; /* In case we are on the total right, move the left edge of the tile */ - if(focused->tile.x + focused->tile.width == output_box.width) { + if(focused->tile.x + focused->tile.width == + output_get_layout_box(output).width) { x_offset = -hpixs; } bool resize_allowed = @@ -471,10 +476,13 @@ resize_tile(struct cg_server *server, int hpixs, int vpixs) { } } /* Repeat for vertical */ - if(vpixs != 0 && focused->tile.height < output_box.height && - is_between_strict(0, output_box.height, focused->tile.height + vpixs)) { + if(vpixs != 0 && + focused->tile.height < output_get_layout_box(output).height && + is_between_strict(0, output_get_layout_box(output).height, + focused->tile.height + vpixs)) { int y_offset = 0; - if(focused->tile.y + focused->tile.height == output_box.height) { + if(focused->tile.y + focused->tile.height == + output_get_layout_box(output).height) { y_offset = -vpixs; } bool resize_allowed = @@ -495,16 +503,15 @@ keybinding_workspace_fullscreen(struct cg_server *server) { "\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", output->workspaces[output->curr_workspace]->focused_tile->id, output->workspaces[output->curr_workspace]->num + 1, - output->wlr_output->name, output_get_num(output)); + output->name, output_get_num(output)); } // Switch to a differerent virtual terminal static int -keybinding_switch_vt(struct wlr_backend *backend, unsigned int vt) { - if(wlr_backend_is_multi(backend)) { - struct wlr_session *session = wlr_backend_get_session(backend); - if(session) { - wlr_session_change_vt(session, vt); +keybinding_switch_vt(struct cg_server *server, unsigned int vt) { + if(wlr_backend_is_multi(server->backend)) { + if(server->session) { + wlr_session_change_vt(server->session, vt); } return 0; } @@ -589,8 +596,8 @@ keybinding_split_output(struct cg_output *output, bool vertical) { "{\"event_name\":\"split\",\"tile_id\":%d,\"new_tile_id\":%d," "\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d,\"vertical\":%d}", curr_workspace->focused_tile->id, new_tile->id, curr_workspace->num + 1, - curr_workspace->output->wlr_output->name, - output_get_num(curr_workspace->output), vertical); + curr_workspace->output->name, output_get_num(curr_workspace->output), + vertical); } static void @@ -608,8 +615,7 @@ keybinding_close_view(struct cg_view *view) { outp->server, "{\"event_name\":\"close\",\"view_id\":%d,\"view_pid\":%d,\"tile_id\":" "%d,\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", - view_id, view_pid, tile_id, ws + 1, outp->wlr_output->name, - output_get_num(outp)); + view_id, view_pid, tile_id, ws + 1, outp->name, output_get_num(outp)); } static void @@ -624,7 +630,7 @@ keybinding_split_horizontal(struct cg_server *server) { static void into_process(const char *command) { - execl("/bin/sh", "sh", "-c", command, (char *)NULL); + execlp("sh", "sh", "-c", command, (char *)NULL); _exit(1); } @@ -664,8 +670,8 @@ keybinding_cycle_outputs(struct cg_server *server, bool reverse, "{\"event_name\":\"cycle_outputs\",\"old_output\":\"%s\",\"old_" "output_id\":%d," "\"new_output\":\"%s\",\"new_output_id\":%d,\"reverse\":%d}", - old_output->wlr_output->name, output_get_num(old_output), - output->wlr_output->name, output_get_num(output), reverse); + old_output->name, output_get_num(old_output), output->name, + output_get_num(output), reverse); } } @@ -715,7 +721,7 @@ keybinding_cycle_views(struct cg_server *server, bool reverse, bool ipc) { curr_id, curr_pid, next_view == NULL ? -1 : (int)next_view->id, next_view == NULL ? -1 : (int)next_view->impl->get_pid(next_view), next_view->tile->id, curr_workspace->num + 1, - curr_workspace->output->wlr_output->name, + curr_workspace->output->name, output_get_num(curr_workspace->output)); } } @@ -738,7 +744,7 @@ keybinding_focus_tile(struct cg_server *server, uint32_t tile_id) { "{\"event_name\":\"focus_tile\",\"old_tile_id\":%d,\"new_tile_" "id\":%d,\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", old_tile->id, workspace->focused_tile->id, workspace->num + 1, - output->wlr_output->name, output_get_num(output)); + output->name, output_get_num(output)); break; } } @@ -772,8 +778,7 @@ keybinding_switch_ws(struct cg_server *server, uint32_t ws) { ipc_send_event(output->server, "{\"event_name\":\"switch_ws\",\"old_workspace\":%d," "\"new_workspace\":%d,\"output\":\"%s\",\"output_id\":%d}", - old_ws + 1, ws + 1, output->wlr_output->name, - output_get_num(output)); + old_ws + 1, ws + 1, output->name, output_get_num(output)); return 0; } @@ -830,6 +835,50 @@ print_str(struct dyn_str *outp, const char *fmt, ...) { return 0; } +char * +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; + outp_str.str_arr = calloc(nmemb, sizeof(char *)); + print_str(&outp_str, "\"message_config\": {"); + print_str(&outp_str, "\"font\": \"%s\",\n", config->font); + print_str(&outp_str, "\"display_time\": %d,\n", config->display_time); + print_str(&outp_str, "\"bg_color\": [%f,%f,%f,%f],\n", config->bg_color[0], + 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]); + switch(config->anchor) { + case CG_MESSAGE_TOP_LEFT: + print_str(&outp_str, "\"anchor\": \"top_left\"\n", config->font); + break; + case CG_MESSAGE_TOP_CENTER: + print_str(&outp_str, "\"anchor\": \"top_center\"\n", config->font); + break; + case CG_MESSAGE_TOP_RIGHT: + print_str(&outp_str, "\"anchor\": \"top_right\"\n", config->font); + break; + case CG_MESSAGE_BOTTOM_LEFT: + print_str(&outp_str, "\"anchor\": \"bottom_left\"\n", config->font); + break; + case CG_MESSAGE_BOTTOM_CENTER: + print_str(&outp_str, "\"anchor\": \"bottom_center\"\n", config->font); + break; + case CG_MESSAGE_BOTTOM_RIGHT: + print_str(&outp_str, "\"anchor\": \"bottom_right\"\n", config->font); + break; + case CG_MESSAGE_CENTER: + print_str(&outp_str, "\"anchor\": \"center\"\n", config->font); + break; + case CG_MESSAGE_NOPT: // This should actually never occur + print_str(&outp_str, "\"anchor\": \"no_op\"\n", config->font); + break; + } + print_str(&outp_str, "}"); + return dyn_str_to_str(&outp_str); +} + void print_modes(struct dyn_str *str, char **modes) { uint32_t len = 0; @@ -1013,19 +1062,19 @@ print_output(struct cg_output *outp) { struct dyn_str outp_str; outp_str.len = 0; outp_str.cur_pos = 0; - uint32_t nmemb = 8; - struct wlr_box outp_box; - wlr_output_layout_get_box(outp->server->output_layout, outp->wlr_output, - &outp_box); + uint32_t nmemb = 10; outp_str.str_arr = calloc(nmemb, sizeof(char *)); - print_str(&outp_str, "\"%s\": {\n", outp->wlr_output->name); + print_str(&outp_str, "\"%s\": {\n", outp->name); print_str(&outp_str, "\"priority\": %d,\n", outp->priority); - print_str(&outp_str, "\"coords\": {\"x\":%d,\"y\":%d},\n", outp_box.x, - outp_box.y); + print_str(&outp_str, "\"coords\": {\"x\":%d,\"y\":%d},\n", + output_get_layout_box(outp).x, output_get_layout_box(outp).y); print_str(&outp_str, "\"size\": {\"width\":%d,\"height\":%d},\n", outp->wlr_output->width, outp->wlr_output->height); print_str(&outp_str, "\"refresh_rate\": %f,\n", (float)outp->wlr_output->refresh / 1000.0); + print_str(&outp_str, "\"permanent\": %d,\n", + outp->role == OUTPUT_ROLE_PERMANENT); + print_str(&outp_str, "\"active\": %d,\n", !outp->destroyed); print_str(&outp_str, "\"curr_workspace\": %d,\n", outp->curr_workspace + 1); char *workspaces_str = print_workspaces(outp); if(workspaces_str != NULL) { @@ -1179,7 +1228,7 @@ keybinding_dump(struct cg_server *server) { struct dyn_str str; str.len = 0; str.cur_pos = 0; - uint32_t nmemb = 13; + uint32_t nmemb = 14; str.str_arr = calloc(nmemb, sizeof(char *)); print_str(&str, "{\"event_name\":\"dump\","); @@ -1196,11 +1245,15 @@ keybinding_dump(struct cg_server *server) { } print_str(&str, "\"views_curr_id\":%d,\n", curr_view_id); print_str(&str, "\"tiles_curr_id\":%d,\n", curr_tile_id); - print_str(&str, "\"curr_output\":\"%s\",\n", - server->curr_output->wlr_output->name); + print_str(&str, "\"curr_output\":\"%s\",\n", server->curr_output->name); print_str(&str, "\"default_mode\":\"%s\",\n", get_mode_name(server->modes, server->seat->default_mode)); print_modes(&str, server->modes); + char *message_string = print_message_conf(&server->message_config); + if(message_string != NULL) { + print_str(&str, "%s,", message_string); + free(message_string); + } char *outps_str = print_outputs(server); if(outps_str != NULL) { print_str(&str, "%s,", outps_str); @@ -1245,6 +1298,12 @@ keybinding_display_message(struct cg_server *server, char *msg) { message_printf(server->curr_output, "%s", msg); } +void +keybinding_send_custom_event(struct cg_server *server, char *msg) { + ipc_send_event(server, + "{\"event_name\":\"custom_event\",\"message\":\"%s\"}", msg); +} + void keybinding_move_view_to_cycle_output(struct cg_server *server, bool reverse) { if(wl_list_length(&server->outputs) <= 1) { @@ -1286,9 +1345,8 @@ keybinding_move_view_to_cycle_output(struct cg_server *server, bool reverse) { "{\"event_name\":\"move_view_to_cycle_output\",\"view_id\":%d,\"view_" "pid\":%d,\"old_output\":\"%s\",\"old_output_id\":%d,\"new_output\":\"%" "s\",\"new_output_id\":%d,\"old_tile_id\":%d,\"new_tile_id\":%d}", - id, pid, old_outp->wlr_output->name, output_get_num(old_outp), - server->curr_output->wlr_output->name, - output_get_num(server->curr_output), + id, pid, old_outp->name, output_get_num(old_outp), + server->curr_output->name, output_get_num(server->curr_output), old_outp->workspaces[old_outp->curr_workspace]->focused_tile->id, server->curr_output->workspaces[server->curr_output->curr_workspace] ->focused_tile->id); @@ -1410,8 +1468,8 @@ keybinding_switch_output(struct cg_server *server, int output) { "{\"event_name\":\"switch_output\",\"old_output\":" "\"%s\",\"old_output_id\":%d,\"new_output\":\"%s\"," "\"new_output_id\":%d}", - old_outp->wlr_output->name, output_get_num(old_outp), - it->wlr_output->name, output_get_num(it)); + old_outp->name, output_get_num(old_outp), it->name, + output_get_num(it)); return; } ++count; @@ -1457,8 +1515,7 @@ keybinding_move_view_to_output(struct cg_server *server, int output_num) { server, "{\"event_name\":\"move_view_to_output\",\"view_id\":%d,\"old_" "output\":\"%s\",\"new_output\":\"%s\"}", - view_id, old_outp->wlr_output->name, - server->curr_output->wlr_output->name); + view_id, old_outp->name, server->curr_output->name); } void @@ -1493,7 +1550,7 @@ keybinding_move_view_to_workspace(struct cg_server *server, uint32_t ws) { "\"old_workspace\":%d,\"new_workspace\":%d," "\"output\":\"%s\",\"output_id\":%d,\"view_pid\":%d}", view == NULL ? -1 : (int)view->id, old_ws + 1, ws + 1, - server->curr_output->wlr_output->name, + server->curr_output->name, output_get_num(server->curr_output), view == NULL ? 0 : view->impl->get_pid(view)); } @@ -1542,17 +1599,18 @@ keybinding_configure_output(struct cg_server *server, struct cg_output *output, *tmp_output; wl_list_for_each_safe(output, tmp_output, &server->outputs, link) { - if(strcmp(config->output_name, output->wlr_output->name) == 0) { + if(strcmp(config->output_name, output->name) == 0) { + int output_num = output_get_num(output); output_configure(server, output); - ipc_send_event(output->server, + ipc_send_event(server, "{\"event_name\":\"configure_output\",\"output\":\"%" "s\",\"output_id\":%d}", - cfg->output_name, output_get_num(output)); + cfg->output_name, output_num); return; } } wl_list_for_each_safe(output, tmp_output, &server->disabled_outputs, link) { - if(strcmp(config->output_name, output->wlr_output->name) == 0) { + if(strcmp(config->output_name, output->name) == 0) { output_configure(server, output); ipc_send_event( output->server, @@ -1608,6 +1666,9 @@ keybinding_configure_message(struct cg_server *server, server->message_config.fg_color[2] = config->fg_color[2]; server->message_config.fg_color[3] = config->fg_color[3]; } + if(config->anchor != CG_MESSAGE_NOPT) { + server->message_config.anchor = config->anchor; + } ipc_send_event(server, "{\"event_name\":\"configure_message\"}"); } @@ -1615,11 +1676,11 @@ void set_cursor(bool enabled, struct cg_seat *seat) { if(enabled == true) { seat->enable_cursor = true; - wlr_xcursor_manager_set_cursor_image(seat->xcursor_manager, - DEFAULT_XCURSOR, seat->cursor); + wlr_cursor_set_xcursor(seat->cursor, seat->xcursor_manager, + DEFAULT_XCURSOR); } else { seat->enable_cursor = false; - wlr_cursor_set_image(seat->cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_unset_image(seat->cursor); } } @@ -1633,7 +1694,7 @@ run_action(enum keybinding_action action, struct cg_server *server, server->running = false; break; case KEYBINDING_CHANGE_TTY: - return keybinding_switch_vt(server->backend, data.u); + return keybinding_switch_vt(server, data.u); case KEYBINDING_CURSOR: set_cursor(data.i, server->seat); break; @@ -1649,6 +1710,10 @@ run_action(enum keybinding_action action, struct cg_server *server, case KEYBINDING_RUN_COMMAND: { int pid; if((pid = fork()) == 0) { + setsid(); + sigset_t set; + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); if(fork() == 0) { into_process(data.c); } @@ -1676,9 +1741,9 @@ run_action(enum keybinding_action action, struct cg_server *server, if(data.u != server->seat->default_mode) { wlr_seat_pointer_notify_clear_focus(server->seat->seat); if(server->seat->enable_cursor == true) { - wlr_xcursor_manager_set_cursor_image( - server->seat->xcursor_manager, "dot_box_mask", - server->seat->cursor); + wlr_cursor_set_xcursor(server->seat->cursor, + server->seat->xcursor_manager, + "dot_box_mask"); } } server->seat->mode = data.u; @@ -1706,6 +1771,9 @@ run_action(enum keybinding_action action, struct cg_server *server, case KEYBINDING_DISPLAY_MESSAGE: keybinding_display_message(server, data.c); break; + case KEYBINDING_SEND_CUSTOM_EVENT: + keybinding_send_custom_event(server, data.c); + break; case KEYBINDING_RESIZE_TILE_HORIZONTAL: resize_tile(server, data.i, 0); break; diff --git a/keybinding.h b/keybinding.h index 6d6cf87..fca1271 100644 --- a/keybinding.h +++ b/keybinding.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef KEYBINDING_H @@ -63,6 +63,7 @@ struct cg_server; KEYBINDING(KEYBINDING_SHOW_TIME, time) \ KEYBINDING(KEYBINDING_SHOW_INFO, show_info) \ KEYBINDING(KEYBINDING_DISPLAY_MESSAGE, message) \ + KEYBINDING(KEYBINDING_SEND_CUSTOM_EVENT, custom_event) \ KEYBINDING(KEYBINDING_CURSOR, cursor) \ \ KEYBINDING(KEYBINDING_SWAP_LEFT, exchangeleft) \ diff --git a/keys/cagebreak@project-repo.co.pub b/keys/cagebreak@project-repo.co.pub index 648618b..4ef3235 100644 --- a/keys/cagebreak@project-repo.co.pub +++ b/keys/cagebreak@project-repo.co.pub @@ -1,87 +1,76 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -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 -=bl5A +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 +6arp +=AorA -----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak@project-repo.co.pub-legacy-4 b/keys/cagebreak@project-repo.co.pub-legacy-4 new file mode 100644 index 0000000..648618b --- /dev/null +++ b/keys/cagebreak@project-repo.co.pub-legacy-4 @@ -0,0 +1,87 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=bl5A +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_13@project-repo.co.pub b/keys/cagebreak_signing_key_13@project-repo.co.pub new file mode 100644 index 0000000..7c8a376 --- /dev/null +++ b/keys/cagebreak_signing_key_13@project-repo.co.pub @@ -0,0 +1,76 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +XPUssBeVi6uNhWON/EjKc0cLAfNwuBrjj6I= +=5Ie4 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/keys/cagebreak_signing_key_14@project-repo.co.pub b/keys/cagebreak_signing_key_14@project-repo.co.pub new file mode 100644 index 0000000..974001d --- /dev/null +++ b/keys/cagebreak_signing_key_14@project-repo.co.pub @@ -0,0 +1,76 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +2rpj+N0DJVi3/r0GWYgBEzvO+yV1ly011sk= +=AVO4 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/libinput.c b/libinput.c index e980060..b6244aa 100644 --- a/libinput.c +++ b/libinput.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include "input.h" @@ -219,7 +219,7 @@ output_by_name_or_id(const char *name_or_id, struct cg_server *server) { char identifier[128]; output_get_identifier(identifier, sizeof(identifier), output); if(strcasecmp(identifier, name_or_id) == 0 || - strcasecmp(output->wlr_output->name, name_or_id) == 0) { + strcasecmp(output->name, name_or_id) == 0) { return output; } } diff --git a/man/cagebreak-config.5.md b/man/cagebreak-config.5.md index b9632dd..7c18c9a 100644 --- a/man/cagebreak-config.5.md +++ b/man/cagebreak-config.5.md @@ -1,8 +1,8 @@ -cagebreak-config(5) "Version 2.1.2" "Cagebreak Manual" +cagebreak-config(5) "Version 2.3.1" "Cagebreak Manual" # NAME -*cagebreak-config* — Cagebreak configuration file +*cagebreak-config* Cagebreak configuration file # SYNOPSIS @@ -17,9 +17,8 @@ are parsed sequentially but independently from the rest of the file. Each line starting with a "#" is a comment. -Note that nesting of commands is limited to 50 times, though lines -are arbitrarily long in practice, though a reasonable limit of 4Mb has -been set. +Note that nesting of commands is limited to 50 times. +Lines are arbitrarily long in practice, though a reasonable limit of 4Mb has been set. See *KEY DEFINITIONS* for details on modifier keys and *MODES* for details on modes. @@ -29,8 +28,8 @@ on modes. *abort* Return to default mode -*background * - Set RGB of background - <[r|g|b]> are floating point numbers +*background * + Set RGB of background - <[r|g|b]\> are floating point numbers between 0 and 1. There is no support for background images. @@ -39,8 +38,8 @@ on modes. background 1.0 0.0 0.0 ``` -*bind * - Bind to execute if pressed in root mode +*bind * + Bind to execute if pressed in root mode ``` bind @@ -52,15 +51,17 @@ definekey root Close current window - This may be useful for windows of applications which do not offer any method of closing them. -*configure_message [font |[f|b]g_color b> |display_time ]* +*configure_message [font |[f|b]g_color |display_time |anchor ]* Configure message characteristics - - - font sets - - is - - X core font description or - - FreeType font description via pango - - fg_color sets RGBA of foreground - - bg_color sets RGBA of background - - display_time sets display time in seconds + - font sets the font of the message. + Here, is either + - an X core font description or + - a FreeType font description via pango + - fg_color sets the RGBA of the foreground + - bg_color sets the RGBA of the background + - display_time sets the display time in seconds + - anchor sets the position of the message. + may be one of {top,bottom}\_{left,center,right} or center. ``` # Set font @@ -81,16 +82,24 @@ configure_message display_time 4 *cursor [enable|disable]* Enable or disable cursor + This simply hides the cursor. Pointing and clicking is still possible. -*definekey * - Bind to execute if pressed in - +*custom_event * + Send a custom event to the IPC socket + + This sends an event of type "custom_event" to all programs + listening to the IPC socket along with the string . + See *cagebreak-socket(7)* for more details. + +*definekey * + Bind to execute if pressed in - *definekey* is a more general version of *bind*. -*definemode * - Define new mode - After a call to *definemode*, - can be used with *definekey* to create a custom key mapping. +*definemode * + Define new mode - After a call to *definemode*, + can be used with *definekey* to create a custom key mapping. ``` # define new mode and create a mapping for it @@ -101,8 +110,8 @@ definekey foo C-t abort *dump* Triggers the *dump* event, see *cagebreak-socket(7)* for details -*escape * - Set to switch to root mode to execute one command +*escape * + Set to switch to root mode to execute one command ``` escape @@ -122,8 +131,8 @@ definekey top mode root *exchangeup* Exchange current window with window in the tile to the top -*exec * - Execute using *sh -c* +*exec * + Execute using *sh -c* *focus* Focus next tile @@ -146,10 +155,10 @@ definekey top mode root *hsplit* Split current tile horizontally -*input * - Set to for device - - can be "\*" (wildcard), of the form - "type:" or the identifier of the device as printed +*input * + Set to for device - + can be "\*" (wildcard), of the form + "type:" or the identifier of the device as printed for example by *cagebreak -s*. The supported input types are - touchpad - pointer @@ -166,7 +175,7 @@ definekey top mode root *accel_profile adaptive|flat* Set pointer acceleration profile for specified input device - *calibration_matrix <6 space-separated floating point values>* + *calibration_matrix <6 space-separated floating point values\>* Set calibration matrix *click_method none|button_areas|clickfinger* @@ -199,26 +208,26 @@ definekey top mode root Enable or disable natural (inverted) scrolling for specified input device - *pointer_accel [<-1|1>]* + *pointer_accel [<-1|1\>]* Change the pointer acceleration for specified input device - *scroll_button disable|* + *scroll_button disable|* Set button used for scroll_method on_button_down - The button can be given as an event name or code, which can be obtained from *libinput debug-events*. If set to _disable_, it disables the scroll_method on_button_down. - *scroll_factor * + *scroll_factor * Change the scroll factor for the specified input device - Scroll speed will be scaled by the given value, which must be non-negative. *scroll_method none|two_finger|edge|on_button_down* Change scroll method for specified input device - *repeat_delay * + *repeat_delay * Repeat delay in ms for keyboards only - *repeat_rate * + *repeat_rate * Repeat rate in 1/s for keyboards only *tap enabled|disabled* @@ -230,11 +239,11 @@ definekey top mode root middle click. _lmr_ treats 1 finger as left click, 2 fingers as middle click, and 3 fingers as right click. -message +message Display a line of arbitrary text. -*mode * - Enter mode "" - Returns to default mode, after a command is +*mode * + Enter mode "" - Returns to default mode, after a command is executed. *movetonextscreen* @@ -245,12 +254,12 @@ message Move currently focused window to previous screen See *output* for differences between screen and output. -*movetoscreen * - Move currently focused window to -th screen +*movetoscreen * + Move currently focused window to -th screen See *output* for differences between screen and output. -*movetoworkspace * - Move currently focused window to -th workspace +*movetoworkspace * + Move currently focused window to -th workspace See *output* for differences between screen and output. *next* @@ -263,23 +272,32 @@ message *only* Remove all splits and make current window fill the entire screen -*output [[pos res x rate [scale ]] | enable | disable | prio | rotate ]* - Configure output "" - - - and are the position of the +*output [[pos res x rate [scale ]] | enable | disable | [permanent|peripheral] | prio | rotate ]* + Configure output "" - + - and are the position of the monitor in pixels. The top-left monitor should have the coordinates 0 0. - - and specify the resolution in pixels. - - sets the refresh rate of the monitor (often this is 50 or 60). - - sets the output scale (default is 1.0) - - enable and disable enable or disable . Note that if - is the only enabled output, *output disable* has + - and specify the resolution in pixels. + - sets the refresh rate of the monitor (often this is 50 or 60). + - sets the output scale (default is 1.0) + - enable and disable enable or disable . Note that if + is the only enabled output, *output disable* has no effect. - - prio is used to set the priority of an output. If + - permanent sets to persist even on disconnect. When + the physical monitor is disconnected, the output is + maintained and operates identically to the attached monitor. On reconnect, + the monitor operates as though it was never disconnected. Setting the + output role to peripheral when the monitor is disconnected, + destroys the output, as if the monitor were disconnected. + - peripheral sets the role of to peripheral, meaning that on + disconnecting the respective monitor, all views will be moved to another + available output. The default role is peripheral. + - prio is used to set the priority of an output. If nothing else is set, outputs are added as they request to be added - and have a numerical priority of -1. Using prio it is possible - to set priorities for outputs, where >= 1. The larger is, + and have a numerical priority of -1. Using prio it is possible + to set priorities for outputs, where >= 1. The larger is, the higher the priority is, that is to say, the earlier the output will appear in the list of outputs. - - rotate is used to rotate the output by ` mod 4 x 90` degrees + - rotate is used to rotate the output by ` mod 4 x 90` degrees counter-clockwise. ``` @@ -325,19 +343,19 @@ output DP-1 rotate 3 *resizeup* Resize current tile towards the top -*screen * - Change to -th screen +*screen * + Change to -th screen See *output* for differences between screen and output. *show_info* Display information about the current setup - In particular, print the identifiers of the available inputs and outputs. -*setmode * - Set default mode to +*setmode * + Set default mode to -*switchvt * - Switch to tty +*switchvt * + Switch to tty *time* Display time @@ -345,11 +363,11 @@ output DP-1 rotate 3 *vsplit* Split current tile vertically -*workspace * - Change to -th workspace +*workspace * + Change to -th workspace -*workspaces * - Set number of workspaces to - is a single integer larger than 1 +*workspaces * + Set number of workspaces to - is a single integer larger than 1 and less than 30. # MODES @@ -378,7 +396,7 @@ Keys are specified by their names as displayed for example by *xev*. Modifiers can be specified using the following syntax: - - + - The supported modifiers are: @@ -390,7 +408,7 @@ The supported modifiers are: *S - Shift* -*2 - Mod2* +*2 - Mod 2* *3 - Mod 3* @@ -417,14 +435,12 @@ Mail contact: `cagebreak @ project-repo . co` GPG Fingerprints: -- B15B92642760E11FE002DE168708D42451A94AB5 -- F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C -- 3ACEA46CCECD59E4C8222F791CBEB493681E8693 - 0A268C188D7949FEB39FD1462F2AD980247E4918 +- 283D10F54201B0C6CCEE2C561DE04E4B056C749D # LICENSE -Copyright (c) 2020-2023 The Cagebreak authors +Copyright (c) 2020-2024 The Cagebreak authors Copyright (c) 2018-2020 Jente Hidskes diff --git a/man/cagebreak-socket.7.md b/man/cagebreak-socket.7.md index 4c1a31a..a5f3d8a 100644 --- a/man/cagebreak-socket.7.md +++ b/man/cagebreak-socket.7.md @@ -1,8 +1,8 @@ -cagebreak-socket(7) "Version 2.1.2" "Cagebreak Manual" +cagebreak-socket(7) "Version 2.3.1" "Cagebreak Manual" # NAME -*cagebreak-socket* — Cagebreak socket +*cagebreak-socket* Cagebreak socket # SYNOPSIS @@ -30,7 +30,10 @@ Here is an example of how this works using *only* as a command sent over the soc ``` only -cg-ipc{"event_name":"fullscreen","tile_id":2,"workspace":1,"output":"eDP-1"} +cg-ipc{"event_name":"fullscreen", +"tile_id":2, +"workspace":1, +"output":"eDP-1"} ``` This documentation describes the trigger for the events, the keys and the data @@ -45,7 +48,9 @@ type of the values of each event. ``` background 0 1.0 0 -cg-ipc{"event_name":"background","old_bg":[0.000000,1.000000,1.000000],"new_bg":[0.000000,1.000000,0.000000]} +cg-ipc{"event_name":"background", +"old_bg":[0.000000,1.000000,1.000000], +"new_bg":[0.000000,1.000000,0.000000]} ``` *close* @@ -61,7 +66,13 @@ cg-ipc{"event_name":"background","old_bg":[0.000000,1.000000,1.000000],"new_bg": ``` close -cg-ipc{"event_name":"close","view_id":47,"view_pid":30456,"tile_id":47,"workspace":1,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"close", +"view_id":47, +"view_pid":30456, +"tile_id":47, +"workspace":1, +"output":"eDP-1", +"output_id":1} ``` *configure_input* @@ -110,7 +121,24 @@ cg-ipc{"event_name":"configure_output","output":"eDP-1","output_id":1} ``` # Cursor switches tile -cg-ipc{"event_name":"cursor_switch_tile","old_output":"eDP-1","old_output_id":1,"old_tile":2,"new_output":"eDP-1","new_output_id":1,"new_tile":3} +cg-ipc{"event_name":"cursor_switch_tile", +"old_output":"eDP-1", +"old_output_id":1, +"old_tile":2, +"new_output":"eDP-1", +"new_output_id":1, +"new_tile":3} +``` + +*custom_event* + - Trigger: Cagebreak receives the *custom_event* command, either in the config file or via the IPC socket (see *cagebreak-config(5)*). + - JSON + - event_name: "custom_event" + - message: The message passed to the *custom_event* command + +``` +custom_event Hello World! +cg-ipc{"event_name":"custom_event","message":"Hello World!"} ``` *cycle_outputs* @@ -125,7 +153,12 @@ cg-ipc{"event_name":"cursor_switch_tile","old_output":"eDP-1","old_output_id":1, ``` nextscreen -cg-ipc{"event_name":"cycle_outputs","old_output":"eDP-1","old_output_id":1,"new_output":"HDMI-A-1","new_output_id":2,"reverse":0} +cg-ipc{"event_name":"cycle_outputs", +"old_output":"eDP-1", +"old_output_id":1, +"new_output":"HDMI-A-1", +"new_output_id":2, +"reverse":0} ``` *cycle_views* @@ -143,7 +176,15 @@ cg-ipc{"event_name":"cycle_outputs","old_output":"eDP-1","old_output_id":1,"new_ ``` next -cg-ipc{"event_name":"cycle_views","old_view_id":11,"old_view_pid":32223,"new_view_id":4,"old_view_pid";53221,"tile_id":13,"workspace":1,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"cycle_views", +"old_view_id":11, +"old_view_pid":32223, +"new_view_id":4, +"old_view_pid";53221, +"tile_id":13, +"workspace":1, +"output":"eDP-1", +"output_id":1} ``` *definekey* @@ -209,12 +250,20 @@ cg-ipc{"event_name":"destroy_output","output":"HDMI-A-1","output_id":2} - curr_output: current output as a string - default_mode: name of the default mode as a string - modes: list of names of modes as strings + - message_config: the current configuration of the cagebreak messages + - font: the font used to display the messages + - display_time: the duration in seconds that the cagebreak messages are displayed + - bg_color: list of four floating point numbers denoting the background color in rgba + - fg_color: list of four floating point numbers denoting the foreground color in rgba + - anchor: the positioning of the messages on the screen (see *cagebreak-config(5)* for more information) - outputs: object of objects for each output - output name as string - priority: priority as per *output* prio in *cagebreak-config(5)* or default - coords: object of x and y coordinates of output - size: object of width and height as integers - refresh_rate: refresh rate as float + - permanent: 0 if peripheral, 1 if permanent + - active: 1 if the output is active, 0 if not - curr_workspace: current workspace as an integer - workspaces: list of objects for each workspace - views: list of objects for each view @@ -247,11 +296,18 @@ cg-ipc{"event_name":"dump","nws":1, "curr_output":"eDP-1", "default_mode":"top", "modes":["top","root","resize"], -"outputs": {"eDP-1": { +"message_config": {"font": "pango:Monospace 10", +"display_time": 2, +"bg_color": [0.900000,0.850000,0.850000,1.000000], +"fg_color": [0.000000,0.000000,0.000000,1.000000], +"anchor": "top_right" +},"outputs": {"eDP-1": { "priority": -1, "coords": {"x":0,"y":0}, "size": {"width":2560,"height":1440}, "refresh_rate": 60.012000, +"permanent": 0, +"active": 1, "curr_workspace": 0, "workspaces": [{"views": [{ "id": 16, @@ -340,7 +396,12 @@ cg-ipc{"event_name":"dump","nws":1, ``` focus -cg-ipc{"event_name":"focus_tile","old_tile_id":14,"new_tile_id":13,"workspace":1,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"focus_tile", +"old_tile_id":14, +"new_tile_id":13, +"workspace":1, +"output":"eDP-1", +"output_id":1} ``` *fullscreen* @@ -354,7 +415,11 @@ cg-ipc{"event_name":"focus_tile","old_tile_id":14,"new_tile_id":13,"workspace":1 ``` only -cg-ipc{"event_name":"fullscreen","tile_id":3,"workspace":1,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"fullscreen", +"tile_id":3, +"workspace":1, +"output":"eDP-1", +"output_id":1} ``` *move_view_to_cycle_output* @@ -370,8 +435,17 @@ cg-ipc{"event_name":"fullscreen","tile_id":3,"workspace":1,"output":"eDP-1","out ``` movetonextscreen -cg-ipc{"event_name":"cycle_outputs","old_output":"eDP-1","new_output":"HDMI-A-1","reverse":0} -cg-ipc{"event_name":"move_view_to_cycle_output","view_id":11,"view_pid":43123,"old_output":"eDP-1","old_output_id":1,"new_output":"HDMI-A-1","new_output_id":2} +cg-ipc{"event_name":"cycle_outputs", +"old_output":"eDP-1", +"new_output":"HDMI-A-1", +"reverse":0} +cg-ipc{"event_name":"move_view_to_cycle_output", +"view_id":11, +"view_pid":43123, +"old_output":"eDP-1", +"old_output_id":1, +"new_output":"HDMI-A-1", +"new_output_id":2} ``` *move_view_to_output* @@ -384,8 +458,13 @@ cg-ipc{"event_name":"move_view_to_cycle_output","view_id":11,"view_pid":43123,"o ``` movetoscreen 2 -cg-ipc{"event_name":"switch_output","old_output":"eDP-1","new_output":"HDMI-A-1"} -cg-ipc{"event_name":"move_view_to_output","view_id":78,"old_output":"eDP-1","new_output":"HDMI-A-1"} +cg-ipc{"event_name":"switch_output", +"old_output":"eDP-1", +"new_output":"HDMI-A-1"} +cg-ipc{"event_name":"move_view_to_output", +"view_id":78, +"old_output":"eDP-1", +"new_output":"HDMI-A-1"} ``` *move_view_to_ws* @@ -401,8 +480,17 @@ cg-ipc{"event_name":"move_view_to_output","view_id":78,"old_output":"eDP-1","new ``` movetoworkspace 1 -cg-ipc{"event_name":"switch_ws","old_workspace":1,"new_workspace":1,"output":"eDP-1"} -cg-ipc{"event_name":"move_view_to_ws","view_id":43,"old_workspace":0,"new_workspace":0,"output":"eDP-1","output_id":1,"view_pid":64908} +cg-ipc{"event_name":"switch_ws", +"old_workspace":1, +"new_workspace":1, +"output":"eDP-1"} +cg-ipc{"event_name":"move_view_to_ws", +"view_id":43, +"old_workspace":0, +"new_workspace":0, +"output":"eDP-1", +"output_id":1, +"view_pid":64908} ``` *new_output* @@ -431,8 +519,19 @@ cg-ipc{"event_name":"new_output","output":"HDMI-A-1","output_id":2,"priority":-1 ``` resizeleft -cg-ipc{"event_name":"resize_tile","tile_id":14,"old_dims":"[1280,0,1440,1280]","new_dims":"[1270,0,1440,1290]","workspace":1,"output":"eDP-1","output_id":1} -cg-ipc{"event_name":"resize_tile","tile_id":13,"old_dims":"[0,0,1440,1280]","new_dims":"[0,0,1440,1270]","workspace":1,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"resize_tile", +"tile_id":14, +"old_dims":"[1280,0,1440,1280]", +"new_dims":"[1270,0,1440,1290]", +"workspace":1,"output":"eDP-1", +"output_id":1} +cg-ipc{"event_name":"resize_tile", +"tile_id":13, +"old_dims":"[0,0,1440,1280]", +"new_dims":"[0,0,1440,1270]", +"workspace":1, +"output":"eDP-1", +"output_id":1} ``` *set_nws* @@ -460,7 +559,13 @@ cg-ipc{"event_name":"set_nws","old_nws":1,"new_nws":2} ``` hsplit -cg-ipc{"event_name":"split","tile_id":11,"new_tile_id":12,"workspace":1,"output":"eDP-1","output_id":1,"vertical":0} +cg-ipc{"event_name":"split", +"tile_id":11, +"new_tile_id":12, +"workspace":1, +"output":"eDP-1", +"output_id":1, +"vertical":0} ``` *swap_tile* @@ -477,7 +582,13 @@ cg-ipc{"event_name":"split","tile_id":11,"new_tile_id":12,"workspace":1,"output" ``` exchangeright -cg-ipc{"event_name":"swap_tile","tile_id":1,"tile_pid":53478,"swap_tile_id":3,"swap_tile_pid":98234,"workspace":1,"output":"eDP-1"} +cg-ipc{"event_name":"swap_tile", +"tile_id":1, +"tile_pid":53478, +"swap_tile_id":3, +"swap_tile_pid":98234, +"workspace":1, +"output":"eDP-1"} ``` *switch_default_mode* @@ -503,7 +614,11 @@ switch_output ``` screen 2 -cg-ipc{"event_name":"switch_output","old_output":"eDP-1","old_output_id":1,"new_output":"HDMI-A-1","new_output_id":2} +cg-ipc{"event_name":"switch_output", +"old_output":"eDP-1", +"old_output_id":1, +"new_output":"HDMI-A-1", +"new_output_id":2} ``` switch_ws @@ -517,7 +632,11 @@ switch_ws ``` workspace 2 -cg-ipc{"event_name":"switch_ws","old_workspace":1,"new_workspace":2,"output":"eDP-1","output_id":1} +cg-ipc{"event_name":"switch_ws", +"old_workspace":1, +"new_workspace":2, +"output":"eDP-1", +"output_id":1} ``` *view_map* @@ -533,7 +652,13 @@ cg-ipc{"event_name":"switch_ws","old_workspace":1,"new_workspace":2,"output":"eD ``` # process opens a view -cg-ipc{"event_name":"view_map","view_id":28,"tile_id":14,"workspace":1,"output":"eDP-1","output_id":1,"view_pid":39827} +cg-ipc{"event_name":"view_map", +"view_id":28, +"tile_id":14, +"workspace":1, +"output":"eDP-1", +"output_id":1, +"view_pid":39827} ``` *view_unmap* @@ -549,7 +674,13 @@ cg-ipc{"event_name":"view_map","view_id":28,"tile_id":14,"workspace":1,"output": ``` # view is closed by the process -cg-ipc{"event_name":"view_unmap","view_id":24,"tile_id":13,"workspace":1,"output":"eDP-1","output_id":1,"view_pid":39544} +cg-ipc{"event_name":"view_unmap", +"view_id":24, +"tile_id":13, +"workspace":1, +"output":"eDP-1", +"output_id":1, +"view_pid":39544} ``` ## SECURITY @@ -579,14 +710,12 @@ Mail contact: `cagebreak @ project-repo . co` GPG Fingerprints: -- B15B92642760E11FE002DE168708D42451A94AB5 -- F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C -- 3ACEA46CCECD59E4C8222F791CBEB493681E8693 - 0A268C188D7949FEB39FD1462F2AD980247E4918 +- 283D10F54201B0C6CCEE2C561DE04E4B056C749D # LICENSE -Copyright (c) 2022 - 2023 The Cagebreak authors +Copyright (c) 2022 - 2024 The Cagebreak authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/man/cagebreak.1.md b/man/cagebreak.1.md index c8fc85e..d91c589 100644 --- a/man/cagebreak.1.md +++ b/man/cagebreak.1.md @@ -1,4 +1,4 @@ -cagebreak(1) "Version 2.1.2" "Cagebreak Manual" +cagebreak(1) "Version 2.3.1" "Cagebreak Manual" # NAME @@ -28,7 +28,7 @@ socket specified in the environment variable *\$CAGEBREAK_SOCKET*. The syntax accepted through this socket is identical to that of the configuration file (see *cagebreak-config(5)*). Errors which occur during interaction over IPC channel -are displayed in a message box at the top right of the screen. +are displayed in a message box on the screen. # OPTIONS @@ -87,14 +87,12 @@ Mail contact: `cagebreak @ project-repo . co` GPG Fingerprints: -- B15B92642760E11FE002DE168708D42451A94AB5 -- F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C -- 3ACEA46CCECD59E4C8222F791CBEB493681E8693 - 0A268C188D7949FEB39FD1462F2AD980247E4918 +- 283D10F54201B0C6CCEE2C561DE04E4B056C749D # LICENSE -Copyright (c) 2020-2023 The Cagebreak authors +Copyright (c) 2020-2024 The Cagebreak authors Copyright (c) 2018-2020 Jente Hidskes diff --git a/manuals.md b/manuals.md new file mode 100644 index 0000000..dd5f84b --- /dev/null +++ b/manuals.md @@ -0,0 +1,5 @@ +# Cagebreak Manuals + + * [cagebreak-config (5)](man/cagebreak-config.5.md) (probably, what you are looking for, commands etc.) + * [cagebreak (1)](man/cagebreak.1.md) (command line arguments, environment variables etc.) + * [cagebreak-socket (7)](man/cagebreak-socket.7.md) (mostly useful for scripting, socket information) diff --git a/meson.build b/meson.build index 777c8d3..6b57a32 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,9 @@ -# Copyright 2020 - 2023, project-repo and the cagebreak contributors +# Copyright 2020 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT project( 'cagebreak', 'c', -version : '2.1.2', +version : '2.3.1', license : 'MIT', default_options : ['c_std=c11', 'warning_level=3'] ) @@ -55,7 +55,7 @@ if is_freebsd ) endif -wlroots = dependency('wlroots', version: ['>=0.16.1', '< 0.17.0']) +wlroots = dependency('wlroots', version: ['>=0.17.0', '< 0.18.0']) wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_server = dependency('wayland-server') wayland_cursor = dependency('wayland-cursor') @@ -204,15 +204,15 @@ reproducible_build_versions = { 'wayland_server': '1.19.0', 'wayland_client': '1.22.0', 'wayland_cursor': '1.22.0', - 'wlroots': '0.16.2', - 'xkbcommon': '1.5.0', - 'fontconfig': '2.14.2', - 'libinput': '1.23.0', - 'libevdev': '1.13.0', - 'libudev': '253', - 'pango': '1.50.14', - 'cairo': '1.17.8', - 'pangocairo': '1.50.14', + 'wlroots': '0.17.1', + 'xkbcommon': '1.6.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', 'math': '-1' } @@ -238,7 +238,7 @@ foreach name, dep : cagebreak_dependencies_dict endforeach reproducible_build_compiler = 'gcc' -reproducible_build_compiler_version = '12.2.1' +reproducible_build_compiler_version = '13.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 +260,7 @@ install_data('LICENSE', install_dir : '/usr/share/licenses/' + meson.project_nam if get_option('man-pages') scdoc = find_program('scdoc') - secssinceepoch = 1682363199 + secssinceepoch = 1706350970 shcommand = 'export SOURCE_DATE_EPOCH=' + secssinceepoch.to_string() + ' ; @0@ < @INPUT@'.format(scdoc.path()) sh = find_program('sh') mandir1 = join_paths(get_option('mandir'), 'man1') @@ -371,12 +371,16 @@ run_target('create-artefacts', # Test Suite test('Build without warnings', find_program('test/build-w-o-warnings'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Example script header is consistent', find_program('test/script-header'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Script executability is consistent', find_program('test/script-header'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Man page consistency', find_program('test/man-pages'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') test('Build without xwayland', find_program('test/build-w-o-xwayland'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') test('Copyright and LICENSE', find_program('test/copyright-license'), args : [ cagebreak_main_file + cagebreak_source_strings + cagebreak_header_strings + fuzz_sources + fuzz_headers + fuzz_override_lib ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()), ''.join('MESONLICENSE=', meson.project_license())], suite: 'devel' ) -test('Clang-format (formatting check)', find_program('test/clang-format'), args : [ cagebreak_main_file + cagebreak_source_strings + cagebreak_header_strings + fuzz_sources + fuzz_headers + fuzz_override_lib ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') -test('Shellcheck (script linting)', find_program('test/shellcheck'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Formatting check (clang-format)', find_program('test/clang-format'), args : [ cagebreak_main_file + cagebreak_source_strings + cagebreak_header_strings + fuzz_sources + fuzz_headers + fuzz_override_lib ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Script linting (shellcheck)', find_program('test/shellcheck'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') test('GPG key validity', find_program('test/gpg-validity'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') -test('Scan-build (static analysis)', find_program('test/scan-build'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel-long') +test('Illegal Strings', find_program('test/illegal-strings'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel') +test('Static analysis (scan-build)', find_program('test/scan-build'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel-long') test('Arguments', find_program('test/arguments'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'basic') test('Environment Variables', find_program('test/environment-variables'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'basic') test('Semantic versioning', find_program('test/versions'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release') diff --git a/meson_options.txt b/meson_options.txt index eba2f60..a4377b9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,8 +1,8 @@ -# Copyright 2020 - 2023, project-repo and the cagebreak contributors +# Copyright 2020 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT option('xwayland', type: 'boolean', value: 'false', description: 'Enable support for X11 applications') option('man-pages', type: 'boolean', value: 'false', description: 'Build man pages (requires pandoc)') option('fuzz', type: 'boolean', value: 'false', description: 'Enable building fuzzer targets') option('version_override', type: 'string', description: 'Set the project version to the string specified. Used for creating hashes for reproducible builds.') option('corpus', type: 'string', value: 'fuzz_corpus', description: 'Set fuzzing corpus directory') -option('gpg_id', type: 'string', value: '4E82C72C6B3E58A7BC4FF8554909F84CA83BB867', description: 'Set gpg signing key for cagebreak') +option('gpg_id', type: 'string', value: '438C27DDB5D174673DF4D67B451205B3528C7C63', description: 'Set gpg signing key for cagebreak') diff --git a/message.c b/message.c index 74b1d0a..4b99aaf 100644 --- a/message.c +++ b/message.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -175,13 +174,9 @@ create_message_texture(const char *string, const struct cg_output *output) { return buf; } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif void message_set_output(struct cg_output *output, const char *string, - struct wlr_box *box, enum cg_message_align align) { + struct wlr_box *box, enum cg_message_anchor anchor) { struct cg_message *message = malloc(sizeof(struct cg_message)); if(!message) { wlr_log(WLR_ERROR, "Error allocating message structure"); @@ -203,26 +198,35 @@ message_set_output(struct cg_output *output, const char *string, int height = buf->base.height / scale; message->position->width = width; message->position->height = height; - switch(align) { - case CG_MESSAGE_TOP_RIGHT: { - message->position->x -= width; + switch(anchor) { + case CG_MESSAGE_TOP_LEFT: + message->position->x = 0; + message->position->y = 0; break; - } - case CG_MESSAGE_BOTTOM_LEFT: { + case CG_MESSAGE_TOP_CENTER: + message->position->x -= width / 2; + message->position->y = 0; + break; + case CG_MESSAGE_TOP_RIGHT: + message->position->x -= width; + message->position->y = 0; + break; + case CG_MESSAGE_BOTTOM_LEFT: + message->position->x = 0; message->position->y -= height; break; - } - case CG_MESSAGE_BOTTOM_RIGHT: { + case CG_MESSAGE_BOTTOM_CENTER: + message->position->x -= width / 2; + message->position->y -= height; + break; + case CG_MESSAGE_BOTTOM_RIGHT: message->position->x -= width; message->position->y -= height; break; - } - case CG_MESSAGE_CENTER: { + case CG_MESSAGE_CENTER: message->position->x -= width / 2; message->position->y -= height / 2; break; - } - case CG_MESSAGE_TOP_LEFT: default: break; } @@ -236,17 +240,18 @@ message_set_output(struct cg_output *output, const char *string, wlr_scene_buffer_create(&scene_output->scene->tree, &buf->base); wlr_scene_node_raise_to_top(&message->message->node); wlr_scene_node_set_enabled(&message->message->node, true); - struct wlr_box outp_box; - wlr_output_layout_get_box(output->server->output_layout, output->wlr_output, - &outp_box); wlr_scene_buffer_set_dest_size(message->message, width, height); - wlr_scene_node_set_position(&message->message->node, - message->position->x + outp_box.x, - message->position->y + outp_box.y); + wlr_scene_node_set_position( + &message->message->node, + message->position->x + output_get_layout_box(output).x, + message->position->y + output_get_layout_box(output).y); } void message_printf(struct cg_output *output, const char *fmt, ...) { + if(output->destroyed) { + return; + } va_list ap; va_start(ap, fmt); char *buffer = malloc_vsprintf_va_list(fmt, ap); @@ -262,26 +267,55 @@ message_printf(struct cg_output *output, const char *fmt, ...) { free(buffer); return; } - struct wlr_box output_box; - wlr_output_layout_get_box(output->server->output_layout, output->wlr_output, - &output_box); - - box->x = output_box.width; - box->y = 0; + struct wlr_box output_box = output_get_layout_box(output); box->width = 0; box->height = 0; + switch(output->server->message_config.anchor) { + case CG_MESSAGE_TOP_LEFT: + box->x = 0; + box->y = 0; + break; + case CG_MESSAGE_TOP_CENTER: + box->x = output_box.width / 2; + box->y = 0; + break; + case CG_MESSAGE_TOP_RIGHT: + box->x = output_box.width; + box->y = 0; + break; + case CG_MESSAGE_BOTTOM_LEFT: + box->x = 0; + box->y = output_box.height; + break; + case CG_MESSAGE_BOTTOM_CENTER: + box->x = output_box.width / 2; + box->y = output_box.height; + break; + case CG_MESSAGE_BOTTOM_RIGHT: + box->x = output_box.width; + box->y = output_box.height; + break; + case CG_MESSAGE_CENTER: + box->x = output_box.width / 2; + box->y = output_box.height / 2; + break; + default: + break; + } - message_set_output(output, buffer, box, CG_MESSAGE_TOP_RIGHT); + message_set_output(output, buffer, box, + output->server->message_config.anchor); free(buffer); alarm(output->server->message_config.display_time); } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif void message_printf_pos(struct cg_output *output, struct wlr_box *position, - const enum cg_message_align align, const char *fmt, ...) { + const enum cg_message_anchor anchor, const char *fmt, ...) { + if(output->destroyed) { + free(position); + return; + } uint16_t buf_len = 256; char *buffer = (char *)malloc(buf_len * sizeof(char)); va_list ap; @@ -290,7 +324,7 @@ message_printf_pos(struct cg_output *output, struct wlr_box *position, vsnprintf(buffer, buf_len, fmt, ap); va_end(ap); - message_set_output(output, buffer, position, align); + message_set_output(output, buffer, position, anchor); free(buffer); alarm(output->server->message_config.display_time); } diff --git a/message.h b/message.h index 806307c..a1b8f13 100644 --- a/message.h +++ b/message.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef MESSAGE_H @@ -11,12 +11,15 @@ struct cg_output; struct wlr_box; struct wlr_buffer; -enum cg_message_align { +enum cg_message_anchor { CG_MESSAGE_TOP_LEFT, + CG_MESSAGE_TOP_CENTER, CG_MESSAGE_TOP_RIGHT, CG_MESSAGE_BOTTOM_LEFT, + CG_MESSAGE_BOTTOM_CENTER, CG_MESSAGE_BOTTOM_RIGHT, CG_MESSAGE_CENTER, + CG_MESSAGE_NOPT }; struct cg_message_config { @@ -24,6 +27,7 @@ struct cg_message_config { int display_time; float bg_color[4]; float fg_color[4]; + enum cg_message_anchor anchor; }; struct cg_message { @@ -37,7 +41,7 @@ void message_printf(struct cg_output *output, const char *fmt, ...); void message_printf_pos(struct cg_output *output, struct wlr_box *position, - enum cg_message_align, const char *fmt, ...); + enum cg_message_anchor, const char *fmt, ...); void message_clear(struct cg_output *output); diff --git a/output.c b/output.c index 506f5bd..c048b9b 100644 --- a/output.c +++ b/output.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L @@ -14,13 +14,16 @@ #if WLR_HAS_X11_BACKEND #include #endif +#include #include +#include #include +#include #include -#include #include #include #include +#include #include #include #if CG_HAS_XWAYLAND @@ -42,7 +45,7 @@ void output_clear(struct cg_output *output) { struct cg_server *server = output->server; - wlr_output_layout_remove(server->output_layout, output->wlr_output); + wlr_scene_output_destroy(output->scene_output); if(server->running && server->curr_output == output && wl_list_length(&server->outputs) > 1) { @@ -103,7 +106,7 @@ output_get_num(const struct cg_output *output) { struct cg_output *it; int count = 1; wl_list_for_each(it, &output->server->outputs, link) { - if(strcmp(output->wlr_output->name, it->wlr_output->name) == 0) { + if(strcmp(output->name, it->name) == 0) { return count; } ++count; @@ -111,34 +114,64 @@ output_get_num(const struct cg_output *output) { return -1; } +struct wlr_box +output_get_layout_box(struct cg_output *output) { + struct wlr_box box; + wlr_output_layout_get_box(output->server->output_layout, output->wlr_output, + &box); + if(!output->destroyed && !wlr_box_empty(&box)) { + output->layout_box.x = box.x; + output->layout_box.y = box.y; + output->layout_box.width = box.width; + output->layout_box.height = box.height; + } + return output->layout_box; +} + static void output_destroy(struct cg_output *output) { struct cg_server *server = output->server; - char *outp_name = strdup(output->wlr_output->name); + char *outp_name = strdup(output->name); int outp_num = output_get_num(output); - wl_list_remove(&output->destroy.link); - wl_list_remove(&output->mode.link); - wl_list_remove(&output->commit.link); - wl_list_remove(&output->frame.link); - - output_clear(output); - - /*Important: due to unfortunate events, "workspace" and "output->workspace" - * have nothing in common. The former is the workspace of a single output, - * whereas the latter is the workspace of the outputs.*/ - for(unsigned int i = 0; i < server->nws; ++i) { - workspace_free(output->workspaces[i]); + if(output->destroyed == false) { + wl_list_remove(&output->destroy.link); + wl_list_remove(&output->commit.link); + wl_list_remove(&output->frame.link); + wlr_scene_output_destroy(output->scene_output); + output->scene_output = NULL; } - free(output->workspaces); + output->destroyed = true; + enum output_role role = output->role; + if(role == OUTPUT_ROLE_PERMANENT) { + output->wlr_output = wlr_headless_add_output(server->headless_backend, + output->layout_box.width, + output->layout_box.height); + output->scene_output = + wlr_scene_output_create(server->scene, output->wlr_output); + struct wlr_output_layout_output *lo = + wlr_output_layout_add(server->output_layout, output->wlr_output, + output->layout_box.x, output->layout_box.y); + wlr_scene_output_layout_add_output(server->scene_output_layout, lo, + output->scene_output); - free(output); + } else { + output_clear(output); + + for(unsigned int i = 0; i < server->nws; ++i) { + workspace_free(output->workspaces[i]); + } + free(output->workspaces); + free(output->name); + + free(output); + } if(outp_name != NULL) { ipc_send_event(server, "{\"event_name\":\"destroy_output\",\"output\":\"%s\"," - "\"output_id\":%d}", - outp_name, outp_num); + "\"output_id\":%d,\"permanent\":%d}", + outp_name, outp_num, role == OUTPUT_ROLE_PERMANENT); free(outp_name); } else { wlr_log(WLR_ERROR, @@ -155,6 +188,27 @@ handle_output_destroy(struct wl_listener *listener, void *data) { output_destroy(output); } +void +handle_output_gamma_control_set_gamma(struct wl_listener *listener, + void *data) { + struct cg_server *server = + wl_container_of(listener, server, gamma_control_set_gamma); + const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; + + struct wlr_gamma_control_v1 *gamma_control = + wlr_gamma_control_manager_v1_get_control(server->gamma_control, + event->output); + + struct wlr_output_state pending = {0}; + wlr_gamma_control_v1_apply(gamma_control, &pending); + if(!wlr_output_test_state(event->output, &pending)) { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + } else { + wlr_output_commit_state(event->output, &pending); + wlr_output_schedule_frame(event->output); + } +} + static void handle_output_frame(struct wl_listener *listener, void *data) { struct cg_output *output = wl_container_of(listener, output, frame); @@ -166,7 +220,7 @@ handle_output_frame(struct wl_listener *listener, void *data) { if(scene_output == NULL) { return; } - wlr_scene_output_commit(scene_output); + wlr_scene_output_commit(scene_output, NULL); struct timespec now = {0}; clock_gettime(CLOCK_MONOTONIC, &now); @@ -258,11 +312,24 @@ output_apply_config(struct cg_server *server, struct cg_output *output, struct cg_output_config *config) { struct wlr_output *wlr_output = output->wlr_output; - if(output->wlr_output->enabled) { - wlr_output_layout_remove(server->output_layout, wlr_output); + struct wlr_box prev_box; + prev_box.x = output->layout_box.x; + prev_box.y = output->layout_box.y; + prev_box.width = output->layout_box.width; + prev_box.height = output->layout_box.height; + bool prio_changed = false; + if(config->role != OUTPUT_ROLE_DEFAULT) { + output->role = config->role; + if((output->role == OUTPUT_ROLE_PERIPHERAL) && + (output->destroyed == true)) { + output_destroy(output); + wlr_output_destroy(wlr_output); + return; + } } if(config->priority != -1) { + prio_changed = (output->priority != config->priority); output->priority = config->priority; } @@ -283,15 +350,59 @@ output_apply_config(struct cg_server *server, struct cg_output *output, wlr_output_commit(wlr_output); return; } - wlr_output_layout_add(server->output_layout, wlr_output, config->pos.x, - config->pos.y); - /* Since the size of the output may have changed, we - * reinitialize all workspaces with a fullscreen layout */ - for(unsigned int i = 0; i < output->server->nws; ++i) { - output_make_workspace_fullscreen(output, i); + if(wlr_box_empty(&output->layout_box)) { + struct wlr_output_layout_output *lo = + wlr_output_layout_add(server->output_layout, wlr_output, + config->pos.x, config->pos.y); + wlr_scene_output_layout_add_output(server->scene_output_layout, lo, + output->scene_output); + } else { + wlr_scene_output_set_position(output->scene_output, config->pos.x, + config->pos.y); } - } else { + if(output->workspaces != NULL) { + wlr_output_layout_get_box(server->output_layout, output->wlr_output, + &output->layout_box); + /* Since the size of the output may have changed, we + * reinitialize all workspaces with a fullscreen layout */ + if(output->layout_box.width != prev_box.width || + output->layout_box.height != prev_box.height) { + for(unsigned int i = 0; i < output->server->nws; ++i) { + output_make_workspace_fullscreen(output, i); + } + } + if(prev_box.x != output->layout_box.x || + prev_box.y != output->layout_box.y) { + for(unsigned int i = 0; i < server->nws; ++i) { + struct cg_workspace *ws = output->workspaces[i]; + bool first = true; + for(struct cg_tile *tile = ws->focused_tile; + first || output->workspaces[i]->focused_tile != tile; + tile = tile->next) { + first = false; + if(tile->view != NULL) { + wlr_scene_node_set_position( + &tile->view->scene_tree->node, + tile->view->ox + output->layout_box.x, + tile->view->oy + output->layout_box.y); + } + } + } + } + } + } else if(wlr_box_empty(&output->layout_box)) { wlr_output_layout_add_auto(server->output_layout, wlr_output); + // The following two lines make sure that the output is "manually" + // managed, so that its position doesn't change anymore in the + // future. + wlr_output_layout_get_box(server->output_layout, output->wlr_output, + &output->layout_box); + wlr_output_layout_remove(server->output_layout, output->wlr_output); + struct wlr_output_layout_output *lo = + wlr_output_layout_add(server->output_layout, output->wlr_output, + output->layout_box.x, output->layout_box.y); + wlr_scene_output_layout_add_output(server->scene_output_layout, lo, + output->scene_output); struct wlr_output_mode *preferred_mode = wlr_output_preferred_mode(wlr_output); @@ -307,8 +418,10 @@ output_apply_config(struct cg_server *server, struct cg_output *output, wlr_output_enable(wlr_output, false); wlr_output_commit(wlr_output); } else { - wl_list_remove(&output->link); - output_insert(server, output); + if(prio_changed) { + wl_list_remove(&output->link); + output_insert(server, output); + } wlr_output_enable(wlr_output, true); wlr_output_commit(wlr_output); } @@ -325,9 +438,8 @@ output_apply_config(struct cg_server *server, struct cg_output *output, output->bg = wlr_scene_rect_create( &scene_output->scene->tree, output->wlr_output->width, output->wlr_output->height, server->bg_color); - struct wlr_box box; - wlr_output_layout_get_box(server->output_layout, output->wlr_output, &box); - wlr_scene_node_set_position(&output->bg->node, box.x, box.y); + wlr_scene_node_set_position(&output->bg->node, scene_output->x, + scene_output->y); wlr_scene_node_lower_to_bottom(&output->bg->node); } @@ -340,6 +452,7 @@ empty_output_config(void) { } cfg->status = OUTPUT_DEFAULT; + cfg->role = OUTPUT_ROLE_DEFAULT; cfg->pos.x = -1; cfg->pos.y = -1; cfg->pos.width = -1; @@ -363,6 +476,11 @@ merge_output_configs(struct cg_output_config *cfg1, } else { out_cfg->status = cfg1->status; } + if(cfg1->role == out_cfg->role) { + out_cfg->role = cfg2->role; + } else { + out_cfg->role = cfg1->role; + } if(cfg1->pos.x == out_cfg->pos.x) { out_cfg->pos.x = cfg2->pos.x; out_cfg->pos.y = cfg2->pos.y; @@ -411,7 +529,7 @@ output_configure(struct cg_server *server, struct cg_output *output) { struct cg_output_config *tot_config = empty_output_config(); struct cg_output_config *config; wl_list_for_each(config, &server->output_config, link) { - if(strcmp(config->output_name, output->wlr_output->name) == 0) { + if(strcmp(config->output_name, output->name) == 0) { if(tot_config == NULL) { return; } @@ -439,8 +557,9 @@ handle_output_commit(struct wl_listener *listener, void *data) { return; } - if(event->committed & - (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) { + if(event->state->committed & + (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE | + WLR_OUTPUT_STATE_MODE)) { struct cg_view *view; wl_list_for_each( view, &output->workspaces[output->curr_workspace]->views, link) { @@ -451,29 +570,12 @@ handle_output_commit(struct wl_listener *listener, void *data) { } } -static void -handle_output_mode(struct wl_listener *listener, void *data) { - struct cg_output *output = wl_container_of(listener, output, mode); - - if(!output->wlr_output->enabled || output->workspaces == NULL) { - return; - } - - struct cg_view *view; - wl_list_for_each(view, &output->workspaces[output->curr_workspace]->views, - link) { - if(view_is_visible(view)) { - view_maximize(view, view->tile); - } - } -} - void output_make_workspace_fullscreen(struct cg_output *output, int ws) { struct cg_server *server = output->server; - struct cg_view *current_view = seat_get_focus(server->seat); + struct cg_view *current_view = output->workspaces[ws]->focused_tile->view; - if(current_view == NULL || ws != output->curr_workspace) { + if(current_view == NULL) { struct cg_view *it = NULL; wl_list_for_each(it, &output->workspaces[ws]->views, link) { if(view_is_visible(it)) { @@ -484,7 +586,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->wlr_output, + if(full_screen_workspace_tiles(server->output_layout, output->workspaces[ws], &server->tiles_curr_id) != 0) { wlr_log(WLR_ERROR, "Failed to allocate space for fullscreen workspace"); @@ -496,19 +598,18 @@ output_make_workspace_fullscreen(struct cg_output *output, int ws) { it_view->tile = output->workspaces[ws]->focused_tile; } - if(ws == output->curr_workspace) { + workspace_tile_update_view(output->workspaces[ws]->focused_tile, + current_view); + if((ws == output->curr_workspace) && (output == server->curr_output)) { seat_set_focus(server->seat, current_view); } } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif 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)) { @@ -516,60 +617,104 @@ handle_new_output(struct wl_listener *listener, void *data) { return; } - struct cg_output *output = calloc(1, sizeof(struct cg_output)); + struct cg_output *ito; + bool reinit = false; + struct cg_output *output = NULL; + wl_list_for_each(ito, &server->outputs, link) { + if((strcmp(ito->name, wlr_output->name) == 0) && (ito->destroyed)) { + reinit = true; + output = ito; + } + } + if(reinit) { + wlr_output_layout_remove(server->output_layout, output->wlr_output); + wlr_scene_output_destroy(output->scene_output); + } else { + output = calloc(1, sizeof(struct cg_output)); + } if(!output) { wlr_log(WLR_ERROR, "Failed to allocate output"); return; } + output->scene_output = wlr_scene_output_create(server->scene, wlr_output); output->wlr_output = wlr_output; - output->server = server; - output->last_scanned_out_view = NULL; + output->destroyed = false; - struct cg_output_priorities *it; - int prio = -1; - wl_list_for_each(it, &server->output_priorities, link) { - if(strcmp(output->wlr_output->name, it->ident) == 0) { - prio = it->priority; + if(!reinit) { + output->server = server; + output->name = strdup(wlr_output->name); + + struct cg_output_priorities *it; + int prio = -1; + wl_list_for_each(it, &server->output_priorities, link) { + if(strcmp(output->name, it->ident) == 0) { + prio = it->priority; + } } - } - output->priority = prio; - wlr_output_set_transform(wlr_output, WL_OUTPUT_TRANSFORM_NORMAL); - output->workspaces = NULL; + output->priority = prio; + wlr_output_set_transform(wlr_output, WL_OUTPUT_TRANSFORM_NORMAL); + output->workspaces = NULL; - wl_list_init(&output->messages); + wl_list_init(&output->messages); - if(!wlr_xcursor_manager_load(server->seat->xcursor_manager, - wlr_output->scale)) { - wlr_log(WLR_ERROR, - "Cannot load XCursor theme for output '%s' with scale %f", - wlr_output->name, wlr_output->scale); - } - - output_insert(server, output); - output_configure(server, output); - - output->workspaces = malloc(server->nws * sizeof(struct cg_workspace *)); - for(unsigned int i = 0; i < server->nws; ++i) { - output->workspaces[i] = full_screen_workspace(output); - if(!output->workspaces[i]) { - wlr_log(WLR_ERROR, "Failed to allocate workspaces for output"); - return; + if(!wlr_xcursor_manager_load(server->seat->xcursor_manager, + wlr_output->scale)) { + wlr_log(WLR_ERROR, + "Cannot load XCursor theme for output '%s' with scale %f", + output->name, wlr_output->scale); } - output->workspaces[i]->num = i; - wl_list_init(&output->workspaces[i]->views); - wl_list_init(&output->workspaces[i]->unmanaged_views); + + output_insert(server, output); + // This is duplicated here only as a cue for the static analysis tool + output->destroyed = false; + output_configure(server, output); + wlr_output_layout_get_box(server->output_layout, output->wlr_output, + &output->layout_box); + + output->workspaces = + malloc(server->nws * sizeof(struct cg_workspace *)); + for(unsigned int i = 0; i < server->nws; ++i) { + output->workspaces[i] = full_screen_workspace(output); + if(!output->workspaces[i]) { + wlr_log(WLR_ERROR, "Failed to allocate workspaces for output"); + return; + } + output->workspaces[i]->num = i; + wl_list_init(&output->workspaces[i]->views); + wl_list_init(&output->workspaces[i]->unmanaged_views); + } + + wlr_scene_node_raise_to_top(&output->workspaces[0]->scene->node); + workspace_focus(output, 0); + + /* We are the first output. Set the current output to this one. */ + if(server->curr_output == NULL) { + server->curr_output = output; + } + } else { + struct wlr_output_layout_output *lo = + wlr_output_layout_add(server->output_layout, wlr_output, + output->layout_box.x, output->layout_box.y); + wlr_scene_output_layout_add_output(server->scene_output_layout, lo, + output->scene_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_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); + output_configure(server, output); + output_get_layout_box(output); } - wlr_scene_node_raise_to_top(&output->workspaces[0]->scene->node); - workspace_focus(output, 0); - - /* We are the first output. Set the current output to this one. */ - if(server->curr_output == NULL) { - server->curr_output = output; - } - wlr_xcursor_manager_set_cursor_image(server->seat->xcursor_manager, - DEFAULT_XCURSOR, server->seat->cursor); + wlr_cursor_set_xcursor(server->seat->cursor, server->seat->xcursor_manager, + DEFAULT_XCURSOR); wlr_cursor_warp(server->seat->cursor, NULL, 0, 0); output->destroy.notify = handle_output_destroy; @@ -578,14 +723,10 @@ handle_new_output(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.frame, &output->frame); output->commit.notify = handle_output_commit; wl_signal_add(&wlr_output->events.commit, &output->commit); - output->mode.notify = handle_output_mode; - wl_signal_add(&wlr_output->events.mode, &output->mode); + ipc_send_event(server, "{\"event_name\":\"new_output\",\"output\":\"%s\",\"output_" - "id\":%d,\"priority\":%d}", - output->wlr_output->name, output_get_num(output), - output->priority); + "id\":%d,\"priority\":%d,\"restart\":%d}", + output->name, output_get_num(output), output->priority, + reinit); } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif diff --git a/output.h b/output.h index 90cd615..573c259 100644 --- a/output.h +++ b/output.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_OUTPUT_H @@ -12,20 +12,29 @@ struct cg_view; struct wlr_output; struct wlr_surface; +enum output_role { + OUTPUT_ROLE_PERIPHERAL, + OUTPUT_ROLE_PERMANENT, + OUTPUT_ROLE_DEFAULT +}; + struct cg_output { struct cg_server *server; struct wlr_output *wlr_output; struct wlr_scene_rect *bg; + struct wlr_scene_output *scene_output; - struct wl_listener mode; struct wl_listener commit; struct wl_listener destroy; struct wl_listener frame; struct cg_workspace **workspaces; struct wl_list messages; + struct wlr_box layout_box; int curr_workspace; int priority; - struct cg_view *last_scanned_out_view; + enum output_role role; + bool destroyed; + char *name; struct wl_list link; // cg_server::outputs }; @@ -40,6 +49,7 @@ enum output_status { OUTPUT_ENABLE, OUTPUT_DISABLE, OUTPUT_DEFAULT }; struct cg_output_config { enum output_status status; + enum output_role role; struct wlr_box pos; char *output_name; float refresh_rate; @@ -53,7 +63,8 @@ typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data); - +struct wlr_box +output_get_layout_box(struct cg_output *output); void handle_new_output(struct wl_listener *listener, void *data); void @@ -64,4 +75,8 @@ void output_make_workspace_fullscreen(struct cg_output *output, int ws); int output_get_num(const struct cg_output *output); +void +handle_output_gamma_control_set_gamma(struct wl_listener *listener, void *data); +void +output_insert(struct cg_server *server, struct cg_output *output); #endif diff --git a/pango.c b/pango.c index 3af6f7f..3006f5b 100644 --- a/pango.c +++ b/pango.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include diff --git a/pango.h b/pango.h index 53a78cc..5aa6c8d 100644 --- a/pango.h +++ b/pango.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef _SWAY_PANGO_H diff --git a/parse.c b/parse.c index 68767c6..72d8295 100644 --- a/parse.c +++ b/parse.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200812L @@ -543,6 +543,10 @@ parse_output_config_keyword(char *key_str, enum output_status *status) { *status = OUTPUT_DEFAULT; } else if(strcmp(key_str, "enable") == 0) { *status = OUTPUT_ENABLE; + } else if(strcmp(key_str, "permanent") == 0) { + *status = OUTPUT_DEFAULT; + } else if(strcmp(key_str, "peripheral") == 0) { + *status = OUTPUT_DEFAULT; } else if(strcmp(key_str, "disable") == 0) { *status = OUTPUT_DISABLE; } else { @@ -566,6 +570,7 @@ parse_output_config(char **saveptr, char **errstr) { cfg->priority = -1; cfg->scale = -1; cfg->angle = -1; + cfg->role = OUTPUT_ROLE_DEFAULT; char *name = strtok_r(NULL, " ", saveptr); if(name == NULL) { *errstr = @@ -574,8 +579,9 @@ parse_output_config(char **saveptr, char **errstr) { } char *key_str = strtok_r(NULL, " ", saveptr); if(parse_output_config_keyword(key_str, &(cfg->status)) != 0) { - *errstr = log_error("Expected keyword \"pos\", \"prio\", \"enable\" or " - "\"disable\" in output configuration for output %s", + *errstr = log_error("Expected keyword \"pos\", \"prio\", \"enable\", " + "\"disable\", \"permanent\" or \"peripheral\" in " + "output configuration for output %s", name); goto error; } @@ -622,6 +628,18 @@ parse_output_config(char **saveptr, char **errstr) { return cfg; } + if(strcmp(key_str, "peripheral") == 0) { + cfg->output_name = strdup(name); + cfg->role = OUTPUT_ROLE_PERIPHERAL; + return cfg; + } + + if(strcmp(key_str, "permanent") == 0) { + cfg->output_name = strdup(name); + cfg->role = OUTPUT_ROLE_PERMANENT; + return cfg; + } + cfg->pos.x = parse_uint(saveptr, " "); if(cfg->pos.x < 0) { *errstr = log_error( @@ -702,6 +720,7 @@ parse_message_config(char **saveptr, char **errstr) { cfg->fg_color[0] = -1; cfg->display_time = -1; cfg->font = NULL; + cfg->anchor = CG_MESSAGE_NOPT; char *setting = strtok_r(NULL, " ", saveptr); if(setting == NULL) { @@ -745,6 +764,22 @@ parse_message_config(char **saveptr, char **errstr) { goto error; } } + } else if(strcmp(setting, "anchor") == 0) { + char *anchors[] = {"top_left", "top_center", "top_right", + "bottom_left", "bottom_center", "bottom_right", + "center"}; + for(int i = 0; i < 7; ++i) { + if(strcmp(*saveptr, anchors[i]) == 0) { + cfg->anchor = i; + break; + } + } + if(cfg->anchor == CG_MESSAGE_NOPT) { + *errstr = + log_error("Error parsing command \"configure_message anchor\", " + "the given anchor value is not a valid option"); + goto error; + } } else { *errstr = log_error("Invalid option to command \"configure_message\""); goto error; @@ -811,6 +846,15 @@ parse_command(struct cg_server *server, struct keybinding *keybinding, return -1; } keybinding->data.c = strdup(saveptr); + } else if(strcmp(action, "custom_event") == 0) { + keybinding->action = KEYBINDING_SEND_CUSTOM_EVENT; + if(saveptr == NULL) { + *errstr = + log_error("Not enough paramaters to \"custom_event\". Expected " + "string to send."); + return -1; + } + keybinding->data.c = strdup(saveptr); } else if(strcmp(action, "time") == 0) { keybinding->action = KEYBINDING_SHOW_TIME; } else if(strcmp(action, "nextscreen") == 0) { diff --git a/parse.h b/parse.h index 2949315..d78df94 100644 --- a/parse.h +++ b/parse.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef PARSE_H diff --git a/release-non-auto-checks/Bugs.md b/release-non-auto-checks/Bugs.md index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/Bugs.md +++ b/release-non-auto-checks/Bugs.md @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/FAQ.md b/release-non-auto-checks/FAQ.md index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/FAQ.md +++ b/release-non-auto-checks/FAQ.md @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/SECURITY.md b/release-non-auto-checks/SECURITY.md index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/SECURITY.md +++ b/release-non-auto-checks/SECURITY.md @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/WLR_XDG_VERSION b/release-non-auto-checks/WLR_XDG_VERSION index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/WLR_XDG_VERSION +++ b/release-non-auto-checks/WLR_XDG_VERSION @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/acknowledge-contributors b/release-non-auto-checks/acknowledge-contributors new file mode 100644 index 0000000..8e6104c --- /dev/null +++ b/release-non-auto-checks/acknowledge-contributors @@ -0,0 +1,2 @@ +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/archwiki b/release-non-auto-checks/archwiki new file mode 100644 index 0000000..8e6104c --- /dev/null +++ b/release-non-auto-checks/archwiki @@ -0,0 +1,2 @@ +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/changelog-major-minor b/release-non-auto-checks/changelog-major-minor index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/changelog-major-minor +++ b/release-non-auto-checks/changelog-major-minor @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/internal-wiki b/release-non-auto-checks/internal-wiki index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/internal-wiki +++ b/release-non-auto-checks/internal-wiki @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/release-note b/release-non-auto-checks/release-note index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/release-note +++ b/release-non-auto-checks/release-note @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/reproducibility-checked b/release-non-auto-checks/reproducibility-checked index 5f93ac2..8e6104c 100644 --- a/release-non-auto-checks/reproducibility-checked +++ b/release-non-auto-checks/reproducibility-checked @@ -1,2 +1,2 @@ -2.1.2 -2023-04-24 +2.3.1 +2024-01-27 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 5f93ac2..8e6104c 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.1.2 -2023-04-24 +2.3.1 +2024-01-27 diff --git a/release-non-auto-checks/version-restrictions b/release-non-auto-checks/version-restrictions new file mode 100644 index 0000000..8e6104c --- /dev/null +++ b/release-non-auto-checks/version-restrictions @@ -0,0 +1,2 @@ +2.3.1 +2024-01-27 diff --git a/scripts/adjust-epoch b/scripts/adjust-epoch index 362c840..14b935c 100755 --- a/scripts/adjust-epoch +++ b/scripts/adjust-epoch @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT if [[ -n ${MESON_SOURCE_ROOT} ]] diff --git a/scripts/create-release-artefacts b/scripts/create-release-artefacts index 4b16167..05212a5 100755 --- a/scripts/create-release-artefacts +++ b/scripts/create-release-artefacts @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT if [[ -n ${MESON_SOURCE_ROOT} ]] diff --git a/scripts/create-signatures b/scripts/create-signatures index 3292374..958825f 100755 --- a/scripts/create-signatures +++ b/scripts/create-signatures @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT if [[ -n ${MESON_SOURCE_ROOT} ]] diff --git a/scripts/fuzz b/scripts/fuzz index 7f227ec..e90e17a 100755 --- a/scripts/fuzz +++ b/scripts/fuzz @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT readonly fuzzing_corpus="${1}" diff --git a/scripts/git-tag b/scripts/git-tag index bd8e541..4b5dbbc 100755 --- a/scripts/git-tag +++ b/scripts/git-tag @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT readonly gpg_id="${1}" diff --git a/scripts/install-development-environment b/scripts/install-development-environment old mode 100644 new mode 100755 index 1b71ce5..b799eec --- a/scripts/install-development-environment +++ b/scripts/install-development-environment @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT sudo pacman -Syu --noconfirm git grep sed xorg-xev meson ninja clang gcc shellcheck jq openbsd-netcat gnupg binutils alacritty wlroots wayland wayland-protocols libxkbcommon cairo pango fontconfig libinput libevdev pkgconf scdoc systemd-libs # systemd-libs is included because of libudev diff --git a/scripts/output-hashes b/scripts/output-hashes index cf7cacf..d18088b 100755 --- a/scripts/output-hashes +++ b/scripts/output-hashes @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT if [[ -n ${MESON_SOURCE_ROOT} ]] diff --git a/scripts/set-version b/scripts/set-version index 3ee035c..3f7875e 100755 --- a/scripts/set-version +++ b/scripts/set-version @@ -1,9 +1,7 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT -# TODO man pages - if [[ -n ${MESON_SOURCE_ROOT} ]] then # shellcheck disable=2164 diff --git a/seat.c b/seat.c index cd085be..a011251 100644 --- a/seat.c +++ b/seat.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200812L @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -59,10 +59,10 @@ update_capabilities(const struct cg_seat *seat) { /* Hide cursor if the seat doesn't have pointer capability. */ if(((caps & WL_SEAT_CAPABILITY_POINTER) == 0) || seat->enable_cursor == false) { - wlr_cursor_set_image(seat->cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_unset_image(seat->cursor); } else { - wlr_xcursor_manager_set_cursor_image(seat->xcursor_manager, - DEFAULT_XCURSOR, seat->cursor); + wlr_cursor_set_xcursor(seat->cursor, seat->xcursor_manager, + DEFAULT_XCURSOR); } } @@ -95,7 +95,7 @@ new_touch(struct cg_seat *seat, struct cg_input_device *input_device) { if(wlr_touch->output_name != NULL) { struct cg_output *output; wl_list_for_each(output, &seat->server->outputs, link) { - if(strcmp(wlr_touch->output_name, output->wlr_output->name) == 0) { + if(strcmp(wlr_touch->output_name, output->name) == 0) { wlr_cursor_map_input_to_output(seat->cursor, device, output->wlr_output); break; @@ -133,8 +133,7 @@ new_pointer(struct cg_seat *seat, struct cg_input_device *input_device) { if(wlr_pointer->output_name != NULL) { struct cg_output *output; wl_list_for_each(output, &seat->server->outputs, link) { - if(strcmp(wlr_pointer->output_name, output->wlr_output->name) == - 0) { + if(strcmp(wlr_pointer->output_name, output->name) == 0) { wlr_cursor_map_input_to_output(seat->cursor, device, output->wlr_output); break; @@ -169,7 +168,7 @@ handle_modifier_event(struct wlr_input_device *device, struct cg_seat *seat) { wlr_seat_set_keyboard(seat->seat, keyboard); wlr_seat_keyboard_notify_modifiers(seat->seat, &keyboard->modifiers); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } void @@ -205,12 +204,11 @@ handle_command_key_bindings(struct cg_server *server, xkb_keysym_t sym, &server->scene->tree.node, server->seat->cursor->x, server->seat->cursor->y, &sx, &sy); if(server->seat->enable_cursor) { - wlr_xcursor_manager_set_cursor_image(server->seat->xcursor_manager, - "left_ptr", - server->seat->cursor); + wlr_cursor_set_xcursor(server->seat->cursor, + server->seat->xcursor_manager, "left_ptr"); if(node && node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer( + wlr_scene_surface_try_from_buffer( wlr_scene_buffer_from_node(node)); if(scene_surface != NULL) { surface = scene_surface->surface; @@ -239,7 +237,7 @@ handle_command_key_bindings(struct cg_server *server, xkb_keysym_t sym, } message_clear(group->seat->server->curr_output); run_action((*keybinding)->action, server, (*keybinding)->data); - wlr_idle_notify_activity(server->idle, server->seat->seat); + wlr_idle_notifier_v1_notify_activity(server->idle, server->seat->seat); return true; } else if(mode != 0) { run_action(KEYBINDING_NOOP, server, (union keybinding_params){NULL}); @@ -312,7 +310,7 @@ handle_key_event(struct cg_keyboard_group *group, struct cg_seat *seat, event->keycode, event->state); } - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -589,7 +587,7 @@ handle_touch_down(struct wl_listener *listener, void *data) { uint32_t serial = 0; if(node && node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer(wlr_scene_buffer_from_node(node)); + wlr_scene_surface_try_from_buffer(wlr_scene_buffer_from_node(node)); if(scene_surface != NULL) { serial = wlr_seat_touch_notify_down( seat->seat, scene_surface->surface, event->time_msec, @@ -603,7 +601,7 @@ handle_touch_down(struct wl_listener *listener, void *data) { seat->touch_ly = ly; } - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -616,7 +614,7 @@ handle_touch_up(struct wl_listener *listener, void *data) { } wlr_seat_touch_notify_up(seat->seat, event->time_msec, event->touch_id); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -638,7 +636,7 @@ handle_touch_motion(struct wl_listener *listener, void *data) { if(node && node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer(wlr_scene_buffer_from_node(node)); + wlr_scene_surface_try_from_buffer(wlr_scene_buffer_from_node(node)); if(scene_surface != NULL) { wlr_seat_touch_point_focus(seat->seat, scene_surface->surface, @@ -657,7 +655,7 @@ handle_touch_motion(struct wl_listener *listener, void *data) { seat->touch_ly = ly; } - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -665,7 +663,7 @@ handle_cursor_frame(struct wl_listener *listener, void *_data) { struct cg_seat *seat = wl_container_of(listener, seat, cursor_frame); wlr_seat_pointer_notify_frame(seat->seat); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -676,7 +674,7 @@ handle_cursor_axis(struct wl_listener *listener, void *data) { wlr_seat_pointer_notify_axis(seat->seat, event->time_msec, event->orientation, event->delta, event->delta_discrete, event->source); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -686,7 +684,7 @@ handle_cursor_button(struct wl_listener *listener, void *data) { wlr_seat_pointer_notify_button(seat->seat, event->time_msec, event->button, event->state); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -701,7 +699,7 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time) { if(node && node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_surface *scene_surface = - wlr_scene_surface_from_buffer(wlr_scene_buffer_from_node(node)); + wlr_scene_surface_try_from_buffer(wlr_scene_buffer_from_node(node)); if(scene_surface != NULL) { surface = scene_surface->surface; if(surface != NULL) { @@ -722,7 +720,7 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time) { drag_icon_update_position(drag_icon); } - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); /* Check if cursor switched tile */ struct wlr_output *c_outp = wlr_output_layout_output_at( @@ -733,34 +731,39 @@ process_cursor_motion(struct cg_seat *seat, uint32_t time) { break; } } - struct cg_tile *c_tile; - bool first = true; - for(c_tile = cg_outp->workspaces[cg_outp->curr_workspace]->focused_tile; - first || - c_tile != cg_outp->workspaces[cg_outp->curr_workspace]->focused_tile; - c_tile = c_tile->next) { - first = false; - double ox = seat->cursor->x, oy = seat->cursor->y; - wlr_output_layout_output_coords(seat->server->output_layout, c_outp, - &ox, &oy); - if(c_tile->tile.x <= ox && c_tile->tile.y <= oy && - c_tile->tile.x + c_tile->tile.width >= ox && - c_tile->tile.y + c_tile->tile.height >= oy) { - break; + if(c_outp) { + struct cg_tile *c_tile; + bool first = true; + for(c_tile = cg_outp->workspaces[cg_outp->curr_workspace]->focused_tile; + first || + c_tile != + cg_outp->workspaces[cg_outp->curr_workspace]->focused_tile; + c_tile = c_tile->next) { + first = false; + double ox = seat->cursor->x, oy = seat->cursor->y; + wlr_output_layout_output_coords(seat->server->output_layout, c_outp, + &ox, &oy); + if(c_tile->tile.x <= ox && c_tile->tile.y <= oy && + c_tile->tile.x + c_tile->tile.width >= ox && + c_tile->tile.y + c_tile->tile.height >= oy) { + break; + } } + if(seat->cursor_tile != NULL && seat->cursor_tile != c_tile && + seat->server->running) { + ipc_send_event( + seat->server, + "{\"event_name\":\"cursor_switch_tile\",\"old_output\":" + "\"%s\",\"old_output_id\":%d," + "\"old_tile\":%d,\"new_output\":\"%s\",\"new_output_" + "id\":%d,\"new_tile\":%d}", + seat->cursor_tile->workspace->output->name, + output_get_num(seat->cursor_tile->workspace->output), + seat->cursor_tile->id, c_outp->name, output_get_num(cg_outp), + c_tile->id); + } + seat->cursor_tile = c_tile; } - if(seat->cursor_tile != NULL && seat->cursor_tile != c_tile) { - ipc_send_event(seat->server, - "{\"event_name\":\"cursor_switch_tile\",\"old_output\":" - "\"%s\",\"old_output_id\":%d," - "\"old_tile\":%d,\"new_output\":\"%s\",\"new_output_" - "id\":%d,\"new_tile\":%d}", - seat->cursor_tile->workspace->output->wlr_output->name, - output_get_num(seat->cursor_tile->workspace->output), - seat->cursor_tile->id, c_outp->name, - output_get_num(cg_outp), c_tile->id); - } - seat->cursor_tile = c_tile; } static void @@ -772,7 +775,7 @@ handle_cursor_motion_absolute(struct wl_listener *listener, void *data) { wlr_cursor_warp_absolute(seat->cursor, &event->pointer->base, event->x, event->y); process_cursor_motion(seat, event->time_msec); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -783,7 +786,7 @@ handle_cursor_motion(struct wl_listener *listener, void *data) { wlr_cursor_move(seat->cursor, &event->pointer->base, event->delta_x, event->delta_y); process_cursor_motion(seat, event->time_msec); - wlr_idle_notify_activity(seat->server->idle, seat->seat); + wlr_idle_notifier_v1_notify_activity(seat->server->idle, seat->seat); } static void @@ -915,6 +918,7 @@ handle_destroy(struct wl_listener *listener, void *_data) { wl_list_remove(&seat->request_set_cursor.link); wl_list_remove(&seat->request_set_selection.link); wl_list_remove(&seat->request_set_primary_selection.link); + seat->server->seat = NULL; free(seat); } @@ -1043,6 +1047,7 @@ seat_set_focus(struct cg_seat *seat, struct cg_view *view) { view_activate(prev_view, false); } wlr_seat_keyboard_clear_focus(wlr_seat); + process_cursor_motion(seat, -1); return; } @@ -1094,9 +1099,8 @@ seat_set_focus(struct cg_seat *seat, struct cg_view *view) { wlr_scene_node_raise_to_top(&view->scene_tree->node); process_cursor_motion(seat, -1); - struct wlr_box box; - wlr_output_layout_get_box(server->output_layout, - view->workspace->output->wlr_output, &box); - wlr_scene_node_set_position(&view->workspace->output->bg->node, box.x, - box.y); + wlr_scene_node_set_position( + &view->workspace->output->bg->node, + output_get_layout_box(view->workspace->output).x, + output_get_layout_box(view->workspace->output).y); } diff --git a/seat.h b/seat.h index 74f4092..135c06a 100644 --- a/seat.h +++ b/seat.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_SEAT_H diff --git a/server.c b/server.c index c50f528..98c7630 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L @@ -43,8 +43,7 @@ server_show_info(struct cg_server *server) { return NULL; } output_str_tmp = output_str; - output_str = malloc_vsprintf("%s\t * %s\n", output_str, - output->wlr_output->name); + output_str = malloc_vsprintf("%s\t * %s\n", output_str, output->name); free(output_str_tmp); } char *input_str = strdup(""), *input_str_tmp; diff --git a/server.h b/server.h index 9f6eca6..3224174 100644 --- a/server.h +++ b/server.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_SERVER_H @@ -26,17 +26,22 @@ struct cg_server { struct cg_seat *seat; struct cg_input_manager *input; struct wlr_backend *backend; - struct wlr_idle *idle; + struct wlr_idle_notifier_v1 *idle; struct wlr_idle_inhibit_manager_v1 *idle_inhibit_v1; struct wl_listener new_idle_inhibitor_v1; + struct wlr_gamma_control_manager_v1 *gamma_control; + struct wl_listener gamma_control_set_gamma; struct wl_list inhibitors; struct wlr_output_layout *output_layout; + struct wlr_scene_output_layout *scene_output_layout; struct wl_list disabled_outputs; struct wl_list outputs; struct cg_output *curr_output; struct wl_listener new_output; struct wl_list output_priorities; + struct wlr_backend *headless_backend; + struct wlr_session *session; struct wlr_renderer *renderer; struct wlr_allocator *allocator; diff --git a/signatures/2.1.2-cagebreak-config.5.sig b/signatures/2.1.2-cagebreak-config.5.sig new file mode 100644 index 0000000..93f0f2b Binary files /dev/null and b/signatures/2.1.2-cagebreak-config.5.sig differ diff --git a/signatures/2.1.2-cagebreak-socket.7.sig b/signatures/2.1.2-cagebreak-socket.7.sig new file mode 100644 index 0000000..6797b53 Binary files /dev/null and b/signatures/2.1.2-cagebreak-socket.7.sig differ diff --git a/signatures/2.1.2-cagebreak.1.sig b/signatures/2.1.2-cagebreak.1.sig new file mode 100644 index 0000000..feaa1b9 Binary files /dev/null and b/signatures/2.1.2-cagebreak.1.sig differ diff --git a/signatures/2.1.2-cagebreak.sig b/signatures/2.1.2-cagebreak.sig new file mode 100644 index 0000000..4e3a176 Binary files /dev/null and b/signatures/2.1.2-cagebreak.sig differ diff --git a/signatures/2.2.1-cagebreak-config.5.sig b/signatures/2.2.1-cagebreak-config.5.sig new file mode 100644 index 0000000..4a959e1 Binary files /dev/null and b/signatures/2.2.1-cagebreak-config.5.sig differ diff --git a/signatures/2.2.1-cagebreak-socket.7.sig b/signatures/2.2.1-cagebreak-socket.7.sig new file mode 100644 index 0000000..c2006c1 Binary files /dev/null and b/signatures/2.2.1-cagebreak-socket.7.sig differ diff --git a/signatures/2.2.1-cagebreak.1.sig b/signatures/2.2.1-cagebreak.1.sig new file mode 100644 index 0000000..cdbd781 Binary files /dev/null and b/signatures/2.2.1-cagebreak.1.sig differ diff --git a/signatures/2.2.1-cagebreak.sig b/signatures/2.2.1-cagebreak.sig new file mode 100644 index 0000000..f24848b Binary files /dev/null and b/signatures/2.2.1-cagebreak.sig differ diff --git a/signatures/2.2.2-cagebreak-config.5.sig b/signatures/2.2.2-cagebreak-config.5.sig new file mode 100644 index 0000000..811fe37 Binary files /dev/null and b/signatures/2.2.2-cagebreak-config.5.sig differ diff --git a/signatures/2.2.2-cagebreak-socket.7.sig b/signatures/2.2.2-cagebreak-socket.7.sig new file mode 100644 index 0000000..e46522f Binary files /dev/null and b/signatures/2.2.2-cagebreak-socket.7.sig differ diff --git a/signatures/2.2.2-cagebreak.1.sig b/signatures/2.2.2-cagebreak.1.sig new file mode 100644 index 0000000..36b2c99 Binary files /dev/null and b/signatures/2.2.2-cagebreak.1.sig differ diff --git a/signatures/2.2.2-cagebreak.sig b/signatures/2.2.2-cagebreak.sig new file mode 100644 index 0000000..ca4ae14 Binary files /dev/null and b/signatures/2.2.2-cagebreak.sig differ diff --git a/signatures/2.2.3-cagebreak-config.5.sig b/signatures/2.2.3-cagebreak-config.5.sig new file mode 100644 index 0000000..6d7f6c1 Binary files /dev/null and b/signatures/2.2.3-cagebreak-config.5.sig differ diff --git a/signatures/2.2.3-cagebreak-socket.7.sig b/signatures/2.2.3-cagebreak-socket.7.sig new file mode 100644 index 0000000..5e37733 Binary files /dev/null and b/signatures/2.2.3-cagebreak-socket.7.sig differ diff --git a/signatures/2.2.3-cagebreak.1.sig b/signatures/2.2.3-cagebreak.1.sig new file mode 100644 index 0000000..14ac7ab Binary files /dev/null and b/signatures/2.2.3-cagebreak.1.sig differ diff --git a/signatures/2.2.3-cagebreak.sig b/signatures/2.2.3-cagebreak.sig new file mode 100644 index 0000000..b061305 Binary files /dev/null and b/signatures/2.2.3-cagebreak.sig differ diff --git a/signatures/2.3.0-cagebreak-config.5.sig b/signatures/2.3.0-cagebreak-config.5.sig new file mode 100644 index 0000000..fdbf9e3 Binary files /dev/null and b/signatures/2.3.0-cagebreak-config.5.sig differ diff --git a/signatures/2.3.0-cagebreak-socket.7.sig b/signatures/2.3.0-cagebreak-socket.7.sig new file mode 100644 index 0000000..274e8e5 Binary files /dev/null and b/signatures/2.3.0-cagebreak-socket.7.sig differ diff --git a/signatures/2.3.0-cagebreak.1.sig b/signatures/2.3.0-cagebreak.1.sig new file mode 100644 index 0000000..8ed93af Binary files /dev/null and b/signatures/2.3.0-cagebreak.1.sig differ diff --git a/signatures/2.3.0-cagebreak.sig b/signatures/2.3.0-cagebreak.sig new file mode 100644 index 0000000..e106209 Binary files /dev/null and b/signatures/2.3.0-cagebreak.sig differ diff --git a/signatures/cagebreak-config.5.sig b/signatures/cagebreak-config.5.sig index f96713d..62cebfa 100644 Binary files a/signatures/cagebreak-config.5.sig and b/signatures/cagebreak-config.5.sig differ diff --git a/signatures/cagebreak-socket.7.sig b/signatures/cagebreak-socket.7.sig index fec631f..aef73c0 100644 Binary files a/signatures/cagebreak-socket.7.sig and b/signatures/cagebreak-socket.7.sig differ diff --git a/signatures/cagebreak.1.sig b/signatures/cagebreak.1.sig index 7894766..3bcca8b 100644 Binary files a/signatures/cagebreak.1.sig and b/signatures/cagebreak.1.sig differ diff --git a/signatures/cagebreak.sig b/signatures/cagebreak.sig index d729d10..a6fd9dd 100644 Binary files a/signatures/cagebreak.sig and b/signatures/cagebreak.sig differ diff --git a/test/arguments b/test/arguments index 3112ca4..c4a0c35 100644 --- a/test/arguments +++ b/test/arguments @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT testdir="${MESONCURRENTCONFIGDIR}/_build-arguments/" diff --git a/test/build-w-o-warnings b/test/build-w-o-warnings index 3866aff..5a34ddd 100644 --- a/test/build-w-o-warnings +++ b/test/build-w-o-warnings @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/build-w-o-xwayland b/test/build-w-o-xwayland index 6164f6e..04752ff 100644 --- a/test/build-w-o-xwayland +++ b/test/build-w-o-xwayland @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/check-artefacts b/test/check-artefacts index 9e62bb5..077e1c7 100644 --- a/test/check-artefacts +++ b/test/check-artefacts @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/clang-format b/test/clang-format index cf7e553..a7db76f 100644 --- a/test/clang-format +++ b/test/clang-format @@ -1,5 +1,5 @@ #! /bin/sh -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT readonly declared_deps="${*}" diff --git a/test/copyright-license b/test/copyright-license index 630f843..1297607 100644 --- a/test/copyright-license +++ b/test/copyright-license @@ -1,5 +1,5 @@ #! /bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT readonly declared_deps="${*}" @@ -21,7 +21,7 @@ RESULT=0 for file in ${deps} do echo "${file}" - if (grep -q "Copyright.*${curryear}, project-repo and the cagebreak contributors" "$MESONCURRENTCONFIGDIR/${file}") + if (grep -q "Copyright.*${curryear}, project-repo.* and the cagebreak contributors" "$MESONCURRENTCONFIGDIR/${file}") then echo " [x] Copyright Notice" else diff --git a/test/environment-variables b/test/environment-variables index f1c9fac..b11b693 100644 --- a/test/environment-variables +++ b/test/environment-variables @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT testdir="${MESONCURRENTCONFIGDIR}/_build-envvars" @@ -22,7 +22,7 @@ cp "${MESONCURRENTCONFIGDIR}/test/testing-configurations/config" "${testdir}/env sed -i "s|CONFIGPATH|$testdir\/envvars\/socket|g" "${testdir}/envvars/config" (WLR_BACKENDS=headless ./cagebreak -e -c "${testdir}/envvars/config") sync -[[ ! $(cat "${testdir}/socket") = "${oldsocket}" ]] || RESULT=1 +[[ $(cat "${testdir}/envvars/socket") != "${oldsocket}" ]] || RESULT=1 # XDG_CONFIG_HOME cp "${MESONCURRENTCONFIGDIR}/test/testing-configurations/env-var-config" "${testdir}/cagebreak/config" diff --git a/test/git-tag b/test/git-tag index f080060..ad48009 100644 --- a/test/git-tag +++ b/test/git-tag @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT VERSION=$1 diff --git a/test/gpg-signatures b/test/gpg-signatures index c5d63fd..e424048 100644 --- a/test/gpg-signatures +++ b/test/gpg-signatures @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/gpg-validity b/test/gpg-validity index 6340105..5fc8fb3 100644 --- a/test/gpg-validity +++ b/test/gpg-validity @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 @@ -7,31 +7,31 @@ RESULT=0 # shellcheck disable=2164 cd "${MESONCURRENTCONFIGDIR}/keys" stoday=$(date +%s) -signingmargin=90 +signingmargin=120 # shellcheck disable=2046 -skey11exptime=$(date --date=$(gpg --show-keys cagebreak_signing_key_11\@project-repo.co.pub | tail -2 | head -1 | cut -d " " -f 8 | rev | cut -c2- | rev) '+%s') +skey13exptime=$(date --date=$(gpg --show-keys cagebreak_signing_key_13\@project-repo.co.pub | tail -2 | head -1 | cut -d " " -f 8 | rev | cut -c2- | rev) '+%s') # shellcheck disable=2046 -skey12exptime=$(date --date=$(gpg --show-keys cagebreak_signing_key_12\@project-repo.co.pub | tail -2 | head -1 | cut -d " " -f 8 | rev | cut -c2- | rev) '+%s') +skey14exptime=$(date --date=$(gpg --show-keys cagebreak_signing_key_14\@project-repo.co.pub | tail -2 | head -1 | cut -d " " -f 8 | rev | cut -c2- | rev) '+%s') # shellcheck disable=2046 mailexptime=$(date --date=$(gpg --show-keys cagebreak\@project-repo.co.pub | tail -2 | head -1 | cut -d " " -f 8 | rev | cut -c2- | rev) '+%s') # signing keys -## signing key 11 -if [[ $(( (stoday - skey11exptime) / 86400 )) -lt $signingmargin ]] +## signing key 13 +if [[ $(( (stoday - skey13exptime) / 86400 )) -lt $signingmargin ]] then - echo "[x] signign key 11" + echo "[x] signign key 13" else RESULT=1 - echo "[ ] signing key 11" + echo "[ ] signing key 13" fi -## signing key 12 -if [[ $(( (stoday - skey12exptime) / 86400 )) -lt $signingmargin ]] +## signing key 14 +if [[ $(( (stoday - skey14exptime) / 86400 )) -lt $signingmargin ]] then - echo "[x] signign key 12" + echo "[x] signign key 14" else RESULT=1 - echo "[ ] signing key 12" + echo "[ ] signing key 14" fi # email key diff --git a/test/hashes-md b/test/hashes-md index 30a5529..a768a30 100644 --- a/test/hashes-md +++ b/test/hashes-md @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT VERSION=$1 diff --git a/test/illegal-strings b/test/illegal-strings index 5ae9dc0..4c885d3 100644 --- a/test/illegal-strings +++ b/test/illegal-strings @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 @@ -8,7 +8,7 @@ RESULT=0 cd "${MESONCURRENTCONFIGDIR}" # Check that no TODO statements remain in the release directory -if ! grep -Rq "TODO" . +if grep --exclude='test/illegal-strings' --exclude-dir='build' -Rn "TODO" ./** then echo "[x] TODO" else @@ -16,14 +16,4 @@ else echo "[ ] TODO" fi -# Check that Cagebreak does not falsely claim to be POSIX compliant -if ! grep -Rq "_POSIX_C_SOURCE" . -then - echo "[x] _POSIX_C_SOURCE" -else - RESULT=1 - echo "[ ] _POSIX_C_SOURCE" -fi - - exit "${RESULT}" diff --git a/test/man-pages b/test/man-pages new file mode 100644 index 0000000..bf4b96c --- /dev/null +++ b/test/man-pages @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright 2024, project-repo and the cagebreak contributors +# SPDX-License-Identifier: MIT + +RESULT=0 + +cd "${MESONCURRENTCONFIGDIR}" || exit 1 + +tail_license=$(tail -n 17 LICENSE) +tail_man1=$(tail -n 17 man/cagebreak.1.md) +tail_man5=$(tail -n 17 man/cagebreak-config.5.md) +tail_man7=$(tail -n 17 man/cagebreak-socket.7.md) + +[[ $tail_license = "$tail_man1" ]] || RESULT=1 +[[ $tail_license = "$tail_man5" ]] || RESULT=1 +[[ $tail_license = "$tail_man7" ]] || RESULT=1 + +if [[ $RESULT -eq 0 ]] +then +echo "[x] License ending" +else +echo "[ ] License ending" +fi + +for man_page in man/* +do + grep -q "$man_page" manuals.md || RESULT=1 +done + +if [[ $RESULT -eq 0 ]] +then +echo "[x] All man pages listed in manuals.md" +else +echo "[ ] All man pages listed in manuals.md" +fi + +exit "${RESULT}" diff --git a/test/non-auto-tests b/test/non-auto-tests index 470d494..524839c 100644 --- a/test/non-auto-tests +++ b/test/non-auto-tests @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT VERSION=$1 diff --git a/test/scan-build b/test/scan-build index 562fb42..aa59c21 100644 --- a/test/scan-build +++ b/test/scan-build @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/script-executability b/test/script-executability new file mode 100644 index 0000000..f73f325 --- /dev/null +++ b/test/script-executability @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright 2024, project-repo and the cagebreak contributors +# SPDX-License-Identifier: MIT +# Each example script must contain the header unmodified. + +# shellcheck disable=2164 +cd "${MESONCURRENTCONFIGDIR}" + +RESULT=0 + +example_all=$(find example_scripts/) +example_exec=$(find example_scripts/ -executable) +[[ $example_all = "$example_exec" ]] || RESULT=1 + +scripts_all=$(find scripts/) +scripts_exec=$(find scripts/ -executable) +[[ $scripts_all = "$scripts_exec" ]] || RESULT=1 + +exit $RESULT diff --git a/test/script-header b/test/script-header new file mode 100644 index 0000000..f172f3d --- /dev/null +++ b/test/script-header @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2024, project-repo and the cagebreak contributors +# SPDX-License-Identifier: MIT +# Each example script must contain the header unmodified. + +# shellcheck disable=2164 +cd "${MESONCURRENTCONFIGDIR}" + +RESULT=0 + +for file in example_scripts/* +do + # shellcheck disable=2002 + grep "$(cat test/testing-configurations/cb_script_header.sh | tail -n +3 | tr '\n' ' ' )" <(cat "$file" | tr '\n' ' ') || RESULT=1 +done + +exit $RESULT diff --git a/test/shellcheck b/test/shellcheck index 8fa5f4e..2f68c48 100644 --- a/test/shellcheck +++ b/test/shellcheck @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT RESULT=0 diff --git a/test/testing-configurations/-c-config b/test/testing-configurations/-c-config index a769e73..8476149 100644 --- a/test/testing-configurations/-c-config +++ b/test/testing-configurations/-c-config @@ -1,4 +1,4 @@ -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT exec (echo "SUCCESS" > CONFIGPATH ) quit diff --git a/example_scripts/cb_script_header.sh b/test/testing-configurations/cb_script_header.sh similarity index 89% rename from example_scripts/cb_script_header.sh rename to test/testing-configurations/cb_script_header.sh index 770f075..d844a0a 100644 --- a/example_scripts/cb_script_header.sh +++ b/test/testing-configurations/cb_script_header.sh @@ -1,7 +1,5 @@ -#!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT - named_pipe_send="$(mktemp -u)" named_pipe_recv="$(mktemp -u)" mkfifo "${named_pipe_send}" diff --git a/test/testing-configurations/config b/test/testing-configurations/config index 9925aec..268fe77 100644 --- a/test/testing-configurations/config +++ b/test/testing-configurations/config @@ -1,4 +1,4 @@ -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT exec (echo $CAGEBREAK_SOCKET > CONFIGPATH) quit diff --git a/test/testing-configurations/env-var-config b/test/testing-configurations/env-var-config index a769e73..8476149 100644 --- a/test/testing-configurations/env-var-config +++ b/test/testing-configurations/env-var-config @@ -1,4 +1,4 @@ -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT exec (echo "SUCCESS" > CONFIGPATH ) quit diff --git a/test/testing-configurations/my-scan-build b/test/testing-configurations/my-scan-build index 526f1dd..db3f3d0 100755 --- a/test/testing-configurations/my-scan-build +++ b/test/testing-configurations/my-scan-build @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT scan-build --status-bugs "$@" diff --git a/test/versions b/test/versions index b408c71..66b6d11 100644 --- a/test/versions +++ b/test/versions @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2023, project-repo and the cagebreak contributors +# Copyright 2023 - 2024, project-repo and the cagebreak contributors # SPDX-License-Identifier: MIT readonly newversion="${1}" diff --git a/util.c b/util.c index f8c7a82..1f84bdc 100644 --- a/util.c +++ b/util.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include diff --git a/util.h b/util.h index b509a00..b9a95ef 100644 --- a/util.h +++ b/util.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_UTIL_H diff --git a/view.c b/view.c index 99e2e7c..1d2d9c3 100644 --- a/view.c +++ b/view.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -81,11 +80,10 @@ void view_maximize(struct cg_view *view, struct cg_tile *tile) { view->ox = tile->tile.x; view->oy = tile->tile.y; - struct wlr_box box; - wlr_output_layout_get_box(view->server->output_layout, - view->workspace->output->wlr_output, &box); - wlr_scene_node_set_position(&view->scene_tree->node, view->ox + box.x, - view->oy + box.y); + wlr_scene_node_set_position( + &view->scene_tree->node, + view->ox + output_get_layout_box(view->workspace->output).x, + view->oy + output_get_layout_box(view->workspace->output).y); view->impl->maximize(view, tile->tile.width, tile->tile.height); view->tile = tile; wlr_scene_node_raise_to_top(&view->scene_tree->node); @@ -97,7 +95,7 @@ view_unmap(struct cg_view *view) { uint32_t id = view->id; uint32_t tile_id = 0; uint32_t ws = view->workspace->num; - char *output_name = view->workspace->output->wlr_output->name; + char *output_name = view->workspace->output->name; int output_id = output_get_num(view->workspace->output); pid_t pid = view->impl->get_pid(view); /* If the view is not mapped, do nothing */ @@ -171,11 +169,10 @@ view_map(struct cg_view *view, struct wlr_surface *surface, their own (x,y) coordinates in handle_wayland_surface_map. */ if(view->type == CG_XWAYLAND_VIEW && !xwayland_view_should_manage(view)) { wl_list_insert(&ws->unmanaged_views, &view->link); - struct wlr_box box; - wlr_output_layout_get_box(view->server->output_layout, - view->workspace->output->wlr_output, &box); - wlr_scene_node_set_position(&view->scene_tree->node, view->ox + box.x, - view->oy + box.y); + wlr_scene_node_set_position( + &view->scene_tree->node, + view->ox + output_get_layout_box(view->workspace->output).x, + view->oy + output_get_layout_box(view->workspace->output).y); } else #endif { @@ -193,8 +190,8 @@ view_map(struct cg_view *view, struct wlr_surface *surface, "{\"event_name\":\"view_map\",\"view_id\":%d,\"tile_id\":%d," "\"workspace\":%d,\"output\":\"%s\",\"output_id\":%d,\"view_pid\":%d}", view->id, tile_id, view->workspace->num + 1, - view->workspace->output->wlr_output->name, - output_get_num(view->workspace->output), view->impl->get_pid(view)); + view->workspace->output->name, output_get_num(view->workspace->output), + view->impl->get_pid(view)); } void diff --git a/view.h b/view.h index a3b61ed..b2ff05d 100644 --- a/view.h +++ b/view.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_VIEW_H @@ -28,6 +28,10 @@ struct cg_view { struct cg_tile *tile; struct wlr_scene_tree *scene_tree; + struct wl_listener destroy; + struct wl_listener unmap; + struct wl_listener map; + /* The view has a position in output coordinates. */ int ox, oy; diff --git a/workspace.c b/workspace.c index 3f84c6f..7d93183 100644 --- a/workspace.c +++ b/workspace.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L @@ -29,13 +29,8 @@ workspace_tile_update_view(struct cg_tile *tile, struct cg_view *view) { } } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif int full_screen_workspace_tiles(struct wlr_output_layout *layout, - struct wlr_output *output, struct cg_workspace *workspace, uint32_t *tiles_curr_id) { workspace->focused_tile = calloc(1, sizeof(struct cg_tile)); @@ -47,18 +42,15 @@ full_screen_workspace_tiles(struct wlr_output_layout *layout, workspace->focused_tile->prev = workspace->focused_tile; workspace->focused_tile->tile.x = 0; workspace->focused_tile->tile.y = 0; - struct wlr_box output_box; - wlr_output_layout_get_box(layout, output, &output_box); - workspace->focused_tile->tile.width = output_box.width; - workspace->focused_tile->tile.height = output_box.height; + workspace->focused_tile->tile.width = + output_get_layout_box(workspace->output).width; + workspace->focused_tile->tile.height = + output_get_layout_box(workspace->output).height; workspace_tile_update_view(workspace->focused_tile, NULL); workspace->focused_tile->id = *tiles_curr_id; ++(*tiles_curr_id); return 0; } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif struct cg_workspace * full_screen_workspace(struct cg_output *output) { @@ -72,16 +64,15 @@ full_screen_workspace(struct cg_output *output) { free(workspace); return NULL; } + workspace->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, - output->wlr_output, workspace, + if(full_screen_workspace_tiles(output->server->output_layout, workspace, &output->server->tiles_curr_id) != 0) { free(workspace); return NULL; } - workspace->output = output; return workspace; } @@ -102,10 +93,10 @@ void workspace_free_tiles(struct cg_workspace *workspace) { workspace->focused_tile->prev->next = NULL; while(workspace->focused_tile != NULL) { - if(workspace->output->server->running && - workspace->output->server->seat->cursor_tile == - workspace->focused_tile) { - workspace->output->server->seat->cursor_tile = NULL; + if(workspace->server->seat != NULL && + (!workspace->output->server->running || + workspace->focused_tile == workspace->server->seat->cursor_tile)) { + workspace->server->seat->cursor_tile = NULL; } struct cg_tile *next = workspace->focused_tile->next; free(workspace->focused_tile); diff --git a/workspace.h b/workspace.h index b669cec..83b41a1 100644 --- a/workspace.h +++ b/workspace.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_WORKSPACE_H @@ -33,7 +33,6 @@ struct cg_workspace * full_screen_workspace(struct cg_output *output); int full_screen_workspace_tiles(struct wlr_output_layout *layout, - struct wlr_output *output, struct cg_workspace *workspace, uint32_t *tiles_curr_id); void diff --git a/xdg_shell.c b/xdg_shell.c index afa3352..fa15ad0 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #define _POSIX_C_SOURCE 200809L @@ -23,12 +23,14 @@ static struct cg_view * popup_get_view(struct wlr_xdg_popup *popup) { while(true) { - if(popup->parent == NULL || - !wlr_surface_is_xdg_surface(popup->parent)) { + if(popup->parent == NULL) { return NULL; } struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_from_wlr_surface(popup->parent); + 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; @@ -51,10 +53,6 @@ xdg_decoration_handle_destroy(struct wl_listener *listener, void *data) { free(xdg_decoration); } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif static void xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { struct cg_xdg_decoration *xdg_decoration = @@ -65,21 +63,18 @@ xdg_decoration_handle_request_mode(struct wl_listener *listener, void *_data) { wlr_xdg_toplevel_decoration_v1_set_mode(xdg_decoration->wlr_decoration, mode); } -#if CG_HAS_FANALYZE -#pragma GCC diagnostic pop -#endif static void popup_unconstrain(struct cg_view *view, struct wlr_xdg_popup *popup) { struct wlr_box *popup_box = &popup->current.geometry; struct wlr_output_layout *output_layout = view->server->output_layout; - struct wlr_box view_output_box; - wlr_output_layout_get_box( - output_layout, view->workspace->output->wlr_output, &view_output_box); struct wlr_output *wlr_output = wlr_output_layout_output_at( - output_layout, view_output_box.x + view->ox + popup_box->x, - view_output_box.y + view->oy + popup_box->y); + output_layout, + output_get_layout_box(view->workspace->output).x + view->ox + + popup_box->x, + output_get_layout_box(view->workspace->output).y + view->oy + + popup_box->y); struct wlr_box output_box; wlr_output_layout_get_box(output_layout, wlr_output, &output_box); @@ -169,8 +164,9 @@ handle_xdg_shell_surface_request_fullscreen(struct wl_listener *listener, * they display in fullscreen mode, so we set it here. */ struct wlr_box layout_box; - wlr_output_layout_get_box(xdg_shell_view->view.server->output_layout, NULL, - &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); @@ -244,9 +240,10 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) { xdg_shell_view->xdg_surface = xdg_surface; xdg_shell_view->map.notify = handle_xdg_shell_surface_map; - wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->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->events.unmap, &xdg_shell_view->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 = @@ -265,7 +262,10 @@ handle_xdg_shell_surface_new(struct wl_listener *listener, void *data) { struct wlr_scene_tree *parent_scene_tree = NULL; struct wlr_xdg_surface *parent = - wlr_xdg_surface_from_wlr_surface(popup->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; diff --git a/xdg_shell.h b/xdg_shell.h index fd80b99..5f9456c 100644 --- a/xdg_shell.h +++ b/xdg_shell.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_XDG_SHELL_H diff --git a/xwayland.c b/xwayland.c index ece9e5a..5755148 100644 --- a/xwayland.c +++ b/xwayland.c @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #include "config.h" @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -42,8 +41,12 @@ xwayland_view_should_manage(const struct cg_view *view) { static pid_t get_pid(const struct cg_view *view) { struct wlr_xwayland_surface *surf = - wlr_xwayland_surface_from_wlr_surface(view->wlr_surface); - return surf->pid; + wlr_xwayland_surface_try_from_wlr_surface(view->wlr_surface); + if(surf == NULL) { + return -1; + } else { + return surf->pid; + } } static char * @@ -93,13 +96,11 @@ maximize(struct cg_view *view, int width, int height) { } } - struct wlr_box output_box; - wlr_output_layout_get_box(view->server->output_layout, - view->server->curr_output->wlr_output, - &output_box); - wlr_xwayland_surface_configure(xwayland_view->xwayland_surface, - view->ox + output_box.x, - view->oy + output_box.y, width, height); + wlr_xwayland_surface_configure( + xwayland_view->xwayland_surface, + view->ox + output_get_layout_box(view->server->curr_output).x, + view->oy + output_get_layout_box(view->server->curr_output).y, width, + height); wlr_xwayland_surface_set_maximized(xwayland_view->xwayland_surface, true); } @@ -135,12 +136,10 @@ handle_xwayland_surface_map(struct wl_listener *listener, void *_data) { wl_container_of(listener, xwayland_view, map); struct cg_view *view = &xwayland_view->view; if(!xwayland_view_should_manage(view)) { - struct wlr_output_layout *output_layout = view->server->output_layout; - struct wlr_box output_box; - wlr_output_layout_get_box( - output_layout, view->server->curr_output->wlr_output, &output_box); - view->ox = xwayland_view->xwayland_surface->x - output_box.x; - view->oy = xwayland_view->xwayland_surface->y - output_box.y; + view->ox = xwayland_view->xwayland_surface->x - + view->server->curr_output->layout_box.x; + view->oy = xwayland_view->xwayland_surface->y - + view->server->curr_output->layout_box.y; } view_map(view, xwayland_view->xwayland_surface->surface, @@ -154,8 +153,6 @@ handle_xwayland_surface_destroy(struct wl_listener *listener, void *_data) { wl_container_of(listener, xwayland_view, destroy); struct cg_view *view = &xwayland_view->view; - wl_list_remove(&xwayland_view->map.link); - wl_list_remove(&xwayland_view->unmap.link); wl_list_remove(&xwayland_view->destroy.link); wl_list_remove(&xwayland_view->request_fullscreen.link); xwayland_view->xwayland_surface = NULL; @@ -173,6 +170,25 @@ static const struct cg_view_impl xwayland_view_impl = { .destroy = destroy, }; +static void +handle_xwayland_surface_associate(struct wl_listener *listener, void *data) { + struct cg_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, associate); + struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface; + wl_signal_add(&xsurface->surface->events.unmap, &xwayland_view->unmap); + xwayland_view->unmap.notify = handle_xwayland_surface_unmap; + wl_signal_add(&xsurface->surface->events.map, &xwayland_view->map); + xwayland_view->map.notify = handle_xwayland_surface_map; +} + +static void +handle_xwayland_surface_dissociate(struct wl_listener *listener, void *data) { + struct cg_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, dissociate); + wl_list_remove(&xwayland_view->map.link); + wl_list_remove(&xwayland_view->unmap.link); +} + void handle_xwayland_surface_new(struct wl_listener *listener, void *data) { struct cg_server *server = @@ -190,10 +206,12 @@ handle_xwayland_surface_new(struct wl_listener *listener, void *data) { server); xwayland_view->xwayland_surface = xwayland_surface; - xwayland_view->map.notify = handle_xwayland_surface_map; - wl_signal_add(&xwayland_surface->events.map, &xwayland_view->map); - xwayland_view->unmap.notify = handle_xwayland_surface_unmap; - wl_signal_add(&xwayland_surface->events.unmap, &xwayland_view->unmap); + xwayland_view->associate.notify = handle_xwayland_surface_associate; + wl_signal_add(&xwayland_surface->events.associate, + &xwayland_view->associate); + xwayland_view->dissociate.notify = handle_xwayland_surface_dissociate; + wl_signal_add(&xwayland_surface->events.dissociate, + &xwayland_view->dissociate); xwayland_view->destroy.notify = handle_xwayland_surface_destroy; wl_signal_add(&xwayland_surface->events.destroy, &xwayland_view->destroy); xwayland_view->request_fullscreen.notify = diff --git a/xwayland.h b/xwayland.h index 71a0b7a..6661f0e 100644 --- a/xwayland.h +++ b/xwayland.h @@ -1,4 +1,4 @@ -// Copyright 2020 - 2023, project-repo and the cagebreak contributors +// Copyright 2020 - 2024, project-repo and the cagebreak contributors // SPDX-License-Identifier: MIT #ifndef CG_XWAYLAND_H @@ -13,6 +13,8 @@ struct cg_xwayland_view { struct wl_listener destroy; struct wl_listener unmap; struct wl_listener map; + struct wl_listener associate; + struct wl_listener dissociate; struct wl_listener request_fullscreen; };