Compare commits

...

8 commits

Author SHA1 Message Date
project-repo
ace4ff04c6 Release 2.3.1
* Unbreak build on FreeBSD (#74, 73 in Bugs.md)
    * Thanks to Jan Beich for pointing this out.
  * Add Issue 74 to Bugs.md (#71, was fixed in 2.3.0)
2024-01-27 16:50:27 +00:00
project-repo
d19c32d7a4 Release 2.3.0
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.

Bug Fixes:
  * Fix gamma control (72 in Bugs.md).
  * Add missing commands to example config.
  * Add message_config to dump output.

Example Scripts:
  * Add screenshot script.
  * Make example scripts standalone.

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.

Development Tooling:
  * Add new gpg keys (signed by the old ones).
  * Add PR template.
  * Add dev-FAQ.
  * Remove now-unnecessary fanalyzer pragmas.
2024-01-26 10:53:03 +00:00
project-repo
5dbefccb59 Release 2.2.3
- Fix positioning of outputs (#66)
- Fix version specification of wlroots (#65)
- Add version check to prevent #65 in the future
2023-12-05 14:42:22 +01:00
project-repo
61fb97b070 Release 2.2.2
- Adjust Cagebreak to wlroot 0.17
- Improve README & SECURITY.md
2023-12-04 12:22:24 +01:00
project-repo
61e7f8aeff Release 2.2.1
* Fix Issue 65 (fix calibration matrix)
    * Thanks to Oliver Friedmann for providing a PR
  * Fix minor inelegance in README
  * Adjust dependency versions
2023-08-21 09:33:36 +02:00
project-repo
d946b62a4c Release 2.2.0
- Add custom events
- Fix Issue 62 (#46 Github)
- Fix Issue 63 (environment variables test)
- Fix Issue 64 (pointer focus bug)
2023-05-31 21:38:43 +02:00
project-repo
9a4c07d815 Release 2.1.2
- Adjust release procedure
- Fix Issue 60 in Bugs.md (Thanks to Tom Greig)
- Fix Issue 61 in Bugs.md
2023-04-24 22:57:42 +02:00
project-repo
bea18c7a6f Release 2.1.1
- Adjust dependency versions
- Add release tests
- Add a quick installation script
- Add small utility scripts
- Add note on review and developer certificate of origin (DCO)
- Add note on accessibility
2023-04-17 22:17:06 +02:00
146 changed files with 3170 additions and 1323 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
build
fuzz_corpus
fuzzing-directory

151
Bugs.md
View file

@ -1170,3 +1170,154 @@ leading to a termination of cagebreak.
* Fixed: 2.1.0
Prior to release 2.1.0 `meson install` did not work perfectly.
## Issue 60
* github issue number: N/A
* Fixed: 2.1.2
In the `merge_output_configs` function, when copying the properties of
one config to another, the `angles` element of an input structure was
being copied to the `status` element of the resultant structure.
## Issue 61
* github issue number: N/A
* Fixed: 2.1.2
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.

464
CONTRIBUTING.md Normal file
View file

@ -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

View file

@ -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

37
FAQ.md
View file

@ -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

160
Hashes.md
View file

@ -1,5 +1,165 @@
# 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
* sha 512: 9429bace89affdd9f7e83f48168c1e119d1531a5eb9a320299924e469c0e43052e93580aee6ba5f4c2b878e5b85ec5fc4cf172940cb4c1d950329c175898b647
2.1.2 cagebreak.1
* sha 256: aec69b06cc8dd4328027a04a12847c91b6a176537cce7a6c2d68a4f004cdd47c
* sha 512: 1d6e882a1fa8bec84df189cd32a1ac8953fb61d0241b04296ecb8caadfc55733947037b3810ba28b73e2a32bc30dfd68794dd173220e1f8af8ba9d3d02abe19e
2.1.2 cagebreak-config.5
* sha 256: 36e11b9d4437485a9671e72b3f6cc5669fb6a5b67b60198ee310efd6f3f3b093
* sha 512: 8378924d81c2c35ddfeace15debafb0407fbbe76513f7a488815a1421ff1c49d7aa7f21812573043004a8fd4e481242fd6970be270fac8007771623ed8d92208
2.1.2 cagebreak-socket.7
* sha 256: 346f8e203210a1542ca31980628095dbfb267764e3c2228457dc5b0b43850fda
* sha 512: 84e40072c71a38449ec6a5409445458405009010ee47d3e26ba13f6fd13f0291e1c3b38f5e84ba5521b14955bd97ab6d1c636b72a093b6322d0879f98218ab7f
2.1.1 cagebreak
* sha 256: 8632e7e49637e5a3e7ab425a05fbd63d71cf6025143c89d196f309dbf4efdd57
* sha 512: ca853aca80bde974f00e4cfcb21a77159d2f9f639342e92d049a0c5290a57094a1b2b1f28ac76ebdf89cf76384bb1caca45813d25ba5ef8ba8996e8c10e51e7a
2.1.1 cagebreak.1
* sha 256: 1d56762bcbe4ba5b9015dda3c19ab1d628d08c7a7c731042643c9f2e59cf3a7c
* sha 512: e421da32e8d6f9eec4559c53614427900fd7ae5c17bf9b9fdfa90764017d5d90c08e10e737aacbe46ed97966dbc4c76944b54bce367925fd9899ff8e41fa7947
2.1.1 cagebreak-config.5
* sha 256: f4405bd650d4cab29e536651f0d45443ebe51628c4dfef75576923ec903d781e
* sha 512: 451c85c7a02f724824499a43929ef6f05eee4d4c666186f766163c01e36503a36b7f6bbf2d5cb632cbd2cd0740b0b3becc2d8c388e914cb0bacfe6134a6ada92
2.1.1 cagebreak-socket.7
* sha 256: cd67c9de727d6f8727269bc06a80aa77ede26b5652eb4ab35c898939711ae429
* sha 512: a572710972b19a3872269fd2c52f1afd09a11dd621b4108f6ec3cde383c088c52782d5a240b001328257a66143a045fbf967d327b434e2ca32c2ffafc3b18b7f
2.1.0 cagebreak
* sha 256: 0c90ba529ffc916306a1ca04d4c56a800c62a98d184d3cfcc2ce67dcdffad324

View file

@ -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

572
README.md
View file

@ -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.0)](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,339 +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.
### 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.
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 wl-roots 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`
* [ ] New semantic version number determined
* [ ] Adjust version number
* [ ] meson.build
* [ ] git tag
* [ ] Relevant Documentation completed
* [ ] New features
* [ ] man pages
* [ ] cagebreak
* [ ] cagebreak-config
* [ ] cagebreak-socket
* [ ] example config
* [ ] Set EPOCH to release day in man generation in meson.build
* [ ] FAQ.md
* [ ] Changelog.md for major and minor releases but not patches
* [ ] Check features for SECURITY.md relevance (changes to socket scope
for example)
* [ ] Synchronize any socket changes to cagebreak-socket man page
* [ ] Updated internal wiki
* [ ] Added new files to meson.build or hardcoded testing variable
* [ ] Fixed bugs documented in Bugs.md
* [ ] Include issue discussion from github, where applicable
* [ ] Testing
* [ ] Manual testing
* [ ] Libfuzzer testing
* [ ] Arch Build System is up to date
* [ ] wlr_xdg_shell version check
* [ ] Cagebreak is reproducible on multiple machines
* [ ] Documented reproducible build artefacts
* [ ] Hashes of the artefacts in Hashes.md
* [ ] Renamed previous signatures
* [ ] Created gpg signature of the artefacts
* [ ] `gpg --detach-sign -u keyid cagebreak`
* [ ] `gpg --detach-sign -u keyid cagebreak.1`
* [ ] `gpg --detach-sign -u keyid cagebreak-config.5`
* [ ] `gpg --detach-sign -u keyid cagebreak-socket.7`
* [ ] `meson test -C build`
* [ ] `git add` relevant files
* [ ] `git commit`
* [ ] `git push origin development`
* [ ] Determined commit and tag message (Start with "Release version_number\n\n")
* [ ] Mentioned fixed Bugs.md issues ("Fixed Issue n")
* [ ] Mentioned other important changes
* [ ] `git checkout master`
* [ ] `git merge --squash development`
* [ ] `git commit` and insert message
* [ ] `git tag -u keyid version HEAD` and insert message
* [ ] `git tag -v version` and check output
* [ ] `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`
* [ ] `git archive --prefix=cagebreak/ -o release_version.tar.gz tags/version .`
* [ ] Create release-artefacts_version.tar.gz
* [ ] `mkdir release-artefacts_version`
* [ ] `cp build/cagebreak release-artefacts_version/`
* [ ] `cp build/cagebreak.sig release-artefacts_version/`
* [ ] `cp build/cagebreak.1 release-artefacts_version/`
* [ ] `cp build/cagebreak.1.sig release-artefacts_version/`
* [ ] `cp build/cagebreak-config.5 release-artefacts_version/`
* [ ] `cp build/cagebreak-config.5.sig release-artefacts_version/`
* [ ] `cp build/cagebreak-socket.7 release-artefacts_version/`
* [ ] `cp build/cagebreak-socket.7.sig release-artefacts_version/`
* [ ] `cp LICENSE release-artefacts_version/`
* [ ] `cp README.md release-artefacts_version/`
* [ ] `cp SECURITY.md release-artefacts_version/`
* [ ] `cp FAQ.md release-artefacts_version/`
* [ ] `export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) ; tar --sort=name --mtime= --owner=0 --group=0 --numeric-owner -czf release-artefacts_version.tar.gz release-artefacts_version`
* [ ] Checked archive
* [ ] tar -xvf release_version.tar.gz
* [ ] cd cagebreak
* [ ] meson setup build -Dxwayland=true -Dman-pages=true --buildtype=release
* [ ] ninja -C build
* [ ] gpg --verify ../signatures/cagebreak.sig build/cagebreak
* [ ] cd ..
* [ ] rm -rf cagebreak
* [ ] `gpg --detach-sign -u keyid release_version.tar.gz`
* [ ] `gpg --detach-sign -u keyid release-artefacts_version.tar.gz`
* [ ] Upload archives and signatures as release assets
## Roadmap
Cagebreak plans to do or keep doing the following things
@ -545,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
@ -568,37 +212,39 @@ 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.
We strive to increase the bus factor to at least 2 in all
aspects.
### Governance Issues
## Accessibility
Anyone can use the information in [SECURITY.md](SECURITY.md) to
contact the members of project-repo and bring governance
issues to their attention.
* We use text input/output to interact with the user whenever possible. For
example, sending text-based commands to the cagebreak sockets allows
one to change every configurable feature of cagebreak.
* Color is displayed but never a vital part to operating cagebreak.
* Text size can be increased and background color adjusted using text commands.
* There is no screen reader support per se but using a screen reader on socket output
would work and cagebreak does not preclude the use of a screen reader
for any software run with it.
## Bugs
For any bug, please [create an issue](https://github.com/project-repo/cagebreak/issues/new) on
[GitHub](https://github.com/project-repo/cagebreak).
[Open an issue](https://github.com/project-repo/cagebreak/issues/new) is you find something.
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.
See [SECURITY.md](SECURITY.md) for other means of contacting the Cagebreak authors and security issues.
For other means of contacting the Cagebreak authors and for security issues
see [SECURITY.md](SECURITY.md).
Fixed bugs are assigned a number and summarized in [Bugs.md](Bugs.md) for future reference.
## Contributors
@ -608,10 +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

View file

@ -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

View file

@ -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 <wayland-client.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/backend/headless.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
@ -26,8 +27,8 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_primary_selection_v1.h>
@ -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

67
docs/dev-FAQ.md Normal file
View file

@ -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.

View file

@ -0,0 +1,26 @@
# Description
<!-- Replace this with a description of your pull request. -->
<!-- Please reference any relevant issues, PRs etc. -->
## Type of Change
* [ ] Fix
* [ ] Backwards-compatible Feature
* [ ] Breaking Change
## Considerations
<!-- Replace this with a description of what might be missing, any points of confusion or -->
<!-- side effects you would like to point out. -->
## Credit
* [ ] I want to be credited as YOUR_NAME_OR_PSEUDONYM in your contributor section
* [ ] I don't want to be credited.
<!-- (by signing off, you state that you are allowed to contribute and allow us to publish -->
<!-- your contribution under the MIT License) -->
signed-off-by: YOUR_NAME_OR_PSEUDONYM

View file

@ -1,23 +0,0 @@
#!/bin/bash
# Copyright 2023, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
# This script uses the cagebreak socket to modify the compositor's behaviour in
# such a way that the currently focussed tile follows the cursor, i.e. that the
# currently focussed tile is always the one within which the cursor is located.
# Start up the ipc link
source "$(dirname "${BASH_SOURCE[0]}")/cb_script_header.sh"
while IFS= read -r -d $'\0' event
do
# Remove the cg-ipc header
event="${event:6}"
if [[ "$(echo "${event}" | jq ".event_name")" = "\"cursor_switch_tile\"" ]]
then
new_tile="$(echo "${event}"|jq -r ".new_tile")"
new_output_id="$(echo "${event}"|jq -r ".new_output_id")"
# Send the new tile to focus to cagebreak
echo -e "screen ${new_output_id}\nfocus_tile ${new_tile}" >&3
fi
done <&4

View file

@ -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}"

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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 <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_primary_selection_v1.h>
@ -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;

View file

@ -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

View file

@ -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

View file

@ -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 <wayland-server-core.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#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) {

View file

@ -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

1
img/archwiki.svg Normal file
View file

@ -0,0 +1 @@
<svg width="65.4" height="20" viewBox="0 0 654 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : Wiki</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="335" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="235" fill="#000" opacity="0.1">Wiki</text><text x="369" y="138" textLength="235">Wiki</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNCA1QzMuNDQ3NzIgNSAzIDUuNDQ3NzIgMyA2QzMgNi41NTIyOCAzLjQ0NzcyIDcgNCA3SDIwQzIwLjU1MjMgNyAyMSA2LjU1MjI4IDIxIDZDMjEgNS40NDc3MiAyMC41NTIzIDUgMjAgNUg0WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik00IDlDMy40NDc3MiA5IDMgOS40NDc3MiAzIDEwQzMgMTAuNTUyMyAzLjQ0NzcyIDExIDQgMTFIMTJDMTIuNTUyMyAxMSAxMyAxMC41NTIzIDEzIDEwQzEzIDkuNDQ3NzIgMTIuNTUyMyA5IDEyIDlINFoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJNMyAxNEMzIDEzLjQ0NzcgMy40NDc3MiAxMyA0IDEzSDIwQzIwLjU1MjMgMTMgMjEgMTMuNDQ3NyAyMSAxNEMyMSAxNC41NTIzIDIwLjU1MjMgMTUgMjAgMTVINEMzLjQ0NzcyIDE1IDMgMTQuNTUyMyAzIDE0WiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Ik00IDE3QzMuNDQ3NzIgMTcgMyAxNy40NDc3IDMgMThDMyAxOC41NTIzIDMuNDQ3NzIgMTkgNCAxOUgxMkMxMi41NTIzIDE5IDEzIDE4LjU1MjMgMTMgMThDMTMgMTcuNDQ3NyAxMi41NTIzIDE3IDEyIDE3SDRaIiBmaWxsPSIjZmZmIi8+PC9zdmc+"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

1
img/aur.svg Normal file
View file

@ -0,0 +1 @@
<svg width="65.1" height="20" viewBox="0 0 651 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : AUR</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="332" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="232" fill="#000" opacity="0.1">AUR</text><text x="369" y="138" textLength="232">AUR</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNy43NTczNSA1LjYzNjA1TDYuMzQzMTQgNy4wNTAyNkwxMiAxMi43MDcxTDE3LjY1NjkgNy4wNTAyOUwxNi4yNDI3IDUuNjM2MDhMMTIgOS44Nzg3Mkw3Ljc1NzM1IDUuNjM2MDVaIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTYuMzQzMTQgMTIuNzA3MUw3Ljc1NzM1IDExLjI5MjlMMTIgMTUuNTM1NkwxNi4yNDI3IDExLjI5MjlMMTcuNjU2OSAxMi43MDcxTDEyIDE4LjM2NEw2LjM0MzE0IDEyLjcwNzFaIiBmaWxsPSIjZmZmIi8+PC9zdmc+"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
img/contributing.svg Normal file
View file

@ -0,0 +1 @@
<svg width="82.2" height="20" viewBox="0 0 822 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : Contrib</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="503" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="403" fill="#000" opacity="0.1">Contrib</text><text x="369" y="138" textLength="403">Contrib</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjAuMjQgMTIuMjRhNiA2IDAgMCAwLTguNDktOC40OUw1IDEwLjVWMTloOC41eiIvPjxsaW5lIHgxPSIxNiIgeTE9IjgiIHgyPSIyIiB5Mj0iMjIiLz48bGluZSB4MT0iMTcuNSIgeTE9IjE1IiB4Mj0iOSIgeTI9IjE1Ii8+PC9zdmc+"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
img/faq.svg Normal file
View file

@ -0,0 +1 @@
<svg width="64.4" height="20" viewBox="0 0 644 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : FAQ</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="325" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="225" fill="#000" opacity="0.1">FAQ</text><text x="369" y="138" textLength="225">FAQ</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMiAzaDZhNCA0IDAgMCAxIDQgNHYxNGEzIDMgMCAwIDAtMy0zSDJ6Ii8+PHBhdGggZD0iTTIyIDNoLTZhNCA0IDAgMCAwLTQgNHYxNGEzIDMgMCAwIDEgMy0zaDd6Ii8+PC9zdmc+"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
img/mail.svg Normal file
View file

@ -0,0 +1 @@
<svg width="63.8" height="20" viewBox="0 0 638 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : Mail</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="319" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="219" fill="#000" opacity="0.1">Mail</text><text x="369" y="138" textLength="219">Mail</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNNCA0aDE2YzEuMSAwIDIgLjkgMiAydjEyYzAgMS4xLS45IDItMiAySDRjLTEuMSAwLTItLjktMi0yVjZjMC0xLjEuOS0yIDItMnoiLz48cG9seWxpbmUgcG9pbnRzPSIyMiw2IDEyLDEzIDIsNiIvPjwvc3ZnPg=="/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
img/manuals.svg Normal file
View file

@ -0,0 +1 @@
<svg width="87.1" height="20" viewBox="0 0 871 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : Manuals</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="552" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="452" fill="#000" opacity="0.1">Manuals</text><text x="369" y="138" textLength="452">Manuals</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMiAzaDZhNCA0IDAgMCAxIDQgNHYxNGEzIDMgMCAwIDAtMy0zSDJ6Ii8+PHBhdGggZD0iTTIyIDNoLTZhNCA0IDAgMCAwLTQgNHYxNGEzIDMgMCAwIDEgMy0zaDd6Ii8+PC9zdmc+"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

1
img/web-artefacts.svg Normal file
View file

@ -0,0 +1 @@
<svg width="75" height="20" viewBox="0 0 750 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : Mirror</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="431" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="331" fill="#000" opacity="0.1">Mirror</text><text x="369" y="138" textLength="331">Mirror</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7b3BhY2l0eTowO30uY2xzLTJ7ZmlsbDojZmZmO308L3N0eWxlPjwvZGVmcz48dGl0bGU+Zm9sZGVyPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iZm9sZGVyIj48ZyBpZD0iZm9sZGVyLTIiIGRhdGEtbmFtZT0iZm9sZGVyIj48cmVjdCBjbGFzcz0iY2xzLTEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTE5LjUsMjAuNUg0LjVBMi40NywyLjQ3LDAsMCwxLDIsMTguMDdWNS45M0EyLjQ3LDIuNDcsMCwwLDEsNC41LDMuNUg5LjFhMSwxLDAsMCwxLC43Ny4zN2wyLjYsMy4xOGg3QTIuNDcsMi40NywwLDAsMSwyMiw5LjQ4djguNTlBMi40NywyLjQ3LDAsMCwxLDE5LjUsMjAuNVoiLz48L2c+PC9nPjwvZz48L3N2Zz4="/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
img/web-open-issue.svg Normal file
View file

@ -0,0 +1 @@
<svg width="84.4" height="20" viewBox="0 0 844 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img"><title> : + Issue</title><g><rect fill="#4a414e" width="319" height="200"/><rect fill="#3373cc" x="319" width="525" height="200"/></g><g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110"><text x="240" y="148" textLength="39" fill="#000" opacity="0.1"></text><text x="230" y="138" textLength="39"></text><text x="379" y="148" textLength="425" fill="#000" opacity="0.1">+ Issue</text><text x="369" y="138" textLength="425">+ Issue</text></g><image x="50" y="35" width="130" height="132" xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7b3BhY2l0eTowO30uY2xzLTJ7ZmlsbDojZmZmO308L3N0eWxlPjwvZGVmcz48dGl0bGU+Z2l0aHViPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iZ2l0aHViIj48cmVjdCBjbGFzcz0iY2xzLTEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjQgMjQpIHJvdGF0ZSgxODApIi8+PGcgaWQ9ImdpdGh1Yi0yIiBkYXRhLW5hbWU9ImdpdGh1YiI+PGcgaWQ9Im1vYmlsZS0yIj48ZyBpZD0iR3JvdXAtOSI+PGcgaWQ9Ikdyb3VwLTExIj48cGF0aCBpZD0iRmlsbC0xIiBjbGFzcz0iY2xzLTIiIGQ9Ik0xMiwxQTEwLjg5LDEwLjg5LDAsMCwwLDEsMTEuNzcsMTAuNzksMTAuNzksMCwwLDAsOC41MiwyMmMuNTUuMS43NS0uMjMuNzUtLjUyczAtLjkzLDAtMS44M2MtMy4wNi42NS0zLjcxLTEuNDQtMy43MS0xLjQ0YTIuODYsMi44NiwwLDAsMC0xLjIyLTEuNThjLTEtLjY2LjA4LS42NS4wOC0uNjVhMi4zMSwyLjMxLDAsMCwxLDEuNjgsMS4xMSwyLjM3LDIuMzcsMCwwLDAsMy4yLjg5LDIuMzMsMi4zMywwLDAsMSwuNy0xLjQ0Yy0yLjQ0LS4yNy01LTEuMTktNS01LjMyQTQuMTUsNC4xNSwwLDAsMSw2LjExLDguMzFhMy43OCwzLjc4LDAsMCwxLC4xMS0yLjg0cy45My0uMjksMywxLjFhMTAuNjgsMTAuNjgsMCwwLDEsNS41LDBjMi4xLTEuMzksMy0xLjEsMy0xLjFhMy43OCwzLjc4LDAsMCwxLC4xMSwyLjg0QTQuMTUsNC4xNSwwLDAsMSwxOSwxMS4yYzAsNC4xNC0yLjU4LDUuMDUtNSw1LjMyYTIuNSwyLjUsMCwwLDEsLjc1LDJjMCwxLjQ0LDAsMi42LDAsMi45NXMuMi42My43NS41MkExMC44LDEwLjgsMCwwLDAsMjMsMTEuNzcsMTAuODksMTAuODksMCwwLDAsMTIsMSIvPjwvZz48L2c+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg=="/></svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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 <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
@ -11,7 +12,6 @@
#include <wlr/backend/session.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xcursor_manager.h>
@ -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;

View file

@ -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) \

View file

@ -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-----

View file

@ -0,0 +1,87 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=bl5A
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -0,0 +1,76 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGWUZaEBEACb84wE6iLL+FjnziWKDUR0zeYLth3x10UZS7Yu0zmrZOFlht4M
OQJ7Fr7aOAu30XRrNWKMaXov5kBIaggpg3vMGT4bL0yoeWoHc39mU2JL78pP1c08
H+I+KusCcsLtCT07k+YvUWCXYjRtSs/w14SS7Hj5CyMp4NNLqMRkLd4Hcd4CT5qp
PhlHAULVCEPsALk7krrNLG4XqAwvpvuWZR6FDgdxHHwpu2zI+43cfhZQ3XP88dk0
WGI+owoD+yYib2xY2+gU5IbHoVNUCF7Zdkf+5a2K1mYU4hkCGQQyx3LBKEa45BVF
I25uxBQ/elH9r02K3ppAdixqEs+RlL5VFudM3/Cdl04qfgHOxmkNJzSAiZlhoYHw
uta0o0ynFwYJIi1EUnOAFsrGeE0XcKeT7DXjbAsSqBm1lev7s4ueKvCgfnY5S06k
JhQZsVFnF7XxW6Ar+32AxEH+8fO1KQUJlenzIupPg03hx2zQ9BxaXnS+3rDzXDaF
kbFTaHz5ldU1DyqmHaFH9NEZH+2k2b45nmoc2Ts5D24g59+siJzb/mWk/iQCioJ/
pAFrDuEunHVoXMOlZ43cph3qAy7mjG+KnUY9QSIZl+SsHvJHUJXD3qJkoDPOwQI/
jro66de7U3WS28z1yPEr5jGkBgnPMEN35QbrGQ2tUPDJl12vJgvU24HpmQARAQAB
tENDYWdlYnJlYWsgU2lnbmluZyBLZXkgMTMgPGNhZ2VicmVha19zaWduaW5nX2tl
eV8xM0Bwcm9qZWN0LXJlcG8uY28+iQJXBBMBCABBFiEEQ4wn3bXRdGc99NZ7RRIF
s1KMfGMFAmWUZaECGwMFCQHhM4AFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AA
CgkQRRIFs1KMfGMwUQ//RJZp4b2DgtBlJv7tCXMt+qcUes1nSvVhbhtbfdPGa7K4
zh51UEYrhFz98fWAtER/ZRVouXNSpnnnR4fsqFP5yJDJWVbVFI7hnqcZ+SB4ojRz
5A6fnegv7CqgY7Ix8JH26eSahYwpSK2NDgs9ZUvUZk8RsOrke94wi/DaDQXVbnGr
Uz7/a+Umcg0P9J+3e1CVnTHu/u/NpyNmsqcc0LA6QNKwfZFKtfJ+Kv7xMkIsVIuZ
lnT5dcXYrTGDjf8IO+1Lr2ecg28ZAlyK69LFASvsnUA+WkUqlm1woZe7eimzRUhp
yD91d5R4mbrxoEWpU6atf6nam9o5qdr6a7P8iJXmx55oLe35kw7NIPKb9VAVq7Zb
Fz94F6xnfHNkWhUpiHWcXh3iJkHJgie2WrSstHJjRKpALr7VBhvNb7eykRpIkdnO
1D4J8Kjp2hRhPReRCoYHtkzixZYg9uxfODsm+rS1nj27R5Y6i0x4RXOdQcSs8V5j
eb+Lefd6xB7/SX4IkWsBr4f9wgiWL/ZVKvnOhMEaq0TuRb4KPFJ4aflTq7LvzMmG
wGqQaqzuWsxQdkB4BhfaPZlSrLkV6bOUhTAT25WbgiOsvDjhhUnItX3PR7T7Opcd
yzfVfJ+0cGm6os9wfZyOQ7aysBaBCQGn/aRlyOIbIdOO+WV0zfaNFeD20Z3le9mJ
AjMEEAEIAB0WIQROgscsaz5Yp7xP+FVJCfhMqDu4ZwUCZZV7BQAKCRBJCfhMqDu4
Z/acD/92MiqYEugEo8JszGNugJ6jpoNVSCP8RFiHR2uxyorPx0MCgGcrbUMgpdZc
gHaCyEWYD9vSOiut3g71H/iY6iACV8L5AaVkkodwKX+YKg0FASdVeu3uekNvHX4D
GwhX+LMr2E0QYe98mhffCUnuJbPNFY5Oj6eQEJ525t0JxOUHPJ6k3WvgW/lmVsik
oLVC5iQzz+z96bZ/J+bN0Fgd+bCy7eT3c2I+O0UjtrUr9vBCpW8J/EzkiWVAqaJg
0tTZOCiQmDTADoSw+g3AhxdU1ilnuB1VDLVhLmijsu51yt6JWeSsB3wU8ga3GpE3
HDbTBQji6aF6yt/zOtBVTsSNdfDrKUmb0FzfjdLKwUXfZjBaaXxM9LQLRkMqjnBX
+zqqkIqhRKgKbDT8y5Cq35I5rN6EjL8+Ck/LgeZ1x/wox0l6KLzu8H/rFHclt5VJ
0yAN0md9ZIDCmVqJQO7EVUQ3s1qU1rDrFjCZViJG9khBNvAZLkjnMx3BeJ9RJS2q
D3rMpk45A1Y88QS3fnttNGLHwp1sR6LW8FD1qyY0o1cQ09/b3JSkIiF3Bbl/X7Ze
qgm76Mj4nKcjfXtW15jdn78Hj7S2+yMcuyzexYSdsPVQONOuhkWaruoVH06RLTbT
MUQbgBaBfQqRaMyTzxkAL/u98seS0Limc9Gwtyttr2q1xy4i3IkCMwQQAQgAHRYh
BFrrGi6w0T9n4wasWdwMyBvgBv2FBQJllXtBAAoJENwMyBvgBv2Fc/YP/3dgkwXS
GOii3+rDFp+Xrz8Dp3fwFTjmpxsM+ODXsI0Yf2qVohkmzfrz3cDlpm+rpYu/Mp8/
Ss5b70XCbFZV4lnPz4jmiOchdcgsZcI29x4u78LPvl3gAVuOWyvcf1SrMFcRM+rh
YdEp/nugfPk1+9TOWUISUxrLCnR4a1ezg50p7C9TOiPAnLstog2p0rFYrmzBdH5V
EPU++Znyk0U9vqmH/99kkppY4SU6Pnph/w2at5N+WKLJ9djShaNwpedF5dWJArMj
Qlem0giTJb3WcKLYzWjhthYeASMg+j9SYVWC3Sgk6kRyBEZeWg7zO/v0ovnTATU5
34ABMkOTRYZr49qvUlrdleyN36uR7S9o+Gb+41q+EqHlVW4+eaFiNqN//WvuSG1a
9sNcDDOxTsEqSdhEpy1WCuHGnzlUk/VG2cI4xlNtDWbW4V0P/SYZ4BXasxdkHYCd
Hgg/81/PL57KlxyqzOEFOB/Fn6wPE/4ElFvcRhe3sLSbq+3OLHQLe/1Vc6Rxmwqx
KK34TWRZOW5/HM6KCyo6+YeEhaclV0q3GneGg/yvgO7AoMQG8nPxGFyLHgdlfeji
XEFIA4e4Z74N+Sx0GcyY41xTt9y3/Dg/WdJg6KO7Mqa4ecp44O+kPJz7Q8hZ6yS9
Pd74UjYivJ2caK5BUc6t3YnP0XSxsGLLkf51uQINBGWUZaEBEADLl3EO9ZabLHbE
dTESl23Q2MokmHRY69JMNTFhldq6zFjgu4lz1Q9a0YQJQEuXSGFh4h+JXTKHij6y
IJSE8LZcD7Epd0ko2hbF2etcflFV4j0/2SByfnHLt2oqauhUFCsZZeuTpguysRGI
mvjhGsCjYi9nBZA42AgukPC/sh1onuVKejYjIZLJKyR47gowJxRSbnOtuSTkppYW
e/EEF4FJsV35C0t1N1aMvtc5sidVwuaxSVGJflNMGaoKlvoIex+vK1LrSum0Ji3t
9QfAerYL1ZnyU8dZ63c870vyY0cxFegtv/d9qDohjiUqUYrZ1jIUdY4o/IvDSMhc
x3iSOB1CB3oIup66oNpnmGP6CAN7UpnnGIYjMWb4eAeVSOHMEEzxdwQl/BEg/K3z
IbRM1BdCv82WGx0no1FNE/PmFkboHAQMSV+3gbO58aQEBnOROfnxVTG9lK7Ey4uc
LrZs0nJsvOQxXemQvcTTPL/C2L7y3Hyf2wQO/2JC+Z7cINiYpRuYRS37gwmuC5ik
P6yu1uLUpjHGpDMPv9yAB4qNUAkfnBT7Et59P0TznnYONwRZ8fVf8KZ8H2HiwpeI
CjIASrfCRMu4VInKZALYgF0kaqsuZW6LcHYIJ3K4/1GhEfVTDTiRSz1MqtjjRfDw
Avu3aOe7y2UKEkOaqWDf9a/Zs85ucwARAQABiQI8BBgBCAAmFiEEQ4wn3bXRdGc9
9NZ7RRIFs1KMfGMFAmWUZaECGwwFCQHhM4AACgkQRRIFs1KMfGPg3w/9Hfu1haNG
v5CPojVlvfBWGhDdnQiqAAWuQpDwZIZB3CZ7HPBXAInH5J5dR/s3akZdwb6zvxdK
RuvbkIdw8hFWsc0M3tIIM3mWim9ctB3xYqC4O6gyFdqDNHk4B4j0xrbeSVgp+kPP
gV5J8rfegY09uxzPKlUgpIf8NRhdE/gLjm5nv1KrIe3G1Bk/0H7RhRkqug5rkAE8
TfLGrvXkYCWJ0BHU3mivBJt/NaAgj/SF0YbomRPFt5BJzYGU6EEyj+G6AIHrm4np
88/5ZAqxfb37wtucXJ+IcjHZsEBAuh61xMWHpgxlJ1246+G+FJM1aHlqGbWruNlo
R6dymqN/kMbN4nKWG3j8549Av03ltpzxaASf4vjDHZ0GziXCovnzGaF9Bt5wyG7v
TyaUBFxacdtKCgMzGidIvPVrTqLxSr7Dwn8Iz3oZp4yVZpldEuTP5OxA/OP55ym1
tAPEKVpa9Ui+R+5dwhRWzMxdZ7Ns0OrquFbZ6/rGafqie8fjVmEIoSjd0Ny+/40t
EGKSx//F90ZPS02ZRqy12rVV/i5Xyt38UCzlegFq9BAsz2IhXkUQSts0EAS3wE2Q
D+B+0RH+tcL4I8AzyE/LMpHBA7m1hi6kciCOHSzYANvuTJ3na6p0x6YBhcRkPgTD
XPUssBeVi6uNhWON/EjKc0cLAfNwuBrjj6I=
=5Ie4
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -0,0 +1,76 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
2rpj+N0DJVi3/r0GWYgBEzvO+yV1ly011sk=
=AVO4
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -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;
}
}

View file

@ -1,8 +1,8 @@
cagebreak-config(5) "Version 2.1.0" "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 <r> <g> <b>*
Set RGB of background - <[r|g|b]> are floating point numbers
*background <r\> <g\> <b\>*
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 <key> <command>*
Bind <key> to execute <command> if pressed in root mode
*bind <key\> <command\>*
Bind <key\> to execute <command\> if pressed in root mode
```
bind <key> <command>
@ -52,15 +51,17 @@ definekey root <key> <command>
Close current window - This may be useful for windows of
applications which do not offer any method of closing them.
*configure_message [font <font description>|[f|b]g_color <r> <g> b> <a>|display_time <n>]*
*configure_message [font <font description\>|[f|b]g_color <r\> <g\> <b\> <a\>|display_time <n\>|anchor <position\>]*
Configure message characteristics -
- font <font description> sets
- <font description> is
- X core font description or
- FreeType font description via pango
- fg_color <r> <g> <b> <a> sets RGBA of foreground
- bg_color <r> <g> <b> <a> sets RGBA of background
- display_time <n> sets display time in seconds
- font <font description\> sets the font of the message.
Here, <font description\> is either
- an X core font description or
- a FreeType font description via pango
- fg_color <r\> <g\> <b\> <a\> sets the RGBA of the foreground
- bg_color <r\> <g\> <b\> <a\> sets the RGBA of the background
- display_time <n\> sets the display time in seconds
- anchor <position\> sets the position of the message.
<position\> 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 <mode> <key> <command>*
Bind <key> to execute <command> if pressed in <mode> -
*custom_event <message\>*
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 <message\>.
See *cagebreak-socket(7)* for more details.
*definekey <mode\> <key\> <command\>*
Bind <key\> to execute <command\> if pressed in <mode\> -
*definekey* is a more general version of *bind*.
*definemode <mode>*
Define new mode <mode> - After a call to *definemode*,
<mode> can be used with *definekey* to create a custom key mapping.
*definemode <mode\>*
Define new mode <mode\> - After a call to *definemode*,
<mode\> 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 <key>*
Set <key> to switch to root mode to execute one command
*escape <key\>*
Set <key\> to switch to root mode to execute one command
```
escape <key>
@ -122,8 +131,8 @@ definekey top <key> mode root
*exchangeup*
Exchange current window with window in the tile to the top
*exec <command>*
Execute <command> using *sh -c*
*exec <command\>*
Execute <command\> using *sh -c*
*focus*
Focus next tile
@ -146,10 +155,10 @@ definekey top <key> mode root
*hsplit*
Split current tile horizontally
*input <identifier> <setting> <value>*
Set <setting> to <value> for device <identifier> -
<identifier> can be "\*" (wildcard), of the form
"type:<device_type>" or the identifier of the device as printed
*input <identifier\> <setting\> <value\>*
Set <setting\> to <value\> for device <identifier\> -
<identifier\> can be "\*" (wildcard), of the form
"type:<device_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 <key> 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 <key> 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|<event-code-or-name>*
*scroll_button disable|<event-code-or-name\>*
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 <floating point value>*
*scroll_factor <floating point value\>*
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 <n>*
*repeat_delay <n\>*
Repeat delay in ms for keyboards only
*repeat_rate <n>*
*repeat_rate <n\>*
Repeat rate in 1/s for keyboards only
*tap enabled|disabled*
@ -230,11 +239,11 @@ definekey top <key> mode root
middle click. _lmr_ treats 1 finger as left click, 2 fingers as
middle click, and 3 fingers as right click.
message <text>
message <text\>
Display a line of arbitrary text.
*mode <mode>*
Enter mode "<mode>" - Returns to default mode, after a command is
*mode <mode\>*
Enter mode "<mode\>" - Returns to default mode, after a command is
executed.
*movetonextscreen*
@ -245,12 +254,12 @@ message <text>
Move currently focused window to previous screen
See *output* for differences between screen and output.
*movetoscreen <n>*
Move currently focused window to <n>-th screen
*movetoscreen <n\>*
Move currently focused window to <n\>-th screen
See *output* for differences between screen and output.
*movetoworkspace <n>*
Move currently focused window to <n>-th workspace
*movetoworkspace <n\>*
Move currently focused window to <n\>-th workspace
See *output* for differences between screen and output.
*next*
@ -263,23 +272,32 @@ message <text>
*only*
Remove all splits and make current window fill the entire screen
*output <name> [[pos <xpos> <ypos> res <width>x<height> rate <rate> [scale <scale>]] | enable | disable | prio <n> | rotate <n>]*
Configure output "<name>" -
- <xpos> and <ypos> are the position of the
*output <name\> [[pos <xpos\> <ypos\> res <width\>x<height\> rate <rate\> [scale <scale\>]] | enable | disable | [permanent|peripheral] | prio <n\> | rotate <n\>]*
Configure output "<name\>" -
- <xpos\> and <ypos\> are the position of the
monitor in pixels. The top-left monitor should have the coordinates 0 0.
- <width> and <height> specify the resolution in pixels.
- <rate> sets the refresh rate of the monitor (often this is 50 or 60).
- <scale> sets the output scale (default is 1.0)
- enable and disable enable or disable <name>. Note that if
<output> is the only enabled output, *output <output> disable* has
- <width\> and <height\> specify the resolution in pixels.
- <rate\> sets the refresh rate of the monitor (often this is 50 or 60).
- <scale\> sets the output scale (default is 1.0)
- enable and disable enable or disable <name\>. Note that if
<output\> is the only enabled output, *output <output\> disable* has
no effect.
- prio <n> is used to set the priority of an output. If
- permanent sets <name\> 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 <name\> to peripheral, meaning that on
disconnecting the respective monitor, all views will be moved to another
available output. The default role is peripheral.
- prio <n\> 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 <n> it is possible
to set priorities for outputs, where <n> >= 1. The larger <n> is,
and have a numerical priority of -1. Using prio <n\> it is possible
to set priorities for outputs, where <n\> >= 1. The larger <n\> is,
the higher the priority is, that is to say, the earlier the output
will appear in the list of outputs.
- rotate <n> is used to rotate the output by `<n> mod 4 x 90` degrees
- rotate <n\> is used to rotate the output by `<n> mod 4 x 90` degrees
counter-clockwise.
```
@ -325,19 +343,19 @@ output DP-1 rotate 3
*resizeup*
Resize current tile towards the top
*screen <n>*
Change to <n>-th screen
*screen <n\>*
Change to <n\>-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 <mode>*
Set default mode to <mode>
*setmode <mode\>*
Set default mode to <mode\>
*switchvt <n>*
Switch to tty <n>
*switchvt <n\>*
Switch to tty <n\>
*time*
Display time
@ -345,11 +363,11 @@ output DP-1 rotate 3
*vsplit*
Split current tile vertically
*workspace <n>*
Change to <n>-th workspace
*workspace <n\>*
Change to <n\>-th workspace
*workspaces <n>*
Set number of workspaces to <n> - <n> is a single integer larger than 1
*workspaces <n\>*
Set number of workspaces to <n\> - <n\> 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:
<mod>-<key>
<mod\>-<key\>
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

View file

@ -1,8 +1,8 @@
cagebreak-socket(7) "Version 2.1.0" "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 <n> 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

View file

@ -1,4 +1,4 @@
cagebreak(1) "Version 2.1.0" "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

5
manuals.md Normal file
View file

@ -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)

View file

@ -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.0',
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')
@ -202,17 +202,17 @@ cagebreak_dependencies_dict = {
reproducible_build_versions = {
'server_protos': '-1',
'wayland_server': '1.19.0',
'wayland_client': '1.21.0',
'wayland_cursor': '1.21.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',
'wayland_client': '1.22.0',
'wayland_cursor': '1.22.0',
'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 = 1680540192
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')
@ -344,14 +344,48 @@ summary = [
]
message('\n'.join(summary))
run_target('devel-install',
command : ['scripts/install-development-environment'])
run_target('fuzz',
command : ['scripts/fuzz', get_option('corpus')])
run_target('adjust-epoch',
command : ['scripts/adjust-epoch'])
run_target('git-tag',
command : ['scripts/git-tag', get_option('gpg_id'), meson.project_version()])
run_target('output-hashes',
command : ['scripts/output-hashes', meson.project_version()])
run_target('create-sigs',
command : ['scripts/create-signatures', get_option('gpg_id')])
run_target('set-ver',
command : ['scripts/set-version', meson.project_version()])
run_target('create-artefacts',
command : ['scripts/create-release-artefacts', get_option('gpg_id'), meson.project_version()])
# 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('Scan-build (static analysis)', find_program('test/scan-build'), env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'devel-long')
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('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')
test('Signature validity', find_program('test/gpg-signatures'), suite: 'release')
test('Hashes.md', find_program('test/hashes-md'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')
test('Non-auto tests', find_program('test/non-auto-tests'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')
test('Git tag', find_program('test/git-tag'), args : [ meson.project_version() ], suite: 'release')
test('Release-artefacts', find_program('test/check-artefacts'), args : [ meson.project_version() ], env : [ ''.join('MESONCURRENTCONFIGDIR=', meson.current_source_dir()) ], suite: 'release')

View file

@ -1,6 +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: '438C27DDB5D174673DF4D67B451205B3528C7C63', description: 'Set gpg signing key for cagebreak')

106
message.c
View file

@ -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 <cairo/cairo.h>
@ -12,7 +12,6 @@
#include <wlr/render/allocator.h>
#include <wlr/render/drm_format_set.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/util/log.h>
@ -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);
}

View file

@ -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);

369
output.c
View file

@ -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 <wlr/backend/x11.h>
#endif
#include <wlr/backend/headless.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
#include <wlr/util/region.h>
#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;
@ -399,7 +517,7 @@ merge_output_configs(struct cg_output_config *cfg1,
out_cfg->scale = cfg1->scale;
}
if(cfg1->angle == out_cfg->angle) {
out_cfg->status = cfg2->angle;
out_cfg->angle = cfg2->angle;
} else {
out_cfg->angle = cfg1->angle;
}
@ -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

View file

@ -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

View file

@ -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 <cairo.h>

View file

@ -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

50
parse.c
View file

@ -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) {

View file

@ -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

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

View file

@ -0,0 +1,2 @@
2.3.1
2024-01-27

13
scripts/adjust-epoch Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
# shellcheck disable=2034
ssepoch=$(date +%s)
sed -i -e "/secssinceepoch \=/s/[0-9]*$/$ssepoch/" meson.build

View file

@ -0,0 +1,40 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
readonly gpg_id="${1}"
readonly version="${2}"
git archive --prefix=cagebreak/ -o "release_${version}.tar.gz" "tags/${version}" .
rm -rf "release-artefacts_${version}"
mkdir "release-artefacts_${version}"
rm -rf temp-rel-artefacts
meson setup temp-rel-artefacts -Dxwayland=true -Dman-pages=true --buildtype=release
ninja -C temp-rel-artefacts
cp LICENSE "release-artefacts_${version}"
cp SECURITY.md "release-artefacts_${version}"
cp FAQ.md "release-artefacts_${version}"
cp README.md "release-artefacts_${version}"
cp temp-rel-artefacts/cagebreak "release-artefacts_${version}"
cp temp-rel-artefacts/cagebreak.1 "release-artefacts_${version}"
cp temp-rel-artefacts/cagebreak-config.5 "release-artefacts_${version}"
cp temp-rel-artefacts/cagebreak-socket.7 "release-artefacts_${version}"
cp signatures/cagebreak*.sig "release-artefacts_${version}"
# shellcheck disable=2155
export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) ; tar --sort=name --mtime= --owner=0 --group=0 --numeric-owner -czf "release-artefacts_${version}.tar.gz" "release-artefacts_${version}"
gpg -u "${gpg_id}" --detach-sign "release-artefacts_${version}.tar.gz"
gpg -u "${gpg_id}" --detach-sign "release_${version}.tar.gz"
rm -rf temp-rel-artefacts

37
scripts/create-signatures Executable file
View file

@ -0,0 +1,37 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
readonly gpg_id="${1}"
# shellcheck disable=2155
readonly old_tags=$(git tag| tail -1)
mv signatures/cagebreak.sig "signatures/${old_tags}-cagebreak.sig"
mv signatures/cagebreak.1.sig "signatures/${old_tags}-cagebreak.1.sig"
mv signatures/cagebreak-config.5.sig "signatures/${old_tags}-cagebreak-config.5.sig"
mv signatures/cagebreak-socket.7.sig "signatures/${old_tags}-cagebreak-socket.7.sig"
git add "signatures/${old_tags}-cagebreak.sig"
git add "signatures/${old_tags}-cagebreak.1.sig"
git add "signatures/${old_tags}-cagebreak-config.5.sig"
git add "signatures/${old_tags}-cagebreak-socket.7.sig"
rm -rf temp-sigs
meson setup temp-sigs -Dxwayland=true -Dman-pages=true --buildtype=release
ninja -C temp-sigs
gpg -u "${gpg_id}" --detach-sign temp-sigs/cagebreak
gpg -u "${gpg_id}" --detach-sign temp-sigs/cagebreak.1
gpg -u "${gpg_id}" --detach-sign temp-sigs/cagebreak-config.5
gpg -u "${gpg_id}" --detach-sign temp-sigs/cagebreak-socket.7
cp temp-sigs/*.sig signatures/
rm -rf temp-sigs

17
scripts/fuzz Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
readonly fuzzing_corpus="${1}"
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
rm -rf fuzzing-directory
CC=clang meson setup fuzzing-directory -Dfuzz=true -Db_sanitize=address,undefined -Db_lundef=false -Db_detect-leaks=0
ninja -C fuzzing-directory/
WLR_BACKENDS=headless ./fuzzing-directory/fuzz-parse -jobs=12 -max_len=50000 -close_fd_mask=3 "${fuzzing_corpus}"
rm -rf fuzzing-directory

8
scripts/git-tag Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
readonly gpg_id="${1}"
readonly version="${2}"
git tag -u "${gpg_id}" "${version}" HEAD

View file

@ -0,0 +1,13 @@
#!/bin/bash
# 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
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
gpg --import keys/*

50
scripts/output-hashes Executable file
View file

@ -0,0 +1,50 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
readonly version="${1}"
rm -rf hashes
meson setup hashes -Dxwayland=true -Dman-pages=true --buildtype=release
ninja -C hashes
cb256=$(sha256sum hashes/cagebreak | cut -d " " -f1)
cb512=$(sha512sum hashes/cagebreak | cut -d " " -f1)
cb1man256=$(sha256sum hashes/cagebreak.1 | cut -d " " -f1)
cb1man512=$(sha512sum hashes/cagebreak.1 | cut -d " " -f1)
cb5man256=$(sha256sum hashes/cagebreak-config.5 | cut -d " " -f1)
cb5man512=$(sha512sum hashes/cagebreak-config.5 | cut -d " " -f1)
cb7man256=$(sha256sum hashes/cagebreak-socket.7 | cut -d " " -f1)
cb7man512=$(sha512sum hashes/cagebreak-socket.7 | cut -d " " -f1)
echo "${version} cagebreak
* sha 256: ${cb256}
* sha 512: ${cb512}
${version} cagebreak.1
* sha 256: ${cb1man256}
* sha 512: ${cb1man512}
${version} cagebreak-config.5
* sha 256: ${cb5man256}
* sha 512: ${cb5man512}
${version} cagebreak-socket.7
* sha 256: ${cb7man256}
* sha 512: ${cb7man512}
" > local-hashes.txt
rm -rf hashes

18
scripts/set-version Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
# Copyright 2023 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
if [[ -n ${MESON_SOURCE_ROOT} ]]
then
# shellcheck disable=2164
cd "${MESON_SOURCE_ROOT}"
fi
# shellcheck disable=2034
version="${1}"
sed -i -e "s/minversion\=[0-9]*\.[0-9]*.[0-9]*/minversion=$version/" README.md
sed -i -e "s/Version [0-9]*\.[0-9]*.[0-9]*/Version $version/" man/cagebreak.1.md
sed -i -e "s/Version [0-9]*\.[0-9]*.[0-9]*/Version $version/" man/cagebreak-config.5.md
sed -i -e "s/Version [0-9]*\.[0-9]*.[0-9]*/Version $version/" man/cagebreak-socket.7.md

120
seat.c
View file

@ -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 <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_scene.h>
@ -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);
}

2
seat.h
View file

@ -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

View file

@ -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;

View file

@ -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;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more