Compare commits

..

No commits in common. "master" and "1.7.2" have entirely different histories.

195 changed files with 3169 additions and 10530 deletions

2
.gitignore vendored
View file

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

980
Bugs.md
View file

@ -341,983 +341,3 @@ The advantages are:
Cagebreak has always used pandoc to compile man pages. Cagebreak now uses scdoc
instead.
### Issue 27
* github issue number: #8
* Fixed: 1.8.1
```
Apologies for opening two tickets instead of one, but I thought that these two suggestions are different enought they merit their own "issue".
Would replicating the behaviour in ratpoison (if no config file is found, load predefined defaults) something you would be interested in? I personally found confusing when I first tried cagebreak that it wouldn't start without a config file, coming from ratpoison. Of course, other people's experience might be different.
```
### Issue 28
* github issue number: #10
* Fixed: 1.8.2
```
I'm using v. 1.8.1 and am experiencing a screen refresh lag, particularly on Firefox:
When I type in anything, the text is refreshed and becomes visible only following mouse movement. I don't experience this with the same setup when I use Sway as the compositor.
```
Cagebreak had an error with damage tracking.
### Issue 29
* github issue number: #19
* Fixed: 1.9.0
bda65hp:
```
Hi,
Is there a way to easily change de font? "monospace 10" are too small for my eyes. I've changed them in message.c but can you add a configuration option, please?
Same for the display time of these window. They sometimes disappear too fast (mainly time).
May be a config for the background and foreground color of the message window too?
cagebreak is great :)
```
project-repo:
```
No, there is currently no easy way to change the font size, background or display
time of the message.
Adding these ideas as a command is a good idea though.
To summarize, the release pertaining to #19 will presumably introduce a
command for configuring the cagebreak messages. This command will be
able to set the following:
* [ ] Font size
* [ ] Font colour
* [ ] Background colour
* [ ] Display time of message
Another, related, idea would be to have an interface for sending
arbitrary messages over the socket which are then displayed by
cagebreak. This may also be added to the above features.
We're glad to hear that you enjoy cagebreak! Thank you for helping to
make it even greater.
cheers
project-repo
```
bda65hp:
```
Awesome :)
Displaying time in locale format (or configurable) will be great too ;)
```
project-repo:
```
Yes, once it is possible to send arbitrary messages via cagebreak over
the socket it will be possible to have the date be displayed however you
like!
cheers
project-repo
```
project-repo:
```
We pushed some code to development implementing this in 348925e (configuration) and f12a161 (message command). Sorry for not writing this much sooner. However, at least it will be part of the upcoming release.
cheers
project-repo
```
### Issue 30
* github issue number: #11
* Fixed: 1.9.0
kinleyd:
```
In my first post I forgot to thank you for cagebreak. I've been evaluating compositors for my needs and have been through kiwmi, japokwm, wayfire, sway and cagebreak. So far I like cagebreak most of all.
Back to my question:
You currently support 'movetonextscreen' but there is no equivalent movetoprevscreen.
For multiple 3 to 4 screen configurations the second command would be useful.
Also, is it not possible to move to a screen directly, like 'movetoscreen 3'?
The same thing with prevscreen and nextscreen: something like 'focusscreen 3', if it were possible, would be useful.
```
project-repo:
```
Thank you! It's great to hear that cagebreak seems to suit your needs.
About your question, yes, that absolutely makes sense. The reason this
wasn't implemented earlier is that no-one has needed it up to now, but
seeing as there now appears to be a use-case, we can definitely
implement these features. In future releases, cagebreak will then most
likely support movetoprevscreen and movetoscreen <n> (as these are
distinct functionalities).
The only issue I see at this point is that the numbering of screens is
not directly canonical. To resolve this, I suggest that per default,
screens are numbered according to the order in which they were added
along with an additional configuration option to specify numbering (this
would most likely be an additional option for the already existent
output command). Does that seem fine to you?
cheers,
project-repo
```
kinleyd:
```
Yes, that would be perfect. Thank you!
```
kinleyd:
```
May I suggest we also have 'screen <n>' like we have 'workspace <n>'.
```
project-repo:
```
Thank you for this suggestion. This will be implemented in the release
where the rest of this issue is resolved (probably the next one).
To summarize, presumably the release pertaining to #11 will include:
* [ ] movetoprevscreen as a command symmetric to movetonextscreen
* [ ] movetoscreen <n> as a command similar to movetoworkspace
* [ ] screen <n> as a command similar to workspace <n>
* [ ] additional output functionality for monitor numbering (of
course backwards-compatible, such that valid configs remain
valid)
If anything changes with regard to this draft, we will post it here so
you can let us know what you think.
cheers,
project-repo
```
kinleyd:
```
Super - I greatly look forward to their addition, and thank you for your responsiveness!
```
project-repo:
```
Everything mentioned on our last comment has now been implemented on the
development branch. (More specifically in 851a2f8,
though documentation was added later.)
The simple commands work as proposed in our previous comment.
The output command has a new feature called prio now, which you can call as follows:
output <name of the output> prio <n>
All outputs, regardless of configuration are added once they request to be added
and have a default priority of -1. Using prio, you can set priorities
greater than or equal to 1 for specific outputs and hence order your outputs
as you wish. Note that cagebreak -s might be useful while fiddling around
with this.
If you like, you can check it out on development and compile it for yourself.
If you're up to it we would be glad to know what you think about it,
especially when output prio is applied to your multi-screen setup and
regarding the readability of the cagebreak-config man page description of
output prio.
Please note that this is not a release yet and the development branch
might undergo changes.
cheers
project-repo
```
kinleyd:
```
I took the development branch for a swirl, and it looks good. Thank you!
Everything works as you had set out: screen, movetoscreen, movetoprevscreen and output screen prio all work as expected. The default screen position now reflects the prio settings and that's great.
I took a look at the updates to the man page as well and it looks quite clear.
So hey, thank you for the great work! I look forward to the incorporation of the new features in the master branch when it is ready.
Happy holidays and a happy new year!
```
### Issue 31
* github issue number: #25
* Fixed: 1.9.0
```
The configuration man page for the input send events setting is missing the events word:
diff --git man/cagebreak-config.5.md man/cagebreak-config.5.md
index 4eea4c5..c618314 100644
--- man/cagebreak-config.5.md
+++ man/cagebreak-config.5.md
@@ -123,7 +123,7 @@ by prepending a line with the # symbol.
*dwt enabled|disabled*
Enables or disables disable-while-typing for the specified input device.
- *enabled|disabled|disabled_on_external_mouse*
- + *events enabled|disabled|disabled_on_external_mouse*
Enables or disables send_events for specified input device. Disabling
send_events disables the input device.
Slightly off topic: I was hoping to use this setting to hide the mouse cursor, but it doesn't work. My embedded system must expose a pointer device even though none is connected, altough I can only infer that much because the system is very bare bones and I can't check. Is there a way to do that?
```
The word was omitted before 1.9.0. Mouse hiding was relegated to a new issue (#26).
### Issue 32
* github issue number: #24
* Fixed: 1.9.0
```
The wlr/xwayland.h include in output.c:32 is missing an #if CG_HAS_XWAYLAND guard, which breaks building without xwayland.
```
Cagebreak did not build without xwayland. This bug has been fixed and building
without xwayland has been added to the release checklist.
### Issue 33
* github issue number: #23
* Fixed: 1.9.0
Similar to djpohly/dwl#177. Xwayland works fine elsewhere: cage, hikari, kwinft, labwc, phoc, river, sway, wayfire.
```
$ cagebreak
[...]
00:00:00.085 [xwayland/server.c:92] Starting Xwayland on :0
00:00:00.116 [render/swapchain.c:105] Allocating new swapchain buffer
00:00:00.118 [render/allocator/gbm.c:142] Allocated 1280x720 GBM buffer (format 0x34325258, modifier 0x100000000000004)
00:00:00.118 [render/gles2/renderer.c:143] Created GL FBO for buffer 1280x720
00:00:00.160 [types/wlr_surface.c:748] New wlr_surface 0x880d81f80 (res 0x86f22d380)
00:00:00.165 [xwayland/server.c:243] waitpid for Xwayland fork failed: No child processes
(EE) failed to read Wayland events: Broken pipe
xterm: Xt error: Can't open display: :0
$ cc --version
FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)
Target: x86_64-unknown-freebsd13.0
Thread model: posix
InstalledDir: /usr/bin
$ pkg info -x cagebreak wayland wlroots
cagebreak-1.8.3
wayland-1.20.0
wayland-protocols-1.25
xwayland-devel-21.0.99.1.171
wlroots-0.15.1
```
## Issue 34
* github issue number: N/A
* Fixed: 1.9.0
Cagebreak crashed when a touch device was removed due to a call to
`wl_list_remove` on a pointer which was never initialized.
## Issue 35
* github issue number: N/A
* Fixed: 1.9.1
Cagebreak 1.9.0 broke the nextscreen and prevscreen functionality.
This issue was not present in earlier releases.
## Issue 36
* github issue number: N/A
* Fixed: 1.9.1
Cagebreak 1.9.0 broke the configure_message functionality.
This issue was not present in earlier releases.
## Issue 37
* github issue number: N/A
* Fixed: 1.9.1
Cagebreak 1.9.0 broke the screen/movetoscreen functionality.
This issue was not present in earlier releases.
## Issue 38
* github issue number: #31
* Fixed: 2.0.0
Cagebreak terminology was unclear up to and including 1.9.1.
The following are extracts from the github issue discussion:
kinleyd:
```
This isn't an issue per se, but concerns cagebreak terminology.
I won't try to cover the entire range of terms used but stick
to the ones that concern me at the moment:
OK, so I get the use of the terms 'output', 'workspace' and 'tile'.
So my question: In cagebreak, what exactly is a 'screen'? At the
moment, the use of nextscreen, prevscreen, movetoscreen,
movetonextscreen, movetoprevscreen all seem to suggest that
'screen' is the same as 'output'. If so, shouldn't all the
aforementioned commands have screen replaced with output?
eg. nextoutput, prevoutput, etc.
```
project-repo
```
You make an interesting point.
We have considered this and the tricky bit is that both output and *screen are
defined cagebreak commands. It would be difficult to merge these two
commands in a reasonable way (even with the freedom of breaking changes).
Additionally, there is a sort of informal symmetry between output and input
we would like to maintain.
Our current conclusion is that we will leave the commands unmodified.
The now ex-post defined distinction between output and *screen is that
the *screen stuff works with the natural number uniquely identifying the
output within a given cagebreak session (but not across sessions, "nextscreen"
and "prevscreen" do so internally by in-/decrementing this number), whereas
output always deals with an output name as does input with an input name.
Please feel free to point out any other inconsistencies in cagebreak or better
solutions than outlined above in this issue.
You can post your suggestions here.
We will close this issue once 2.0.0 is released where the points mentioned above
will be outlined in the documentation. Please leave it open in
the mean time. Afterwards, you may open a new issue.
cheers
project-repo
```
kinleyd:
```
> Our current conclusion is that we will leave the commands unmodified.
> The now ex-post defined distinction between output and *screen is
> that the *screen stuff works with the natural number uniquely
> identifying the output within a given cagebreak session (but not
> across sessions, "nextscreen" and "prevscreen" do so internally
> by in-/decrementing this number), whereas output always deals
> with an output name as does input with an input name.
That makes perfect sense. Additionally, I also realize that there
is the virtual display for which the concept of 'screen' as
distinct from 'output' is necessary as a screen could then be
a fraction of an output, or combine multiple outputs.
> We will close this issue once 2.0.0 is released where the points
> mentioned above will be outlined in the documentation. Please
> leave it open in the mean time. Afterwards, you may open a new issue.
Hey, I look forward to version 2.0.0!
```
project-repo:
```
We have now modified the cagebreak-config man page on the development
branch to clarify the relationship of output and the screen family of
commands.
Please let us know if anything can be improved in that regard.
cheers
project-repo
```
## Issue 39
* github issue number: #30
* Fixed: 2.0.0
Cagebreak 1.9.1 had an issue where clicks did not evoke
any response under some very specific circumstances.
This was remediated by switching Cagebreak to `wlr_scene`.
There was extensive discussion inside the github issue
but this is omitted here due to irrelevance.
## Issue 40
* github issue number: #20
* Fixed: 2.0.0
nor-0 proposed a more intuitive way to switch focus. This
is a breaking change and as such is introduced on a major
release.
Details are described in the github issue discussion, which
is reproduced here:
nor-0:
```
Hello,
I think switching focus is a bit confusing in some situations.
When focus is switched in a direction, it can end up diagonally
instead of the frame next to the previously focused one.
The minimal example for this is with four frames, but it
also applies in layouts with more than four of them.
Let´s say I press the keybindings for these actions:
`vsplit`, `hsplit`, `focusright`, `hsplit`.
This leaves me with a layout of four simple quarters:
> +-----+-----+
> | 1 | 2 |
> +-----+-----+
> | 3 | 4 |
> +-----+-----+
Now, using `focuslefton` frame 2 brings me to frame 3 instead
of one. Likewise, `focusright` on frame 3 brings me to frame
2 instead of frame 4.
As soon as I resize a width, switching works as expected and
desired. The oddness however reappears whenever the vertical
frame edges are realigned.
The same trouble happens when creating the layout with the
keybindings for `hsplit`, `vsplit`, `focusdown`, `vsplit`.
Now, focusing up from frame 3 brings me two frame 2 instead
of 1, and same with the symmetrical opposite again
(2 downwards is 3 instead of 4). Now resizing heights is what
helps until the horizontal edges are realigned.
As said before, similar things occur with more complex layouts.
I use those much less frequently of course, but intuitive
navigation is even more important then. In these two minimal
examples, reaching the frames 1 and 4 is also often more
tedious then necessary.
I understand this is due to the way the frames were created
and makes some sense in this regard. However, unless there
is some reason to keep this behavior (which disappears by
some resize options anyways), I´d suggest to change it to
be more intuitive.
I imagine an approach for this could be to determine the
frames center point and then looking for an adjacent frame
in horizontal (vertical) direction from there when
`focusright` or `focusleft` (`focusdown` or `focusup`) is used.
(Everything said about `focus[direction]` also applies to
`exchange[direction]`.)
```
project-repo:
```
Thanks for the suggestion! Yes, I agree that the current implementation
is not a very satisfying solution... The reason it is handled like this
is simply because it was easiest to implement. Fortunately however,
changing this should not require too much coding since the
determination of the tile to jump to is handled globally by a single
function for each direction.
I like your idea with considering the center of the frame and then
looking for the one adjacent to it which is at the height of the center,
since such a frame is always guaranteed to exist (unless we are at the
edge of the screen in which case there is nothing to jump to).
Of course, this would have to involve some kind of tie-breaking when
two adjacent frames share a border at the height of the center (which is
bound to occur often if you never resize the tiles). I'm currently
leaning towards simply taking the top/left one in this case (or some
similar scheme) but if anyone else has thoughts on this, we'd be glad to
hear!
Some notes:
* This would be a breaking change, so the version number would jump to 2.0.0.
* Also, due to limited developer capacity at the moment and
the ongoing porting of cagebreak to the wlr_scene API it may be a
while until we are able to implement this, so bear with us!
cheers
project-repo
```
project-repo:
```
We pushed some code to development implementing this in `ed5cca9`.
Sorry for not writing this much sooner.
To anyone who reads this: This feature will remain on the development
branch for some time, partially due to some unresolved xwayland and
wlr_scene bugs and partially to allow breaking changes. So if anyone
would like to see something changed, please feel free to let us know!
cheers
project-repo
```
## Issue 41
* github issue number: #12
* Fixed: 2.0.0
kinleyd raised the issue of changing the focussed screen
on mouse hover. The Cagebreak philosophy is completely
keyboard-oriented and this feature request was denied.
However, this line of inquiry led to the idea of implementing
an ipc socket which would report key events and an information
dump functionality which would enable almost arbitrary scripting.
Related Material:
- [cagebreak-config man page](man/cagebreak-config.md)
- [cagebreak-socket man page](man/cagebreak-socket.md)
- [scripting examples](https://github.com/project-repo/cagebreak/tree/development/example_scripts)
The github issue discussion is partially reproduced below:
kinleyd:
```
While fully recognizing - and appreciating - Cagebreak's keyboard orientation, would it be possible to accommodate support for screen change on mouse over? This would help avoid a series of key presses on multi-screen setups and improve overall ergonomics.
Thanks.
```
project-repo:
```
As you correctly recognised, cagebreak is designed to be completely
keyboard-oriented. However, I understand that for the multi-monitor
setup you describe it may be useful to have some kind of
mouse-compositor interaction. To accommodate this, we are considering
implementing a command which allows to obtain the current cagebreak
state from the ipc socket, including the current cursor position.
That way, by implementing a script which listens for cursor events
and acts accordingly, it should be possible to implement the behaviour
you describe externally (provided #11 is implemented as intended).
What do you think?
If you have any other ideas, don't hesitate to let us know!
cheers
project-repo
```
project-repo
```
There has been much talk about #12 and how it would improve all sorts of
use cases, once implemented. While much remains to be determined, we would
like to give an update.
First, #12 is secondary in priority to #11, which is presumably easier
to implement and much clearer in its scope.
Once implemented, cagebreak will communicate the state of at least the
following internal properties:
* [ ] Current cursor position (allowing setting of the current screen
as per navigating screens question and suggestion #11
* [ ] IDs for graphical programs along with position on screen
* [ ] IDs for tiles on particular screens
* [ ] Currently focussed tile, screen, etc.
* [ ] Events such as "new window", "screen split", etc.
In which format this information will be provided is yet to be
determined, but we are considering at least the following:
* full blob of data upon request via ipc socket
* partial information on events
To improve user experience, the release of #12 will include examples of
how to use the new API over the socket for real world use cases,
analogous to the current example config.
* [ ] Example script "Current screen follows cursor on click"
* [ ] Example script "Setup multi screen environment with graphical programs on
specific tiles"
Note that this is just the current state of planning,
the final properties of cagebreak are specified in the man pages upon
release and cagebreak is provided as is, as specified in the LICENSE.
cheers
project-repo
```
project-repo:
```
Some but not all features mentioned in our previous comment have now been implemented on
the development branch.
Information on current events is provided through the ipc socket
now. The types of events which are reported are still subject to change and the
feature is not yet documented but you may check it out nonetheless. Let
us know if there is any additional information you would like to obtain
for the different events.
Current format displayed on the socket is as follows:
'cg-ipc<4 bytes denoting message length><keyword denoting the type of the event>(<property1>:<value1>,<property2>:<value2>,...,<propertyn>:<valuen>)'
Consider it a proof of concept.
A full dump of the current cagebreak state is not yet possible.
Happy new year to you too!
cheers
project-repo
```
project-repo:
```
We pushed some code to development implementing the dump
functionality. This should contain the information you require since it
gives you the view currently focussed by the pointer from which you can
deduce the output the cursor is currently hovering over by looking up
the output on which the view is placed. Note that this only works when
the cursor is actually hovering over a view (i.e. not when it is on an
empty tile). Alternatively, you could read the cursor coordinates and
compare these with the coordinates of the different outputs, though atm
the coordinates of the outputs are not dumped (we aim to add this later).
To anyone who reads this: This feature will remain on the development
branch for some time, partially due to some unresolved xwayland and
wlr_scene bugs and partially to allow breaking changes
(removing/changing data outputted by dump and other information sent by
IPC). So if anyone would like to see something changed, please feel free
to let us know (either by posting here or opening a new issue)!
cheers
project-repo
```
## Issue 42
* github issue number: N/A
* Fixed: 2.0.0
When Cagebreak exited due to an error on startup, it was possible for
memory leaks to occur since `server.modes` was not freed correctly. The
same applies to the variable `name` in `input_manager.c`.
This bug was found using the scan-build utility.
## Issue 43
* github issue number: N/A
* Fixed: 2.0.0
In `keybinding_move_view_to_cycle_output`, it was previously possible for a
null pointer dereference to occur, when no view to be moved was focussed.
This bug was found using the scan-build utility.
## Issue 44
* github issue number: N/A
* Fixed: 2.0.0
`cg_input_reset_libinput_device` was removed as it was unused code.
This bug was found using the scan-build utility.
## Issue 45
* github issue number: N/A
* Fixed: 2.0.0
Various memory leaks in `parse_message_config`, `full_screen_workspace`
and `server_show_info` were fixed.
This bug was found using the scan-build utility.
## Issue 46
* github issue number: #33
* Fixed: 2.0.0
Cagebrak did not state in its FAQ how to use letters not found
on the current keyboards alphabet.
## Issue 47
* github issue number: #32
* Fixed: 2.0.0
Cagebreak did not state in its FAQ how programs can be launched.
## Issue 48
* github issue number: #16
* Fixed: 2.0.0
Cagebreak cursor sizes varied under some environmental circumstances.
Investigations showed that the cursor is set by the respective application
but environment variables are usually respected. This is now documented in
the FAQ.
## Issue 49
* github issue number: #3
* Fixed: 2.0.0
Cagebreak used to have no way to disable the interpretation of keybindings
for a specific keyboard, which was cumbersome for some applications. This
feature is now available
## Issue 50
* github issue number: #26
* Fixed: 2.0.0
Cagebreak used to have no way to hide the cursor. This is now possible.
## Issue 51
* github issue number: #7
* Fixed: 2.0.0
Cagebreak used to not change the cursor while waiting for a key. The cursor
is now a square in this state.
## Issue 52
* github issue number: N/A
* Fixed: 2.0.0
Cagebreak did not correctly apply some simple commands if they were simply
written in the configuration file.
Consider the example config file:
```
quit
```
Under these circumstances Cagebreak did not quit right after startup.
## Issue 53
* github issue number: #35
* Fixed: 2.0.0
Cagebreak did not build with wlroots 0.16.1 and this was adjusted.
## Issue 54
* github issue numer: #36
* Fixed: 2.0.1
Cagebreak was not compatible with clang 15 and POSIX which was causing issues
with building under FreeBSD.
Thanks to Jan Beich for pointing this out and providing a PR.
## Issue 55
* github issue number: N/A
* Fixed: 2.1.0
Prior to release 2.1.0, cagebreak sometimes crased due to a null pointer
derefrence when the cursor was moved.
## Issue 56
* github issue numner: N/A
* Fixed: 2.1.0
Prior to release 2.1.0, the following workflow caused cagebreak to
crash:
* Split an empty workspace.
* Open 2 windows on the left tile.
* exchangeright
* focus left
* cycle views
The reason for this is that the ipc send event did not handle
focussing the background correctly when cycling.
## Issue 57
* github issue number: #39
* Fixed: 2.1.0
maxhbr pointed out that there was a spelling mistake in the
SPDX-License-Identifier.
## Issue 58
* github issue number: #40
* Fixed: 2.1.0
Prior to version 2.1.0, the logic behind configuration file loading was
broken. This had the effect, that the default configuration file was not
loaded when the user-specific config file was not present, instead
leading to a termination of cagebreak.
## Issue 59
* github issue number: N/A
* 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.

View file

@ -1,15 +0,0 @@
# Code of Conduct
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting project-repo (See [SECURITY.md](SECURITY.md) for an e-mail contact.).
This Code of Conduct is adapted from Curl, available at https://curl.se/docs/code-of-conduct.html and transitively the Contributor Covenant, version 1.1.0, available at https://contributor-covenant.org/version/1/1/0/

View file

@ -1,464 +0,0 @@
# 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,162 +0,0 @@
# Changelog
## 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.
## Release 2.2.0
* Add custom events
* Fix Issue 62 (#46 Github)
* Fix Issue 63 (environment variables test)
* Fix Issue 64 (pointer focus bug)
## Release 2.1.0
* 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 2.0.0
This is a major release and includes BREAKING changes!
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"
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
## Release 1.9.0
- Add message functionality (as per Issue 29 in Bugs.md)
- message <text>
- configure_message
- Add (as per Issue 30 in Bugs.md)
- movetoprevscreen
- movetoscreen <n>
- screen <n>
- additional output functionality for monitor numbering
- Improve configuration documentation
- Fix Issue 31 in Bugs.md (word omission)
- Improve README.md and split off some files
- Add SECURITY.md
- Add Hashes.md (hashes of cagebreak binaries and man pages if built reproducably)
- Add Changelog.md (changelog for major and minor releases but not patches)
- Add FAQ.md (updated information from the former wiki)
- Depreciate wiki
- Fix Issue 32 in Bugs.md
- Improve release checklist to partially prevent the above issue
in the future
- Fix Issue 33 in Bugs.md
- Fix Issue 34 in Bugs.md
- Manage gpg keys
- Add new cagebreak gpg signing keys
- Add new cagebreak email contact gpg key
- Add new project-repo AUR gpg key (relevant for cagebreak-pkgbuild)
## Release 1.8.0
Adds libinput configuration and virtual keyboard and pointer support.
## Release 1.7.0
Improves window ordering.
## 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.

118
FAQ.md
View file

@ -1,118 +0,0 @@
# Frequently Asked Questions
## How do I do a particular thing with cagebreak?
* 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?
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
* `MOZ_USE_WAYLAND=1`
* `GDK_BACKEND=wayland`
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
which is likely not on your keyboard like "ы" - you should write
it as "Cyrillic_yeru".
These names can be obtained by running xev and pressing the respective
key(s) (combinations).
## How do I change the size of the cursor?
The size and shape of the cursor is determined by the application, however,
most applications respect the environment variables `XCURSOR_SIZE` and
`XCURSOR_THEME`
To change the cursor size, one could use:
```
export XCURSOR_SIZE=1
```
If you are using an application which inherits its environment variables
from something outside the scope of the export (such as a daemon for
emacs might), you can usually specify your environment variables in
the applications respective configuration.
## How is Cagebreak launched?
The documentation says to start Cagebreak like any other binary.
If you want to start Cagebreak on login, you can use your shells
equivalent of a `.bash_profile`. In BASH appending cagebreak
(given that it is installed in the path) to `.bash_profile`
is fine.
If you want to start Cagebreak using systemd you could use a
service started on user login, though the development team once ran
into some issues with permissions for the services.
Please note that Cagebreak does not solve the problem of
locking the screen or login in general.
## How are applications launched in Cagebreak?
There are multiple ways to launch external programs in cagebreak.
* Using a terminal emulator is a perfectly valid way to launch
applications. If you want to be able to close the terminal
you used to start the program, you may use `&disown`, which should
be available in every shell.
* Using the `exec` command in the cagebreak config, it is possible to
launch programs when cagebreak is started. Moreover, as this command
can be combined with commands such as `bind`, it can be used to
create custom keybindings which execute external programs. (See also
the man page `cagebreak-config`).
* All commands mentioned previously are also available over the socket
which allows the creation of (arbitrary) keybindings on the fly and
a fortiori keybindings running arbitrary commands.
## Which further resources are available?
* [Arch Linux Wiki entry for Cagebreak](https://wiki.archlinux.org/title/Cagebreak)
* [Sway Wiki](https://github.com/swaywm/sway/wiki)
* [Cage Wiki](https://github.com/Hjdskes/cage/wiki)
## This FAQ did not help me. What now?
* Consider [opening an issue](https://github.com/project-repo/cagebreak/issues/new) on github or getting in touch with the
development team (See section Email Contact in [SECURITY.md](SECURITY.md)).

444
Hashes.md
View file

@ -1,444 +0,0 @@
# 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
* sha 512: 097007da750c8acd09ee63159aeff5a5584cbab45525bd8fe81a379da5cc0e9f2bf776b809122d1b599f4716ef7feb0ccc0cf98be47a71d4819e2a8cd7a2f495
2.1.0 cagebreak.1
* sha 256: 6509c9126a9a140c517111f9352bf787a31dd8451fa9976135fc1dfbe40ed23d
* sha 512: 96a8c3d5b9677a95255c09b3674559aea7ff130370baa1cce40212501cb288c047048cf9bfbf78bc2cfab35e346fd49ef6b9d5d67f8ab5d07f8991f66e8de3aa
2.1.0 cagebreak-config.5
* sha 256: dbccee812d59209ddad73b376bfbb823611e2a8a92078b55e847ab678122bd54
* sha 512: a8d0b31007208d7ca38f691ded77d9f13318f47046d9237efd6738d0e10dd8402a35fc48230e72493b17aeeb174cb246440301626a1cd5a48c7d03d0800d0128
2.1.0 cagebreak-socket.7
* sha 256: e7b85f15665da4a4422ad223b4b2748ff4315d315a8b108df279ff3b13b8c4c9
* sha 512: 01dc53b4867ebc18f0091c3b1a239a89959403686c05e5e22aebf8155a46b82492b9aed27198a78e2777a9ff44b03f6e10ca82283062a29e1fa0114b97bb36a3
2.0.1 cagebreak
* sha 256: 3d7cdf511976248614617b1738246a3c5fa94543838e798c0c3a9aec325027b9
* sha 512: 3b584e7a124e8b32b9d6584e82d256ca4a0b8c30423efc4678c8991d7a6f9b43edd29967eda7be6284e3583209e607b14d88e8ec65b19706849d0263a3188852
2.0.1 cagebreak.1
* sha 256: bb93d7d3af98b4b14a5b6968065ded51ad5006e6d81736ee1806ee62a99a137e
* sha 512: 90e8d4c5628cc556001da3b96194c5649cc948389697c4c70e10e5e259ce6a52150c6231b2fb9009d2834d52b64c0ebc5896403b9fd0c584d4c873e45846250f
2.0.1 cagebreak-config.5
* sha 256: 1870c1274848e6535edda170ec0349befb2aa78bc812c56bdc66df99600c86f0
* sha 512: 4b546e77a722375cc6fd22562f3b4724e5cccc0907a935db5854fa4fe2a0eef16adbd2e7e2b35b023ac9609e5d97a341d62ade730c76acd6b3f80ba6f65d8a24
2.0.1 cagebreak-socket.7
* sha 256: 1276c37af5cf32276b2f5bcb3f13d4d00c9a7957ef4d51cb2fa62d2fc3643c6f
* sha 512: 60b38a0b43d2a0d5026ecf2ec660538cd384b5a2e84f7a1a41ac916e67de54ae7a55e45492ed5654d3f248e1d6693ba7c4d596987b03082841a4c3c953c57846
2.0.0 cagebreak
* sha 256: 45f88abdae03bbc7dad5734dd6fb1a00e1bf37d3e0c4016dad2fa3de832335cf
* sha 512: dc261a788ea1843e701f4fb6985200c4813113fda0f911bee4e3cc9b20fd082055e40e9fc60647128674a94ece75f4aa55d1faede8e94e6e1940b02d8a6de8e0
2.0.0 cagebreak.1
* sha 256: 0d96947c2054fb42b284b31cc4ea793944a4562509f5f00b7927d11d0046041d
* sha 512: 4f3eadc88680d994f9ebcf85be38626b7e95971bc3233d710613cee58496553e0bb1e65258956f8a50c633bdd4dbc5c0283826fd5b661e9de0092366cc47caae
2.0.0 cagebreak-config.5
* sha 256: 4ee6ed443ce93cd6af3df49fe5e32244baeca04ca167993fb3d71970bf20939d
* sha 512: d6bf8f73ed8c9084b784653e88e1f149fbab35997f412f6c505972d3299a47bec1238aecd4334dd597bb32e46ced93f36d488badd25c6a8d61bdb73f3aea87ab
2.0.0 cagebreak-socket.7
* sha 256: 682b3cc46ad059147b7d7ab814ac1831689511e31c0d6f2b91732e85244da99e
* sha 512: 92057e4cbbcec4f4dbd98f3a99cb4c450ef31aef557705e5f8f2927b53653149b232771b455f9b9ae8435a7351667a4e663b7d120b76a0bbb5c7ba04db551489
1.9.1 cagebreak
* sha 256: 262c67170eb2a39174d40f97d940707029dca0b2b613b514a1cca29152a12665
* sha 512: bbd962eaf90441338a67215fc7ac0a717b8cb7bd93ce7ef7ed446aa1df9f4e44026994cc1172e6245e5cd4b9c588150ed9c894941069c5c132c9e2009523c241
1.9.1 cagebreak.1
* sha 256: f9c1ee94c0788b98f1e8d93433a0e39d4265ed5c8107e964648da11c60c995ed
* sha 512: 1d39748c42a56852ce21aa5ea872160da0810d0539901f6c307b141d4c2545c52a7de98d924e4e45827dafa8cb76b483abf5e02403e6536f69d2144575d3dfdb
1.9.1 cagebreak-config.5
* sha 256: 2b0d5655e01942cb5130a95c7209e32c1ce3f44411f2a3294a160d6a2232bef4
* sha 512: c13a92e091e56aad099c12c4bf652943bf43dad5aace61677af992331a2700d3d2f433cd2a674cbc2cc080e971169516973835c44416de555a85b5aae9da9a9d
1.9.0 cagebreak
* sha 256: 91096b4c558970666c5ef1ebd5c16301fbb40b52b34a73589f18a14c48edf5c1
* sha 512: 52ec9c6996377d01d35df87ea5480a33c93cd7c62645f54523f3808fa9f84578f3a6201e969c6bdb5987e69b667be7edc8ce7067091c8413193c5e33cb434883
1.9.0 cagebreak.1
* sha 256: 431909f4c62157e57e789359a8458fc650b5f266b2fccc6fc5c0e501f8c879d3
* sha 512: f7523288ef3ca406507ee996e189fd339623fa465585973ac769cbea7948399545e8886fe585c7ddd70ca89465c81a188137dcea5b7273353966ea882d9806bd
1.9.0 cagebreak-config.5
* sha 256: 4433d8a160e48834fefb4cdd54fcec1f6038e21801c7a1dffb041b5eb238a2cc
* sha 512: af44aa42fe05b50a773420000c383fac837e45ead248876bb617c53e44e36d09a88ae26df80c1c9ffd6cf7c4dac72acb02d369888a79fed35114ed7e88fbe159
1.8.2 cagebreak
* sha 256: f4d275d48ba3d999969f8cb3c8142d27aa8e8d362106ee7575e4b13c02173b2a
* sha 512: 72b11cb966b0978133b9848c2a7f57574c599c7fe895ca9f1cba16930216e1ac8aeae86d976593fc01b15e94ecc1430666f474654cf2fe41eda8c1181bf03f3d
1.8.2 cagebreak.1
* sha 256: 51ee97a7c0b86268cf7622f84f7b1813df8e4a7838c00aae412a611d3693e87a
* sha 512: 5ce826afbee9cbc1129f37463f5b6d4dfc060583f6f7816dd5039b18d66a2b7e22f7293a4aa03acc4e6c690886d0297fef5b9f85d720a4467becfd833b59a160
1.8.2 cagebreak-config.5
* sha 256: 7c780ba85211ba40c7535b3f10f12312f9edeaa10030228ba21a96724469a325
* sha 512: 9a56ba16c2aed6f17d4098e54900a5d25602f986e3606dd6ed26563c1920c66404b210dbca9f41bfcc3284bf5a42b750263bcaa2317320f8725e8f9c66e8b893
1.8.1 cagebreak
* sha 256: e3247281d21525413790e3feceae129d9b0559497615d3fdd64ec2fc4ab9ab3d
* sha 512: 8c7c2820be9d7c74e3f9e239c7da740ff41d7f11cd40953dbfbc59c04942077f08625f6d7ec37e6037fd9c4b6950fc4f9af23478080665fdda867c65e0a187bf
1.8.1 cagebreak.1
* sha 256: 96997afdfde9c2719533799aa48c8f036610bb04bc719130d2ab3a3617b072ee
* sha 512: 0831f5d2e3b4f23fd5775df2b7f6486099d64962567222a8fb49e6a40e7d29ed36a7c2c16201bbdcc985ac74f1d0e034b530afbe0ce58d6a0c53d467cff0a6a0
1.8.1 cagebreak-config.5
* sha 256: bd0e2eb02ba28ec1c8f2bd0fd5cd4c84af24b615fcc477414e49e68e1963cf1b
* sha 512: 7135a2b371294bfdc759a393c13fa0225f1789dba94bb09e96ae689796215b8030280d6cc09c9d1fe139f000f5a4748efd16bb3e5d3b9fcc74a19259802f20ef
1.8.0 cagebreak
* sha 256: ac84aa4a08c311da79ca29d92eef4254cb625674b255dbb75621ee6b171a1d79
* sha 512: c047bb1986fd1d444547e4d64aa7ef9138b3d30327ac3ad9b4c6976e8df6638bae07c39293b5bc9c20e959c0a22b0e40eb2b23b4766d9a5531377ff954b16229
1.8.0 cagebreak.1
* sha 256: 4de43de7bde67d6d806d206dffc34389f0b5c3ba648bfef673b7bc0adeb29202
* sha 512: 72aac9a2e9a47f2f85949222d5944dc293332a616e3b961c625fe876172f66638038057c30aa18904d6d969451f468b4fe45e918c0b204cf6952d58ea4c69c33
1.8.0 cagebreak-config.5
* sha 256: 678aadde06b5ff6bfbd9bc9460423210f9599bcaa0e50c2eae076dc6d6852781
* sha 512: 72056018fc1c559f26bd7e007b3f1db7d478cec7ec9337620e03a1e3d06910e244a52e8f655ea4f5d73669ffe064bbd23506005d9a6c06764b0f820d7a1df43f
1.7.4 cagebreak
* sha 256: c7442db906239b13f8d09e91cbe01f9e47b2a2c75bbb4b52adefd15dfbfa820f
* sha 512: 9c36ce706f31e1b8afacd8f9cd216c460d66030e0b2736a3dd929902b0d5fc52c5e69dbf6787205b8c495d960e00b6e7f633da86ab6e31613f1b4a9fd47c9f0e
1.7.4 cagebreak.1
* sha 256: 3dacc521e5e9b963cceeefeed6a10104c7c415d86826a72788aba5b33ce320f1
* sha 512: 0a4c4fbff09dd403fed61056ae3211ad2b4370b4e9ed07806fc22624e5312b4a25e469dc0eef1ca4556cbb8efabb0127e7519df79852e110faa98fb17ca377de
1.7.4 cagebreak-config.5
* sha 256: ed22fed1818172f31d3fb3efbe5e66b49f135cb2367b1c85209fd880ff7532ab
* sha 512: cc634c63962ae50b4de20a3aad8ca0970175b53156690d69e6a69fd8f370ad20d84db783cc7e94c61d4d4d89f1205d43622690e58afba549ed57ddad009e3bac
1.7.3 cagebreak
* sha 256: 8adb4911d9603fec5b8eb4f67a09be95b8f0b37e50d4ab579191da78df18f70b
* sha 512: eddaecd7b577b9fe77b1ed4d341074f7f860967568392d0479543ea8860b4289df3eb5645885e18e35260b14843663ae50f98103f8016e857237a397632322a6
1.7.3 cagebreak.1
* sha 256: bcc623e42c86ab65bc2f8cb7e4377ca0d816ddc281527b7caeded62753e943b8
* sha 512: b4290e1040bd6a299d478ad6b695de75cf030d0d274340b43d3ed4382cf6877f824cd4ed9d7020bfb55afe276c62de7fc07c3fbee6f6485c6440a024115afe12
1.7.3 cagebreak-config.5
* sha 256: b9789b6abd473e9afb33d4e2c7822f7d8f3c10e9eb3fb70c47b713f6331c626a
* sha 512: c49e01cfc4a4ed272f054bea8f2845f0e3f1609cf85d1a0ce14c1b67dc207df153b11bc20ceef09c855d467f0e013e54623ce9f70c217c4278607fc54d0e3206
1.7.2 cagebreak
* sha 256: 40f4642e8e8caee338055079b046f6e0b790c87226ee307b27a64fcb2a6c6472
* sha 512: 22c5f1986ca4262a7c08a6c03cffe36eaedd8c3c5e27e12baf12a90f94aea088ac93ee107770f162fc70148be687f6394b8fd64ad3fe14414bdf63b55b33798e
1.7.2 cagebreak.1
* sha 256: 3253e592c40c78fd3733c761163acc2efaaf5865627cf51fd33cc0bc5d9cc6e7
* sha 512: 901305e166c10aa7e4a26b721a69e0ba4779f4f8ee690551438ceadae65929f13949457872b9397dd46c5b7bad6a6f2638d6fd6df9bc5567c914c798cbf3e9a4
1.7.2 cagebreak-config.5
* sha 256: 148ec4d80dc9a86485fe77f8daf1f7fa4cb3d1b6aaa709bb012005583779e1f7
* sha 512: d5732572e47dd07078ac2f6d589522e6007188fc05ac79520c93442212d5c0341459f135191b88c608a75b2f56c2de4065566bd869fbc24e475936d32a54a7f8
1.7.1 cagebreak
* sha 256: 5a40797e016a2fa32b5bb70a056b35c482bef09f1795bbaf0188dbadaf8197c3
* sha 512: 2ef327b63ac4651f23517be8d5cb8fbec99bd889f52f8abfd62a09ca6e6c0060347ab8d60e4917d39edd36db34597a673239967533f14457733acb97f6c29a7f
1.7.1 cagebreak.1
* sha 256: 0301f04254ae6e7ada7e22bbe7aee022ec0793fbce434a396868258e6f1ea4cf
* sha 512: f0c0c5de30be907e9ba5c9cfa0bca8cef3e94c0b5f52de9e2c3681c85aa957f75e92b5e26bb894c3a5e251295cfe7a1470653cc7dc05564d7d91c6eb43b7409a
1.7.1 cagebreak-config.5
* sha 256: 6882330a77f3ff98ea642f47b4090b38d542abf0b7be3f226486c5614899efc6
* sha 512: a572f97836e4ccc6d67aa21c7f4aaebe06adb066c70038b670ec1ef267e3750764cb53e96b8d7bc24c7f993f24c0cfabee183307b45006d049f7416559bcaca4
1.7.0
* sha 256: 5af11b84e61a82a1a276e8f91f6ebc6baafd2c98d22be3da1d01734cc9d55faa
* sha 512: 45474115fb4c28fe1ee91ad54706bfe521b6e70bd8ea619b94a3f50bae426891bf6a0387aa9b2f7f6d18349280c4e84973e4e433d50c090e5a764c64fa67795d
1.6.0
* sha 256: aef473eae73454429afb158d66a7bd9aec75ef915845b7508de5448820357aa8
* sha 512: 17889bc1af9f343598a5ee599b25e702987dd0bd905a9566874e8a0094c57168e413938624949fa214e6e382cbcf89d7342292b44012cd8e692947f6c01a960a
1.5.1
* sha 256: 9c6df4b94c180f5657cb424383aa2bf3aca063c8e7b40af0497be1ef7bdb858a
* sha 512: 219f753347ae64a4dd593568797438742e9ddae380c729598d8eda863080a6ed4e5086d735fc348c48328bb795a5a5b57b0421be5dd45755744d895b24312627
1.5.0
* sha 256: 22010e2916493b0d7cfb08c2196f12589509ce11010a7107aed13ddbfd9709cc
* sha 512: 707d6cc01326ba32402f9fb402ff8aceaeaba63ca6ba2eb157e5a4c83123515a3a74da960813479db303eddc2e7f79f39b241dff05b89d47d72d5f1d20ca6d37
1.4.4
* sha 256: c6e08e19feb17f768e136cf02f5692ef121ff289763dc60ef8678103803d3307
* sha 512: aebf27fa9c24f93dfd0b7c96536c253e2ea603d6746c40e8de2163e06367bc57ac4e22d6c07dd1e0963cce5b18b460d373e15b5c12a5a42ae6b70787971960c9
1.4.3
* sha 256: 5e29cbaf7c0c5ca74f71a5605bb3d6e302e051798401fee9a79419720b8d8e95
* sha 512: 8004865f8603648d9ac9bb700f3ee040e6516c222ad3d783b34219c8fa3a7bdbba6abb74fe92c4d0bd4dbbce0ec4d08be12297a8bad5032baeb589eec557e24e
1.4.2
* sha 256: 27efb9328cf9cab1f81e66627696baf8c7cc2c372339a2890f955b40f3a7c396
* sha 512: afcdbbce0753aff4770a88ddbd7df5687a7de0c77de3a2d296f85a8b8e01813212be6a0b69548aadef58e0e7da19ffea71c4f3448572656d4b19ff7f2f2fb70a
1.4.1
* sha 256: c3e0ccceaf1078b91071c40b0ccb7c4f8e53ae38b05ee6637f9f39f7f6ece2cb
* sha 512: fd77f39fc7a7e5376d8505a61d643ed4d8f4cfbbf38d70cf9ef6989645e8cc6cb9d4b1024d241dc689b6fd927a405c97b9c918b6994b8f9ab7406646f37b952d
1.4.0
* sha 256: 14aa93d890c62cc763b3b546a51ad8560479d5e91fa9f949858ae6bc785e80be
* sha 512: 88f93b49792684c38553b65d2296a0e502a059814a0cfff30d05c89958870d6f66d67aac2074cfd307bad82b0d72d5c4944822a61a68f665dc161407db365fbc
1.3.4
* sha 256: ea9f634b8f6e2b9f191745a25abff4969eb7ea19cb3186b79a6138904aedeb1c
* sha 512: 9094f9c92acbff8fd95d38e7458c5184804f8913fa8c405bc2b6a0a220fe478b06cfeadbae41bd5ef84bde8d5642c249df9dada953e39c25926aa650c30a5309
1.3.3
* sha 256: 801851ceb52afac333a1decdd236ddef55555f8b36f865e8b3a831975a496f0d
* sha 512: ce64dd56ab99bba0a83414fecc82d85322e1ca5ca3a2ca77bdc7055b2dd10fd5e20e3ff62809a696d1b04ff0046fed88e2d7538aa447099d7c2d7df8e627b2e0
1.3.2
* sha 256: 2cefab73b8d5902b30adb0dda1bd292af2ee808d232abcc4b2a2802d522d5232
* sha 512: 3789efde2cb6f629c77738dd6c8638646b345d5272868aa9b244b2b19c53e6a0f5911d34744e3a9ff6253c73b2b11f6714f37ae86cc21d6979e0c8539315d659
1.3.1
* sha 256: 71be224cd99d20da4f039675ec5c48213dd14ef027b804501fa3241886b2b08b
* sha 512: d094b786e5a74b01699997a85747943e6de3544cc903dd1c5dba449c66bd925b6378de800d3734969dabf8a20c7004dc3402e3c59577db09ce107b68a1f7bd21
1.3.0
* sha 256: aecc5292f56f7250d777110cee1f11a92018a9eb2117d7d37cd51d7d3a5cbae0
* sha 512: 1d2d220f44787a97359a32f305e33185f0369551e61a9d7066023bfa43de50849eba5bcbb0083d2dc563ac993b8d51dd733afa0adb2a823ef50ecfee5624bbc0
1.2.1
* sha 256: 803f7667dc4997062f9ec95afcdca0cac68c82a7cf057cef83fe1ccfee33b8bc
* sha 512: 4d6b7efea10d190a153f893123b1715f290f4b131b490f3d23f489e2dd8edbb886001282849aad9575ad2f40375bbbded59c1cb6157115fcc14dd6a2a061b103
1.2.0
* sha 256: b3c6135833001a0ef600ea9628cca11f4130a524ebe748929d8f7bad034f2bf0
* sha 512: c044a086a9f65b0d27d05e2f12a20fe5d77386fc5682991c13a1894a84804bcd337c9167235869661d6e6581133521bd710ef2330066a5d2e2703d1630042f3f
1.1.0
* sha 256: fc393e225c549f893b9e21e8b904e546d5857bac1d905b3d26334c8f8a1cda11
* sha 512: 8b94b1069e767202bcab087cb592eadc42f0453d17ee119d48760be00bc66278cf0fa60bb09308d30cb551df6a7a3e26e2ab8b29c04f0e953cc6906542cd2d6f
1.0.6
* sha 256: 712ae9a8f17a9e589e108f0d503da203cc5eaf1c4a6ca6efb5b4c83b432ce0b8
* sha 512: d574003023a00cfd6623aac986a5a7f397cfd0bc9114017629a8c72731b0df3977c4a31768502dfa8a6607be06930089b2ccf6ffca9b5bcd1096b7ca0aede226

View file

@ -1,4 +1,4 @@
Copyright (c) 2020-2024 The Cagebreak authors
Copyright (c) 2020-2021 The Cagebreak authors
Copyright (c) 2018-2020 Jente Hidskes
Copyright (c) 2019 The Sway authors

590
README.md
View file

@ -1,288 +1,486 @@
# Cagebreak: A Tiling Wayland Compositor
# Cagebreak: A Wayland Tiling Compositor Inspired by Ratpoison
[![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)
This is Cagebreak, a Wayland tiling compositor. The goal of this project is to
provide a successor to ratpoison for Wayland users. However, this is
no reimplementation of ratpoison. Should you like to know if a feature
will be implemented, open an issue or get in touch with the development team.
[![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)
For documentation of Cagebreak, please see
the man pages for [cagebreak](man/cagebreak.1.md) and cagebreak
[configuration](man/cagebreak-config.5.md) and the
[Wiki](https://github.com/project-repo/cagebreak/wiki/).
## Introduction
Cagebreak is based on [Cage](https://github.com/Hjdskes/cage), a Wayland kiosk
compositor.
Cagebreak provides a [ratpoison](https://www.nongnu.org/ratpoison/)-inspired, [cage](https://github.com/Hjdskes/cage)-based, tiling [Wayland](https://wayland.freedesktop.org/) compositor.
* 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.
Cagebreak is currently being developed under Arch Linux and uses the libraries
as they are obtained through pacman. However, cagebreak should also work on
other distributions given the proper library versions.
## Installation
On [Arch Linux](https://archlinux.org/), use the [AUR](https://aur.archlinux.org/) [PKGBUILDs](https://wiki.archlinux.org/title/PKGBUILD):
If you are using archlinux, just use the PKGBUILDs from the aur:
* Using [cagebreak](https://aur.archlinux.org/packages/cagebreak), Cagebreak is
built on the target system (since release 1.3.0)
* Using [cagebreak-bin](https://aur.archlinux.org/packages/cagebreak-bin),
pre-built binaries are extracted
to the target system (since release 1.3.2)
* Using the `cagebreak` package, Cagebreak is compiled on the target system (since release 1.3.0)
* Using `cagebreak-bin` package, the pre-built binaries are extracted to the appropriate paths on 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:
* [git clone](https://github.com/project-repo/cagebreak) (for all releases)
* [download release asset tarballs](https://github.com/project-repo/cagebreak/releases) (starting at release 1.2.1)
* git clone (for all releases)
* download release asset tarballs (starting at release 1.2.1)
#### Verifying Source Code
### Verifying Source Code
There are ways to verify that you obtained the correct source (See `keys/`
and [CONTRIBUTING](CONTRIBUTING.md)):
There are corresponding methods of verifying that you obtained the correct code:
* signature for the tarball of release assets starting at release 1.2.1
* signed tags for releases in the git history
* our git history includes signed tags for releases
* release assets starting at release 1.2.1 contain a signature for the tarball
## Building Cagebreak
### Building Cagebreak
Cagebreak uses the [meson](https://mesonbuild.com/) build system.
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 is developed against the latest tag of wlroots, so as not to constantly
chase breaking changes.
Execute the following commands to build Cagebreak:
Simply execute the following steps to build Cagebreak:
```
$ meson setup build -Dxwayland=true -Dman-pages=true --buildtype=release
$ meson build
$ ninja -C build
```
### Man Pages
#### Release Build
Remove `-Dman-pages=true` to disable man page generation.
By default, this builds a debug build. To build a release build, use `meson
build --buildtype=release`.
To generate man pages, make sure that you have [scdoc](https://archlinux.org/packages/extra/x86_64/scdoc/) installed.
#### Xwayland Support
### Release Build
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.
To obtain a debug build, remove `--buildtype=release`.
#### Man Pages
The release build is reproducible under conditions outlined in [CONTRIBUTING](CONTRIBUTING.md).
Cagebreak has man pages. To use them, make sure that you have `pandoc`
installed. Then, add `-Dman-pages=true to the `meson` command.
### Xwayland Support
### Running Cagebreak
To build Cagebreak without XWayland support, remove `-Dxwayland=true`.
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. For more configuration options, see the man pages.
To use XWayland make sure that your version of wlroots is compiled with
XWayland support.
## Contributing to Cagebreak
You'll need to have [XWayland](https://archlinux.org/packages/extra/x86_64/xorg-xwayland/) installed for XWayland support to work.
Cagebreak is currently developed to fit the needs of its creators. Should you desire
to implement a feature, please let us know in advance by opening an issue. However,
the feature set is intentionally limited (i.e. we removed support for a desktop
background) and will continue to be so in the future.
## Running Cagebreak
Nonetheless, don't be intimidated by the (slightly lengthy) release checklist or any other
part of this file. Do what you can, open an issue and we will collaborate
toward a solution.
### Branching Strategy and Versioning
All features are to be developed on feature branches, named after the feature.
There exists a branch `development` to which all reasonable feature branches
are merged for final testing.
Once `development` is ready for a release, meaning that the release checklist is fulfilled,
it is merged into `master`, creating a new release, which is tagged and signed.
All releases are tagged according to [semantic versioning](https://semver.org) guidelines.
In the past, our git history did not perfectly reflect this scheme.
### Releases
The release checklist must be completely fulfilled in one run for a release to
occur. Once any failure occurs the entire checklist must be completed from scratch.
* [ ] `git checkout development`
* [ ] `git pull origin development`
* [ ] `git push origin development`
* [ ] `ninja -C build clang-format` makes no changes
* [ ] New version number determined according to [semantic versioning](https://semver.org) guidelines
* [ ] Relevant Documentation completed
* [ ] New features
* [ ] man pages
* [ ] man/cagebreak
* [ ] man/cagebreak-config
* [ ] Set EPOCH to release day in man generation in meson.build
* [ ] wiki
* [ ] README.md Changelog for major and minor releases but not patches
* [ ] Fixed bugs documented in Bugs.md
* [ ] Include issue description from github
* [ ] Testing
* [ ] Manual testing
* [ ] Libfuzzer testing
* [ ] Version Number
* [ ] meson.build
* [ ] git tag
* [ ] man pages
* [ ] meson.build reproducible build versions are current archlinux libraries and gcc
* [ ] Cagebreak is reproducible on multiple machines
* [ ] Documented reproducible build artefacts
* [ ] Hashes of the artefacts in README.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`
* [ ] `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`
* [ ] `git merge master`
* [ ] `git push --tags origin development`
* [ ] `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 LICENSE 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 build --buildtype=release
* [ ] ninja -C build
* [ ] gpg --verify ../signatures/cagebreak.sig build/cagebreak
* [ ] cd ..
* [ ] rm -rf cagebreak
* [ ] `gpg --detach-sign -u keyid release_version.tar.gz`
* [ ] `gpg --detach-sign -u keyid release-artefacts_version.tar.gz`
* [ ] Upload archives and signatures as release assets
### Reproducible Builds
Cagebreak offers reproducible builds given the exact library versions specified
in `meson.build`. Should a version mismatch occur, a warning will be emitted. We have
decided on this compromise to allow flexibility and security. In general we will
adapt the versions to the packages available under Arch Linux at the time of
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.
```
$ ./build/cagebreak
meson build -Dxwayland=true -Dman-pages=true --buildtype=release
ninja -C build
```
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.
#### Hashes for Builds
If you run it in a TTY, it'll run with the KMS+DRM backend.
For every release after 1.0.5, hashes will be provided.
Note that a configuration file is required. For more configuration options, see the [man pages](manuals.md).
For every release after 1.7.0, hashes will be provided for man pages too.
Please see `example_scripts/` for a basis to customize from.
1.7.2 cagebreak
### Usage Philosophy
* sha 256: 40f4642e8e8caee338055079b046f6e0b790c87226ee307b27a64fcb2a6c6472
* sha 512: 22c5f1986ca4262a7c08a6c03cffe36eaedd8c3c5e27e12baf12a90f94aea088ac93ee107770f162fc70148be687f6394b8fd64ad3fe14414bdf63b55b33798e
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](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.7.2 cagebreak.1
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
that pointers, touchpads and such are not available for the few applications
that do require them.
* sha 256: 3253e592c40c78fd3733c761163acc2efaaf5865627cf51fd33cc0bc5d9cc6e7
* sha 512: 901305e166c10aa7e4a26b721a69e0ba4779f4f8ee690551438ceadae65929f13949457872b9397dd46c5b7bad6a6f2638d6fd6df9bc5567c914c798cbf3e9a4
2. Cagebreak is a tiling compositor. Every view takes up as much screen space
as possible. We believe this is useful, as only very few programs are typically
necessary to complete a task. To manage multiple tasks concurrently, we use
workspaces.
1.7.2 cagebreak-config.5
3. Each task deserves its own workspace. Any given task (the sort of thing you
might find in your calendar or on your todo list) probably requires very few
views and ideally, these take up as much of the screen as possible.
* sha 256: 148ec4d80dc9a86485fe77f8daf1f7fa4cb3d1b6aaa709bb012005583779e1f7
* sha 512: d5732572e47dd07078ac2f6d589522e6007188fc05ac79520c93442212d5c0341459f135191b88c608a75b2f56c2de4065566bd869fbc24e475936d32a54a7f8
> Combining 2. and 3. might look like this in practice:
1.7.1 cagebreak
> * Task 1: Edit introduction section for paper on X
> * Task 2: Coordinate event with person Y
* sha 256: 5a40797e016a2fa32b5bb70a056b35c482bef09f1795bbaf0188dbadaf8197c3
* sha 512: 2ef327b63ac4651f23517be8d5cb8fbec99bd889f52f8abfd62a09ca6e6c0060347ab8d60e4917d39edd36db34597a673239967533f14457733acb97f6c29a7f
> * split screen vertically
> * open web browser or pdf viewer to read literature
> * focus next
> * open editor
> * change to a different workspace
> * split screen vertically
> * open calendar application
> * focus next
> * open chat application
1.7.1 cagebreak.1
> Now each task has its own workspace and switching between tasks is possible
> by switching between workspaces.
* sha 256: 0301f04254ae6e7ada7e22bbe7aee022ec0793fbce434a396868258e6f1ea4cf
* sha 512: f0c0c5de30be907e9ba5c9cfa0bca8cef3e94c0b5f52de9e2c3681c85aa957f75e92b5e26bb894c3a5e251295cfe7a1470653cc7dc05564d7d91c6eb43b7409a
> Note that, for example by using the socket, more advanced setups are
> possible. But the user is warned that excessive tweaking eats into the work
> to be done.
1.7.1 cagebreak-config.5
4. Use keybindings and terminal emulators for the right purpose. Given the
philosophy outlined above you probably launch the same few programs very
often and others are very rarely used. We believe that commonly
used programs should have their own keybindings together with the most
important cagebreak commands. All the rarely used programs should be launched
from a terminal emulator as they probably require special flags, environment
variables and file paths anyway.
* sha 256: 6882330a77f3ff98ea642f47b4090b38d542abf0b7be3f226486c5614899efc6
* sha 512: a572f97836e4ccc6d67aa21c7f4aaebe06adb066c70038b670ec1ef267e3750764cb53e96b8d7bc24c7f993f24c0cfabee183307b45006d049f7416559bcaca4
> In practice this means thinking about the applications and cagebreak commands
> you use and taking your keyboard layout into account when defining keybindings for
> your individual needs.
1.7.0
5. Cagebreak can't do everything, but with scripting you can do most things.
Through the socket and with a bit of scripting, you can use the internal state
of cagebreak in combination with cagebreak commands and the full power of
a scripting language of your choice to do almost whatever you want.
* sha 256: 5af11b84e61a82a1a276e8f91f6ebc6baafd2c98d22be3da1d01734cc9d55faa
* sha 512: 45474115fb4c28fe1ee91ad54706bfe521b6e70bd8ea619b94a3f50bae426891bf6a0387aa9b2f7f6d18349280c4e84973e4e433d50c090e5a764c64fa67795d
> Example scripts can be found in the repository under `example_scripts/`.
1.6.0
## Roadmap
* sha 256: aef473eae73454429afb158d66a7bd9aec75ef915845b7508de5448820357aa8
* sha 512: 17889bc1af9f343598a5ee599b25e702987dd0bd905a9566874e8a0094c57168e413938624949fa214e6e382cbcf89d7342292b44012cd8e692947f6c01a960a
Cagebreak plans to do or keep doing the following things
in the future:
1.5.1
* 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.
* sha 256: 9c6df4b94c180f5657cb424383aa2bf3aca063c8e7b40af0497be1ef7bdb858a
* sha 512: 219f753347ae64a4dd593568797438742e9ddae380c729598d8eda863080a6ed4e5086d735fc348c48328bb795a5a5b57b0421be5dd45755744d895b24312627
## Governance
1.5.0
Cagebreak is managed by project-repo.
* sha 256: 22010e2916493b0d7cfb08c2196f12589509ce11010a7107aed13ddbfd9709cc
* sha 512: 707d6cc01326ba32402f9fb402ff8aceaeaba63ca6ba2eb157e5a4c83123515a3a74da960813479db303eddc2e7f79f39b241dff05b89d47d72d5f1d20ca6d37
Consider project-repo a single benevolent dictator for life that happens
to occupy at least two brains.
1.4.4
Project-repo is a pseudonym of at least two individuals acting
as benevolent dictators for the project by the others mutual consent.
* sha 256: c6e08e19feb17f768e136cf02f5692ef121ff289763dc60ef8678103803d3307
* sha 512: aebf27fa9c24f93dfd0b7c96536c253e2ea603d6746c40e8de2163e06367bc57ac4e22d6c07dd1e0963cce5b18b460d373e15b5c12a5a42ae6b70787971960c9
The individuals comprising project-repo are not otherwise associated
by payment from any organisation or grant.
1.4.3
### Governance Issues
* sha 256: 5e29cbaf7c0c5ca74f71a5605bb3d6e302e051798401fee9a79419720b8d8e95
* sha 512: 8004865f8603648d9ac9bb700f3ee040e6516c222ad3d783b34219c8fa3a7bdbba6abb74fe92c4d0bd4dbbce0ec4d08be12297a8bad5032baeb589eec557e24e
Use [SECURITY.md](SECURITY.md) to contact project-repo.
1.4.2
### Roles
* sha 256: 27efb9328cf9cab1f81e66627696baf8c7cc2c372339a2890f955b40f3a7c396
* sha 512: afcdbbce0753aff4770a88ddbd7df5687a7de0c77de3a2d296f85a8b8e01813212be6a0b69548aadef58e0e7da19ffea71c4f3448572656d4b19ff7f2f2fb70a
There are members of project-repo and those who are not.
1.4.1
There are no specific roles forced unto anyone.
* sha 256: c3e0ccceaf1078b91071c40b0ccb7c4f8e53ae38b05ee6637f9f39f7f6ece2cb
* sha 512: fd77f39fc7a7e5376d8505a61d643ed4d8f4cfbbf38d70cf9ef6989645e8cc6cb9d4b1024d241dc689b6fd927a405c97b9c918b6994b8f9ab7406646f37b952d
### Bus Factor
1.4.0
The current bus factor for Cagebreak is: 1
* sha 256: 14aa93d890c62cc763b3b546a51ad8560479d5e91fa9f949858ae6bc785e80be
* sha 512: 88f93b49792684c38553b65d2296a0e502a059814a0cfff30d05c89958870d6f66d67aac2074cfd307bad82b0d72d5c4944822a61a68f665dc161407db365fbc
The Bus Factor is a measure of how many people have to be
incapacitated for a project to be unable to continue.
1.3.4
Project-repo could react to issues (even confidential
e-mails) and fix easier issues if any one individual were
incapacitated.
* sha 256: ea9f634b8f6e2b9f191745a25abff4969eb7ea19cb3186b79a6138904aedeb1c
* sha 512: 9094f9c92acbff8fd95d38e7458c5184804f8913fa8c405bc2b6a0a220fe478b06cfeadbae41bd5ef84bde8d5642c249df9dada953e39c25926aa650c30a5309
However, not all aspects of the code or release engineering
are fully resilient to the loss of any one individual.
1.3.3
We strive to increase the bus factor to at least 2 in all
aspects.
* sha 256: 801851ceb52afac333a1decdd236ddef55555f8b36f865e8b3a831975a496f0d
* sha 512: ce64dd56ab99bba0a83414fecc82d85322e1ca5ca3a2ca77bdc7055b2dd10fd5e20e3ff62809a696d1b04ff0046fed88e2d7538aa447099d7c2d7df8e627b2e0
## Accessibility
1.3.2
* 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.
* sha 256: 2cefab73b8d5902b30adb0dda1bd292af2ee808d232abcc4b2a2802d522d5232
* sha 512: 3789efde2cb6f629c77738dd6c8638646b345d5272868aa9b244b2b19c53e6a0f5911d34744e3a9ff6253c73b2b11f6714f37ae86cc21d6979e0c8539315d659
1.3.1
* sha 256: 71be224cd99d20da4f039675ec5c48213dd14ef027b804501fa3241886b2b08b
* sha 512: d094b786e5a74b01699997a85747943e6de3544cc903dd1c5dba449c66bd925b6378de800d3734969dabf8a20c7004dc3402e3c59577db09ce107b68a1f7bd21
1.3.0
* sha 256: aecc5292f56f7250d777110cee1f11a92018a9eb2117d7d37cd51d7d3a5cbae0
* sha 512: 1d2d220f44787a97359a32f305e33185f0369551e61a9d7066023bfa43de50849eba5bcbb0083d2dc563ac993b8d51dd733afa0adb2a823ef50ecfee5624bbc0
1.2.1
* sha 256: 803f7667dc4997062f9ec95afcdca0cac68c82a7cf057cef83fe1ccfee33b8bc
* sha 512: 4d6b7efea10d190a153f893123b1715f290f4b131b490f3d23f489e2dd8edbb886001282849aad9575ad2f40375bbbded59c1cb6157115fcc14dd6a2a061b103
1.2.0
* sha 256: b3c6135833001a0ef600ea9628cca11f4130a524ebe748929d8f7bad034f2bf0
* sha 512: c044a086a9f65b0d27d05e2f12a20fe5d77386fc5682991c13a1894a84804bcd337c9167235869661d6e6581133521bd710ef2330066a5d2e2703d1630042f3f
1.1.0
* sha 256: fc393e225c549f893b9e21e8b904e546d5857bac1d905b3d26334c8f8a1cda11
* sha 512: 8b94b1069e767202bcab087cb592eadc42f0453d17ee119d48760be00bc66278cf0fa60bb09308d30cb551df6a7a3e26e2ab8b29c04f0e953cc6906542cd2d6f
1.0.6
* sha 256: 712ae9a8f17a9e589e108f0d503da203cc5eaf1c4a6ca6efb5b4c83b432ce0b8
* sha 512: d574003023a00cfd6623aac986a5a7f397cfd0bc9114017629a8c72731b0df3977c4a31768502dfa8a6607be06930089b2ccf6ffca9b5bcd1096b7ca0aede226
#### 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.
#### Signing Keys
All releases are signed by at least one of the following collection of
keys.
* E79F6D9E113529F4B1FFE4D5C4F974D70CEC2C5B
* 4739D329C9187A1C2795C20A02ABFDEC3A40545F
* 7535AB89220A5C15A728B75F74104CC7DCA5D7A8
* 827BC2320D535AEAD0540E6E2E66F65D99761A6F
* A88D7431E5BAAD0B6EAE550AC8D61D8BD4FA3C46
* 8F872885968EB8C589A32E9539ACC012896D450F
* 896B92AF738C974E0065BF42F2576BD366156BB9
* AA927AFD50AF7C6810E69FE8274F2C605359E31B
Should we at any point retire a key, we will only replace it with keys signed
by at least one of the above collection.
We registered project-repo.co and added mail addresses after release `1.3.0`.
We now have a mail address and its key is signed by signing keys. See Security
Bugs for details.
The full public keys can be found in `keys/` along with any revocation certificates.
### GCC and -fanalyzer
Cagebreak should compile with any reasonably new gcc or clang. Consider
a gcc version of at least [10.1](https://gcc.gnu.org/gcc-10/changes.html) if
you want to get the benefit of the brand-new
[-fanalyzer](https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html)
flag. However, this new flag sometimes produces false-postives and we
selectively disable warnings for affected code segments as described below.
Meson is configured to set `CG_HAS_FANALYZE` if `-fanalyzer` is available.
Therefore, to maintain portability, false-positive fanalyzer warnings are to be
disabled using the following syntax:
```
#if CG_HAS_FANALYZE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "WARNING OPTION"
#endif
```
and after
```
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
```
### Fuzzing
Along with the project source code, a fuzzing framework based on `libfuzzer` is
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 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/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.
## Bugs
[Open an issue](https://github.com/project-repo/cagebreak/issues/new) is you find something.
For any bug, please [create an
issue](https://github.com/project-repo/cagebreak/issues/new) on
[GitHub](https://github.com/project-rep/cagebreak).
See [SECURITY.md](SECURITY.md) for other means of contacting the Cagebreak authors and security issues.
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.
Fixed bugs are assigned a number and summarized in [Bugs.md](Bugs.md) for future reference.
### Security Bugs
Should you want to get in touch with the developers of cagebreak to report a
security vulnerability or a different issue confidentially, contact
`cagebreak @ project-repo . co`.
We will try to respond to everything that is not obvious spam.
Please encrypt your email with the appropriate GPG key found in `keys/`.
* B15B92642760E11FE002DE168708D42451A94AB5
* F8DD9F8DD12B85A28F5827C4678E34D2E753AA3C
Note that the keys are signed by cagebreak signing keys.
If you want us to respond via GPG-encrypted mail, please include your own
public key or provide the fingerprint and directions to obtain the key.
## Changelog
### Release 1.0.0
Adds basic tiling window manager functionality to cage.
### Release 1.1.0
Unifies commands and actions. See Issue 4 in Bugs.md.
### Release 1.2.0
Adds output configuration as described in the man pages.
### Release 1.3.0
Adds IPC as described in the man pages.
### Release 1.4.0
Adds close command for windows as described in the man pages.
### Release 1.5.0
Adds options to disable or enable outputs. See Issue 22 in Bugs.md and Issue #2 on github.
### Release 1.6.0
Adds support for non-build dependencies and an option for builds without pandoc.
### Release 1.7.0
Improve window ordering.
## Contributors
* Aisha Tammy
* [make man pages optional](https://github.com/project-repo/cagebreak/pull/4), released
in 1.6.0 with slight modifications
* 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-2024 The Cagebreak authors
Copyright (c) 2018-2020 Jente Hidskes
Copyright (c) 2019 The Sway 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Please see [LICENSE](https://github.com/project-repo/cagebreak/blob/master/LICENSE)

View file

@ -1,103 +0,0 @@
# Security
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).
## Email Contact
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
The most recent release always contains the latest bug fixes and features.
There are no official backports for security vulnerabilities.
Builds are reproducible under conditions outlined in [README.md](README.md).
## Bug Reports
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 above.
## Threat Model
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 (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 (especially options -e and --bs ).
#### Spoofing
Not applicable - Cagebreak is executed after user login.
#### Tampering
Not applicable - Cagebreak allows system manipulation for user software.
#### Repudiation
Not applicable - There are no prohibited operations (See Tampering above.).
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.
Any user software may exfiltrate any data the user has access to.
#### Denial of Service
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 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
All Cagebreak project keys are found under keys/ in the cagebreak
repository (the public keys anyway).
The most trusted keys of the Cagebreak project are its signing keys,
all signing keys are signed by at least one of its predecessors and at
least one non-expired signing key is used at the time of release to
sign the commit tag and the release code tarball.
Signing keys are also used to lend credence to other keys in the Cagebreak
project, such as the keys for email correspondence and the key used in the
cagebreak-pkgbuild repository.

View file

@ -1,25 +1,25 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2018-2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#define _DEFAULT_SOURCE
#define _POSIX_C_SOURCE 200812L
#include "config.h"
#include <fontconfig/fontconfig.h>
#include <getopt.h>
#include <pango.h>
#include <pango/pangocairo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#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>
#include <wlr/types/wlr_cursor.h>
@ -27,27 +27,23 @@
#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>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_viewporter.h>
#if CG_HAS_XWAYLAND
#include <wlr/types/wlr_xcursor_manager.h>
#endif
#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
#if CG_HAS_XWAYLAND
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/xwayland.h>
#endif
#include "idle_inhibit_v1.h"
#include "input_manager.h"
#include "ipc_server.h"
#include "keybinding.h"
#include "message.h"
@ -55,7 +51,6 @@
#include "parse.h"
#include "seat.h"
#include "server.h"
#include "workspace.h"
#include "xdg_shell.h"
#if CG_HAS_XWAYLAND
#include "xwayland.h"
@ -65,8 +60,6 @@
#define WAIT_ANY -1
#endif
bool show_info = false;
void
set_sig_handler(int sig, void (*action)(int)) {
struct sigaction act;
@ -80,6 +73,14 @@ set_sig_handler(int sig, void (*action)(int)) {
}
}
void
sig_chld_handler(int signal) {
int pid = 1;
while(pid > 0) {
pid = waitpid(WAIT_ANY, NULL, WNOHANG);
}
}
static bool
drop_permissions(void) {
if(getuid() != geteuid() || getgid() != getegid()) {
@ -126,48 +127,42 @@ usage(FILE *file, const char *const cage) {
fprintf(file,
"Usage: %s [OPTIONS]\n"
"\n"
" -c <path>\t Load configuration file from <path>\n"
" -e\t\t Enable socket\n"
" -h\t\t Display this help message\n"
" -s\t\t Show information about the current setup and exit\n"
" -v\t\t Show the version number and exit\n"
" --bs\t\t \"bad security\": Enable features with potential "
"security implications (see man page)\n",
" -r\t Rotate the output 90 degrees clockwise, specify up to three "
"times\n"
#ifdef DEBUG
" -D\t Turn on damage tracking debugging\n"
#endif
" -h\t Display this help message\n"
" -v\t Show the version number and exit\n",
cage);
}
static bool
parse_args(struct cg_server *server, int argc, char *argv[],
char **config_path) {
int c, option_index;
server->enable_socket = false;
static struct option long_options[] = {{"bs", no_argument, 0, 0},
{0, 0, 0, 0}};
#ifndef __clang_analyzer__
while((c = getopt_long(argc, argv, "c:hvse", long_options,
&option_index)) != -1) {
parse_args(struct cg_server *server, int argc, char *argv[]) {
int c;
#ifdef DEBUG
while((c = getopt(argc, argv, "rDhv")) != -1) {
#else
while((c = getopt(argc, argv, "rhv")) != -1) {
#endif
switch(c) {
case 0:
server->bs = true;
case 'r':
server->output_transform++;
if(server->output_transform > WL_OUTPUT_TRANSFORM_270) {
server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL;
}
break;
#ifdef DEBUG
case 'D':
server->debug_damage_tracking = true;
break;
#endif
case 'h':
usage(stdout, argv[0]);
return false;
case 'v':
fprintf(stdout, "Cagebreak version " CG_VERSION "\n");
exit(0);
case 's':
show_info = true;
break;
case 'c':
if(optarg != NULL) {
*config_path = strdup(optarg);
optarg = NULL;
}
break;
case 'e':
server->enable_socket = true;
break;
default:
usage(stderr, argv[0]);
return false;
@ -178,7 +173,6 @@ parse_args(struct cg_server *server, int argc, char *argv[],
usage(stderr, argv[0]);
return false;
}
#endif
return true;
}
@ -191,30 +185,11 @@ set_configuration(struct cg_server *server,
if(config_file == NULL) {
wlr_log(WLR_ERROR, "Could not open config file \"%s\"",
config_file_path);
return 1;
return -1;
}
uint32_t line_length = 64;
char *line = calloc(line_length, sizeof(char));
for(unsigned int line_num = 1;; ++line_num) {
while(true) {
if(fgets(line + strlen(line), line_length - strlen(line),
config_file) == NULL) {
break;
}
if(strcspn(line, "\n") != line_length - 1) {
break;
}
line_length *= 2;
line = reallocarray(line, line_length, sizeof(char));
if(line == NULL) {
wlr_log(WLR_ERROR, "Could not allocate buffer for reading "
"configuration file.");
return 2;
}
}
if(strlen(line) == 0) {
break;
}
char line[MAX_LINE_SIZE * sizeof(char)];
for(unsigned int line_num = 1;
fgets(line, MAX_LINE_SIZE, config_file) != NULL; ++line_num) {
line[strcspn(line, "\n")] = '\0';
if(*line != '\0' && *line != '#') {
char *errstr;
@ -225,22 +200,16 @@ set_configuration(struct cg_server *server,
if(errstr != NULL) {
free(errstr);
}
free(line);
return -1;
}
}
memset(line, 0, line_length * sizeof(char));
}
free(line);
fclose(config_file);
return 0;
}
char *
get_config_file(char *udef_path) {
if(udef_path != NULL) {
return strdup(udef_path);
}
get_config_file() {
const char *config_home_path = getenv("XDG_CONFIG_HOME");
char *addition = "/cagebreak/config";
if(config_home_path == NULL || config_home_path[0] == '\0') {
@ -267,30 +236,26 @@ main(int argc, char *argv[]) {
struct wl_event_source *sigint_source = NULL;
struct wl_event_source *sigterm_source = NULL;
struct wl_event_source *sigalrm_source = NULL;
struct wl_event_source *sigpipe_source = NULL;
struct wlr_backend *backend = NULL;
struct wlr_renderer *renderer = NULL;
struct wlr_compositor *compositor = NULL;
struct wlr_subcompositor *subcompositor = NULL;
struct wlr_data_device_manager *data_device_manager = NULL;
struct wlr_server_decoration_manager *server_decoration_manager = NULL;
struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL;
struct wlr_screencopy_manager_v1 *screencopy_manager = NULL;
struct wlr_data_control_manager_v1 *data_control_manager = NULL;
struct wlr_viewporter *viewporter = NULL;
struct wlr_presentation *presentation = NULL;
struct wlr_xdg_output_manager_v1 *output_manager = NULL;
struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
struct wlr_xdg_shell *xdg_shell = NULL;
wl_list_init(&server.input_config);
wl_list_init(&server.output_config);
wl_list_init(&server.output_priorities);
#if CG_HAS_XWAYLAND
struct wlr_xwayland *xwayland = NULL;
struct wlr_xcursor_manager *xcursor_manager = NULL;
#endif
int ret = 0;
server.bs = 0;
char *config_path = NULL;
if(!parse_args(&server, argc, argv, &config_path)) {
goto end;
if(!parse_args(&server, argc, argv)) {
return 1;
}
#ifdef DEBUG
@ -302,31 +267,19 @@ main(int argc, char *argv[]) {
server.modes = malloc(4 * sizeof(char *));
if(!server.modes) {
wlr_log(WLR_ERROR, "Error allocating mode array");
goto end;
return -1;
}
/* Wayland requires XDG_RUNTIME_DIR to be set. */
if(!getenv("XDG_RUNTIME_DIR")) {
wlr_log(WLR_INFO, "XDG_RUNTIME_DIR is not set in the environment");
wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment");
return 1;
}
server.wl_display = wl_display_create();
if(!server.wl_display) {
wlr_log(WLR_ERROR, "Cannot allocate a Wayland display");
free(server.modes);
server.modes = NULL;
goto end;
}
server.xcursor_size = XCURSOR_SIZE;
const char *env_cursor_size = getenv("XCURSOR_SIZE");
if(env_cursor_size && strlen(env_cursor_size) > 0) {
errno = 0;
char *end;
unsigned size = strtoul(env_cursor_size, &end, 10);
if(!*end && errno == 0) {
server.xcursor_size = size;
}
return 1;
}
server.running = true;
@ -338,25 +291,11 @@ main(int argc, char *argv[]) {
if(server.modes[0] == NULL || server.modes[1] == NULL ||
server.modes[2] == NULL) {
wlr_log(WLR_ERROR, "Error allocating default modes");
goto end;
return 1;
}
server.nws = 1;
server.views_curr_id = 1;
server.tiles_curr_id = 1;
server.message_config.fg_color[0] = 0.0;
server.message_config.fg_color[1] = 0.0;
server.message_config.fg_color[2] = 0.0;
server.message_config.fg_color[3] = 1.0;
server.message_config.bg_color[0] = 0.9;
server.message_config.bg_color[1] = 0.85;
server.message_config.bg_color[2] = 0.85;
server.message_config.bg_color[3] = 1.0;
server.message_config.display_time = 2;
server.message_config.font = strdup("pango:Monospace 10");
server.message_config.anchor = CG_MESSAGE_TOP_RIGHT;
server.message_timeout = 2;
event_loop = wl_display_get_event_loop(server.wl_display);
sigint_source =
@ -365,12 +304,11 @@ main(int argc, char *argv[]) {
wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server);
sigalrm_source =
wl_event_loop_add_signal(event_loop, SIGALRM, handle_signal, &server);
sigpipe_source =
wl_event_loop_add_signal(event_loop, SIGPIPE, handle_signal, &server);
server.event_loop = event_loop;
backend = wlr_backend_autocreate(server.wl_display, &server.session);
server.headless_backend = wlr_headless_backend_create(server.wl_display);
set_sig_handler(SIGCHLD, sig_chld_handler);
backend = wlr_backend_autocreate(server.wl_display);
if(!backend) {
wlr_log(WLR_ERROR, "Unable to create the wlroots backend");
ret = 1;
@ -390,22 +328,10 @@ main(int argc, char *argv[]) {
goto end;
}
server.renderer = wlr_renderer_autocreate(backend);
if(!server.renderer) {
wlr_log(WLR_ERROR, "Unable to create the wlroots renderer");
ret = 1;
goto end;
}
wl_list_init(&server.output_config);
server.allocator =
wlr_allocator_autocreate(server.backend, server.renderer);
if(!server.allocator) {
wlr_log(WLR_ERROR, "Unable to create the wlroots allocator");
ret = 1;
goto end;
}
wlr_renderer_init_wl_display(server.renderer, server.wl_display);
renderer = wlr_backend_get_renderer(backend);
wlr_renderer_init_wl_display(renderer, server.wl_display);
server.bg_color = (float[4]){0, 0, 0, 1};
wl_list_init(&server.outputs);
@ -418,35 +344,13 @@ main(int argc, char *argv[]) {
goto end;
}
if(ipc_init(&server) != 0) {
wlr_log(WLR_ERROR, "Failed to initialize IPC");
ret = 1;
goto end;
}
server.scene = wlr_scene_create();
if(!server.scene) {
wlr_log(WLR_ERROR, "Unable to create scene");
ret = 1;
goto end;
}
server.scene_output_layout =
wlr_scene_attach_output_layout(server.scene, server.output_layout);
compositor = wlr_compositor_create(server.wl_display, 6, server.renderer);
compositor = wlr_compositor_create(server.wl_display, renderer);
if(!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");
ret = 1;
goto end;
}
subcompositor = wlr_subcompositor_create(server.wl_display);
if(!subcompositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots subcompositor");
ret = 1;
goto end;
}
data_device_manager = wlr_data_device_manager_create(server.wl_display);
if(!data_device_manager) {
wlr_log(WLR_ERROR, "Unable to create the data device manager");
@ -454,8 +358,6 @@ main(int argc, char *argv[]) {
goto end;
}
server.input = input_manager_create(&server);
data_control_manager =
wlr_data_control_manager_v1_create(server.wl_display);
if(!data_control_manager) {
@ -477,8 +379,14 @@ 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;
@ -489,7 +397,7 @@ main(int argc, char *argv[]) {
&server.new_idle_inhibitor_v1);
wl_list_init(&server.inhibitors);
xdg_shell = wlr_xdg_shell_create(server.wl_display, 3);
xdg_shell = wlr_xdg_shell_create(server.wl_display);
if(!xdg_shell) {
wlr_log(WLR_ERROR, "Unable to create the XDG shell interface");
ret = 1;
@ -520,21 +428,6 @@ main(int argc, char *argv[]) {
wlr_server_decoration_manager_set_default_mode(
server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
viewporter = wlr_viewporter_create(server.wl_display);
if(!viewporter) {
wlr_log(WLR_ERROR, "Unable to create the viewporter interface");
ret = 1;
goto end;
}
presentation = wlr_presentation_create(server.wl_display, server.backend);
if(!presentation) {
wlr_log(WLR_ERROR, "Unable to create the presentation interface");
ret = 1;
goto end;
}
wlr_scene_set_presentation(server.scene, presentation);
export_dmabuf_manager =
wlr_export_dmabuf_manager_v1_create(server.wl_display);
if(!export_dmabuf_manager) {
@ -558,52 +451,49 @@ main(int argc, char *argv[]) {
goto end;
}
if(!wlr_primary_selection_v1_device_manager_create(server.wl_display)) {
wlr_log(WLR_ERROR,
"Unable to create the primary selection device manager");
ret = 1;
goto end;
}
server.gamma_control =
gamma_control_manager =
wlr_gamma_control_manager_v1_create(server.wl_display);
if(!server.gamma_control) {
if(!gamma_control_manager) {
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);
if(!server.xwayland) {
xwayland = wlr_xwayland_create(server.wl_display, compositor, true);
if(!xwayland) {
wlr_log(WLR_ERROR, "Cannot create XWayland server");
ret = 1;
goto end;
}
server.new_xwayland_surface.notify = handle_xwayland_surface_new;
wl_signal_add(&server.xwayland->events.new_surface,
&server.new_xwayland_surface);
wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface);
if(setenv("DISPLAY", server.xwayland->display_name, true) < 0) {
xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE);
if(!xcursor_manager) {
wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager");
ret = 1;
goto end;
}
if(setenv("DISPLAY", xwayland->display_name, true) < 0) {
wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland.",
"Clients may not be able to connect");
} else {
wlr_log(WLR_DEBUG, "XWayland is running on display %s",
server.xwayland->display_name);
xwayland->display_name);
}
struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
server.seat->xcursor_manager, DEFAULT_XCURSOR, 1);
if(!wlr_xcursor_manager_load(xcursor_manager, 1)) {
wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme");
}
struct wlr_xcursor *xcursor =
wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1);
if(xcursor) {
struct wlr_xcursor_image *image = xcursor->images[0];
wlr_xwayland_set_cursor(server.xwayland, image->buffer,
image->width * 4, image->width, image->height,
image->hotspot_x, image->hotspot_y);
wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4,
image->width, image->height, image->hotspot_x,
image->hotspot_y);
}
#endif
@ -624,65 +514,42 @@ main(int argc, char *argv[]) {
wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.",
"Clients may not be able to connect");
} else {
fprintf(stdout,
"Cagebreak " CG_VERSION " is running on Wayland display %s\n",
wlr_log(WLR_DEBUG,
"Cagebreak " CG_VERSION " is running on Wayland display %s",
socket);
}
#if CG_HAS_XWAYLAND
wlr_xwayland_set_seat(server.xwayland, server.seat->seat);
wlr_xwayland_set_seat(xwayland, server.seat->seat);
#endif
if(show_info) {
char *msg = server_show_info(&server);
if(msg != NULL) {
fprintf(stdout, "%s", msg);
free(msg);
} else {
wlr_log(WLR_ERROR, "Failed to get info on cagebreak setup\n");
}
exit(0);
if(ipc_init(&server) != 0) {
wlr_log(WLR_ERROR, "Failed to initialize IPC");
ret = 1;
goto end;
}
{ // config_file should only be visible as long as it is valid
int conf_ret = 1;
char *config_file = get_config_file(config_path);
char *config_file = get_config_file();
if(config_file == NULL) {
wlr_log(WLR_ERROR, "Unable to get path to config file");
ret = 1;
goto end;
} else {
conf_ret = set_configuration(&server, config_file);
}
if(set_configuration(&server, config_file) != 0) {
free(config_file);
}
// Configuration file not found
if(conf_ret == 1) {
char *default_conf = "/etc/xdg/cagebreak/config";
wlr_log(WLR_INFO, "Loading default configuration file: \"%s\"",
default_conf);
conf_ret = set_configuration(&server, default_conf);
}
if(conf_ret != 0 || !server.running) {
ret = 1;
goto end;
}
free(config_file);
}
{
struct wl_list tmp_list;
wl_list_init(&tmp_list);
wl_list_insert_list(&tmp_list, &server.outputs);
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);
wl_list_for_each_safe(output, output_tmp, &server.outputs, link) {
output_configure(&server, output);
}
server.curr_output =
wl_container_of(server.outputs.next, server.curr_output, link);
}
/* Place the cursor to the top left of the output layout. */
@ -691,24 +558,20 @@ main(int argc, char *argv[]) {
wl_display_run(server.wl_display);
#if CG_HAS_XWAYLAND
if(server.xwayland != NULL) {
wlr_xwayland_destroy(server.xwayland);
}
wlr_xwayland_destroy(xwayland);
wlr_xcursor_manager_destroy(xcursor_manager);
#endif
wl_display_destroy_clients(server.wl_display);
end:
if(server.modes != NULL) {
for(unsigned int i = 0; server.modes[i] != NULL; ++i) {
free(server.modes[i]);
}
free(server.modes);
}
if(config_path != NULL) {
free(config_path);
#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]);
}
free(server.modes);
struct cg_output_config *output_config, *output_config_tmp;
wl_list_for_each_safe(output_config, output_config_tmp,
@ -718,50 +581,23 @@ end:
free(output_config);
}
struct cg_input_config *input_config, *input_config_tmp;
wl_list_for_each_safe(input_config, input_config_tmp, &server.input_config,
link) {
wl_list_remove(&input_config->link);
if(input_config->identifier != NULL) {
free(input_config->identifier);
}
free(input_config);
}
if(server.keybindings != NULL) {
keybinding_list_free(server.keybindings);
}
if(server.message_config.font != NULL) {
free(server.message_config.font);
}
server.running = false;
if(server.seat != NULL) {
seat_destroy(server.seat);
}
if(sigint_source != NULL) {
wl_event_source_remove(sigint_source);
wl_event_source_remove(sigterm_source);
wl_event_source_remove(sigalrm_source);
wl_event_source_remove(sigpipe_source);
}
keybinding_list_free(server.keybindings);
wl_event_source_remove(sigint_source);
wl_event_source_remove(sigterm_source);
wl_event_source_remove(sigalrm_source);
seat_destroy(server.seat);
/* This function is not null-safe, but we only ever get here
with a proper wl_display. */
if(server.wl_display != NULL) {
wl_display_destroy(server.wl_display);
}
if(server.output_layout != NULL) {
wlr_output_layout_destroy(server.output_layout);
}
wl_display_destroy(server.wl_display);
wlr_output_layout_destroy(server.output_layout);
if(server.input != NULL) {
free(server.input);
}
pango_cairo_font_map_set_default(NULL);
cairo_debug_reset_static_data();
FcFini();
return ret;
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif

View file

@ -1,6 +1,3 @@
// Copyright 2020 - 2023, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_CONFIG_H
#define CG_CONFIG_H
@ -9,6 +6,4 @@
#mesondefine CG_VERSION
#define MAX_NESTING_LEVEL 50
#endif

View file

@ -1,67 +0,0 @@
# 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

@ -1,26 +0,0 @@
# 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,44 +0,0 @@
#!/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,38 +0,0 @@
#!/bin/bash
# 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.
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
while IFS= read -r -d $'\0' event
do
# Remove the cg-ipc header
event="${event:6}"
if [[ "$(echo "${event}" | jq ".event_name")" = "\"dump\"" ]]
then
curr_output="$(echo "${event}"|jq ".curr_output")"
curr_workspace="$(echo "${event}"|jq -r ".outputs.${curr_output}.curr_workspace")"
# Print the process names of the view on the current workspace. jq retrieves
# their PID and ps is then used to retrieve the process names.
# shellcheck disable=2046
(echo -n "message ";ps -o comm=Command -p $(echo "${event}"|jq -r ".outputs.${curr_output}.workspaces[$((curr_workspace-1))].views[].pid")|tail +2|sed ':a; N; $!ba; s/\n/||/g') >&3
break
fi
done <&4

View file

@ -1,7 +1,6 @@
# Copyright 2020 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
# General settings and key bindings
######################
# General settings an key bindings
######################
exec xterm
@ -24,7 +23,6 @@ bind N nextscreen
bind P prevscreen
bind a time
bind C-n movetonextscreen
bind C-p movetoprevscreen
bind H exchangeleft
bind J exchangedown
bind K exchangeup
@ -35,35 +33,15 @@ bind k focusup
bind l focusright
bind t exec xterm
bind C-k close
# 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)
cursor enable
# send a custom event over the socket
# custom_event Hello World!
## Workspaces
bind 1 screen 1
bind 2 screen 2
bind 3 screen 3
bind 4 screen 4
bind 5 screen 5
bind 6 screen 6
bind A-1 movetoscreen 1
bind A-2 movetoscreen 2
bind A-3 movetoscreen 3
bind A-4 movetoscreen 4
bind A-5 movetoscreen 5
bind A-6 movetoscreen 6
######################
#Workspaces
######################
definekey top A-1 workspace 1
definekey top A-2 workspace 2
definekey top A-3 workspace 3
@ -85,33 +63,18 @@ 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 configuration
######################
output eDP-1 pos 0 0 res 1366x768 rate 60
output eDP-1 disable
output eDP-1 enable
output eDP-1 permanent
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,7 +1,5 @@
// 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.
/* This file is used by the fuzzer in order to prevent executing shell commands.
*/
#define _GNU_SOURCE
#include "../output.h"
#include <cairo.h>
@ -10,7 +8,7 @@
#include <wlr/render/wlr_renderer.h>
int
fork(void) {
fork() {
return 1;
}

View file

@ -1,5 +1,10 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2018-2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#define _POSIX_C_SOURCE 200812L
@ -17,24 +22,19 @@
#include <wlr/backend.h>
#include <wlr/backend/headless.h>
#include <wlr/backend/multi.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_control_v1.h>
#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>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_viewporter.h>
#if CG_HAS_XWAYLAND
#include <wlr/types/wlr_xcursor_manager.h>
#endif
@ -47,7 +47,6 @@
#endif
#include "../idle_inhibit_v1.h"
#include "../input_manager.h"
#include "../keybinding.h"
#include "../output.h"
#include "../parse.h"
@ -86,8 +85,17 @@ drop_permissions(void) {
return true;
}
static bool
parse_args(struct cg_server *server, int argc, char *argv[]) {
server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL;
#ifdef DEBUG
server->debug_damage_tracking = false;
#endif
return true;
}
void
cleanup(void) {
cleanup() {
server.running = false;
#if CG_HAS_XWAYLAND
if(xwayland != NULL) {
@ -109,98 +117,60 @@ cleanup(void) {
seat_destroy(server.seat);
/* This function is not null-safe, but we only ever get here
with a proper wl_display. */
wl_display_destroy(server.wl_display);
wlr_output_layout_destroy(server.output_layout);
}
int
LLVMFuzzerInitialize(int *argc, char ***argv) {
struct wl_event_loop *event_loop = NULL;
struct wlr_backend *backend = NULL;
struct wlr_renderer *renderer = NULL;
struct wlr_compositor *compositor = NULL;
struct wlr_data_device_manager *data_device_manager = NULL;
struct wlr_server_decoration_manager *server_decoration_manager = NULL;
struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager = NULL;
struct wlr_screencopy_manager_v1 *screencopy_manager = NULL;
struct wlr_data_control_manager_v1 *data_control_manager = NULL;
struct wlr_viewporter *viewporter = NULL;
struct wlr_presentation *presentation = NULL;
struct wlr_xdg_output_manager_v1 *output_manager = NULL;
struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
struct wlr_xdg_shell *xdg_shell = NULL;
#if CG_HAS_XWAYLAND
struct wlr_xwayland *xwayland = NULL;
#endif
wl_list_init(&server.input_config);
wl_list_init(&server.output_config);
wl_list_init(&server.output_priorities);
wl_list_init(&server.outputs);
wl_list_init(&server.disabled_outputs);
int ret = 0;
if(!parse_args(&server, *argc, *argv)) {
return 1;
}
#ifdef DEBUG
wlr_log_init(WLR_DEBUG, NULL);
#else
wlr_log_init(WLR_ERROR, NULL);
#endif
server.modes = malloc(4 * sizeof(char *));
if(!server.modes) {
wlr_log(WLR_ERROR, "Error allocating mode array");
goto end;
}
/* Wayland requires XDG_RUNTIME_DIR to be set. */
if(!getenv("XDG_RUNTIME_DIR")) {
wlr_log(WLR_INFO, "XDG_RUNTIME_DIR is not set in the environment");
wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment");
return 1;
}
server.wl_display = wl_display_create();
if(!server.wl_display) {
wlr_log(WLR_ERROR, "Cannot allocate a Wayland display");
free(server.modes);
server.modes = NULL;
goto end;
}
server.xcursor_size = XCURSOR_SIZE;
const char *env_cursor_size = getenv("XCURSOR_SIZE");
if(env_cursor_size && strlen(env_cursor_size) > 0) {
errno = 0;
char *end;
unsigned size = strtoul(env_cursor_size, &end, 10);
if(!*end && errno == 0) {
server.xcursor_size = size;
}
return 1;
}
server.running = true;
server.modes = malloc(4 * sizeof(char *));
server.modes[0] = strdup("top");
server.modes[1] = strdup("root");
server.modes[2] = strdup("resize");
server.modes[3] = NULL;
if(server.modes[0] == NULL || server.modes[1] == NULL ||
server.modes[2] == NULL) {
wlr_log(WLR_ERROR, "Error allocating default modes");
goto end;
}
server.nws = 1;
server.views_curr_id = 1;
server.tiles_curr_id = 1;
server.message_config.fg_color[0] = 0.0;
server.message_config.fg_color[1] = 0.0;
server.message_config.fg_color[2] = 0.0;
server.message_config.fg_color[3] = 1.0;
server.message_timeout = 2;
server.message_config.bg_color[0] = 0.9;
server.message_config.bg_color[1] = 0.85;
server.message_config.bg_color[2] = 0.85;
server.message_config.bg_color[3] = 1.0;
server.message_config.display_time = 2;
server.message_config.font = strdup("pango:Monospace 10");
event_loop = wl_display_get_event_loop(server.wl_display);
server.event_loop = event_loop;
backend = wlr_multi_backend_create(server.wl_display);
if(!backend) {
@ -226,6 +196,11 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
};
if(!drop_permissions()) {
ret = 1;
goto end;
}
server.keybindings = keybinding_list_init();
if(server.keybindings == NULL || server.keybindings->keybindings == NULL) {
wlr_log(WLR_ERROR, "Unable to allocate keybindings");
@ -233,24 +208,19 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
server.renderer = wlr_renderer_autocreate(backend);
if(!server.renderer) {
wlr_log(WLR_ERROR, "Unable to create the wlroots renderer");
ret = 1;
goto end;
}
wl_list_init(&server.output_config);
server.allocator =
wlr_allocator_autocreate(server.backend, server.renderer);
if(!server.allocator) {
wlr_log(WLR_ERROR, "Unable to create the wlroots allocator");
ret = 1;
goto end;
}
renderer = wlr_backend_get_renderer(backend);
wlr_renderer_init_wl_display(renderer, server.wl_display);
wlr_renderer_init_wl_display(server.renderer, server.wl_display);
server.bg_color = malloc(4 * sizeof(float));
server.bg_color[0] = 0;
server.bg_color[1] = 0;
server.bg_color[2] = 0;
server.bg_color[3] = 1;
wl_list_init(&server.outputs);
wl_list_init(&server.disabled_outputs);
server.bg_color = calloc(4, sizeof(float *));
server.output_layout = wlr_output_layout_create();
if(!server.output_layout) {
wlr_log(WLR_ERROR, "Unable to create output layout");
@ -258,28 +228,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
if(ipc_init(&server) != 0) {
wlr_log(WLR_ERROR, "Failed to initialize IPC");
ret = 1;
goto end;
}
server.scene = wlr_scene_create();
if(!server.scene) {
wlr_log(WLR_ERROR, "Unable to create scene");
ret = 1;
goto end;
}
server.scene_output_layout =
wlr_scene_attach_output_layout(server.scene, server.output_layout);
compositor = wlr_compositor_create(server.wl_display, 6, server.renderer);
if(!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");
ret = 1;
goto end;
}
data_device_manager = wlr_data_device_manager_create(server.wl_display);
if(!data_device_manager) {
wlr_log(WLR_ERROR, "Unable to create the data device manager");
@ -287,16 +235,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
server.input = input_manager_create(&server);
data_control_manager =
wlr_data_control_manager_v1_create(server.wl_display);
if(!data_control_manager) {
wlr_log(WLR_ERROR, "Unable to create the data control manager");
ret = 1;
goto end;
}
/* Configure a listener to be notified when new outputs are
* available on the backend. We use this only to detect the
* first output and ignore subsequent outputs. */
@ -310,7 +248,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
server.idle = wlr_idle_notifier_v1_create(server.wl_display);
server.idle = wlr_idle_create(server.wl_display);
if(!server.idle) {
wlr_log(WLR_ERROR, "Unable to create the idle tracker");
ret = 1;
@ -328,7 +266,7 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
&server.new_idle_inhibitor_v1);
wl_list_init(&server.inhibitors);
xdg_shell = wlr_xdg_shell_create(server.wl_display, 3);
xdg_shell = wlr_xdg_shell_create(server.wl_display);
if(!xdg_shell) {
wlr_log(WLR_ERROR, "Unable to create the XDG shell interface");
ret = 1;
@ -359,21 +297,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
wlr_server_decoration_manager_set_default_mode(
server_decoration_manager, WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
viewporter = wlr_viewporter_create(server.wl_display);
if(!viewporter) {
wlr_log(WLR_ERROR, "Unable to create the viewporter interface");
ret = 1;
goto end;
}
presentation = wlr_presentation_create(server.wl_display, server.backend);
if(!presentation) {
wlr_log(WLR_ERROR, "Unable to create the presentation interface");
ret = 1;
goto end;
}
wlr_scene_set_presentation(server.scene, presentation);
export_dmabuf_manager =
wlr_export_dmabuf_manager_v1_create(server.wl_display);
if(!export_dmabuf_manager) {
@ -397,13 +320,6 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
if(!wlr_primary_selection_v1_device_manager_create(server.wl_display)) {
wlr_log(WLR_ERROR,
"Unable to create the primary selection device manager");
ret = 1;
goto end;
}
gamma_control_manager =
wlr_gamma_control_manager_v1_create(server.wl_display);
if(!gamma_control_manager) {
@ -412,6 +328,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
goto end;
}
compositor = wlr_compositor_create(server.wl_display, renderer);
if(!compositor) {
wlr_log(WLR_ERROR, "Unable to create the wlroots compositor");
ret = 1;
goto end;
}
#if CG_HAS_XWAYLAND
xwayland = wlr_xwayland_create(server.wl_display, compositor, true);
if(!xwayland) {
@ -422,6 +345,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
server.new_xwayland_surface.notify = handle_xwayland_surface_new;
wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface);
xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE);
if(!xcursor_manager) {
wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager");
ret = 1;
goto end;
}
if(setenv("DISPLAY", xwayland->display_name, true) < 0) {
wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland.",
"Clients may not be able to connect");
@ -430,15 +360,18 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
xwayland->display_name);
}
struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
server.seat->xcursor_manager, DEFAULT_XCURSOR, 1);
if(wlr_xcursor_manager_load(xcursor_manager, 1)) {
wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme");
}
struct wlr_xcursor *xcursor =
wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1);
if(xcursor) {
struct wlr_xcursor_image *image = xcursor->images[0];
wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4,
image->width, image->height, image->hotspot_x,
image->hotspot_y);
}
#endif
const char *socket = wl_display_add_socket_auto(server.wl_display);
@ -458,32 +391,42 @@ LLVMFuzzerInitialize(int *argc, char ***argv) {
wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.",
"Clients may not be able to connect");
} else {
fprintf(stderr,
"Cagebreak " CG_VERSION " is running on Wayland display %s\n",
wlr_log(WLR_DEBUG,
"Cagebreak " CG_VERSION " is running on Wayland display %s",
socket);
}
#if CG_HAS_XWAYLAND
wlr_xwayland_set_seat(xwayland, server.seat->seat);
#endif
/* Place the cursor to the top left of the output layout. */
wlr_cursor_warp(server.seat->cursor, NULL, 0, 0);
if(!drop_permissions()) {
ret = 1;
goto end;
}
/* Place the cursor to the topl left of the output layout. */
wlr_cursor_warp(server.seat->cursor, NULL, 0, 0);
atexit(cleanup);
// server.wl_display->run = 1;
return 0;
end:
cleanup();
return ret;
}
void
move_cursor(char *line, struct cg_server *server) {
return; // TODO
long del = 0;
char *delstr = strtok_r(NULL, ";", &line);
enum wlr_axis_orientation orientation =
(*(line++) == '0') ? WLR_AXIS_ORIENTATION_VERTICAL
: WLR_AXIS_ORIENTATION_HORIZONTAL;
if(delstr == NULL) {
return;
}
del = strtol(delstr, NULL, 10);
struct wlr_event_pointer_axis event = {.device = NULL,
.time_msec = 0,
.source = WLR_AXIS_SOURCE_WHEEL,
.orientation = orientation,
.delta = del * 15,
.delta_discrete = del};
// TODO dispatch_cursor_axis(server->seat->cursor, &event);
}
void
add_output_callback(struct wlr_backend *backend, void *data) {
long *dims = data;
@ -515,6 +458,88 @@ create_output(char *line, struct cg_server *server) {
wlr_multi_for_each_backend(server->backend, add_output_callback, dims);
}
void
add_input_device_callback(struct wlr_backend *backend, void *data) {
enum wlr_input_device_type *type = data;
wlr_headless_add_input_device(backend, *type);
}
void
create_input_device(char *line, struct cg_server *server) {
enum wlr_input_device_type type;
if(*line != '\0') {
if(strncmp(line, "kbd", 3) == 0) {
type = WLR_INPUT_DEVICE_KEYBOARD;
wlr_multi_for_each_backend(server->backend,
add_input_device_callback, &type);
} else if(strncmp(line, "ptr", 3) == 0) {
type = WLR_INPUT_DEVICE_POINTER;
wlr_multi_for_each_backend(server->backend,
add_input_device_callback, &type);
} else if(strncmp(line, "tch", 3) == 0) {
type = WLR_INPUT_DEVICE_TOUCH;
wlr_multi_for_each_backend(server->backend,
add_input_device_callback, &type);
}
}
}
void
destroy_input_device(char *line, struct cg_server *server) {
long devn = 0;
if(line[0] != '\0') {
devn = strtol(line + 1, NULL, 10);
}
if(line != NULL) {
if(strncmp(line, "k", 1) == 0) {
if(wl_list_empty(&server->seat->keyboard_groups)) {
return;
}
devn = devn % wl_list_length(&server->seat->keyboard_groups);
struct cg_keyboard_group *group, *group_tmp;
wl_list_for_each_safe(group, group_tmp,
&server->seat->keyboard_groups, link) {
if(devn == 0) {
wl_list_remove(&group->link);
wlr_keyboard_group_destroy(group->wlr_group);
wl_event_source_remove(group->key_repeat_timer);
free(group);
break;
}
--devn;
}
} else if(strncmp(line, "p", 1) == 0) {
if(wl_list_empty(&server->seat->pointers)) {
return;
}
devn = devn % wl_list_length(&server->seat->pointers);
struct cg_pointer *pointer, *pointer_tmp;
wl_list_for_each_safe(pointer, pointer_tmp, &server->seat->pointers,
link) {
if(devn == 0) {
pointer->destroy.notify(&pointer->destroy, NULL);
break;
}
--devn;
}
} else if(strncmp(line, "t", 1) == 0) {
if(wl_list_empty(&server->seat->touch)) {
return;
}
devn = devn % wl_list_length(&server->seat->touch);
struct cg_touch *touch, *touch_tmp;
wl_list_for_each_safe(touch, touch_tmp, &server->seat->touch,
link) {
if(devn == 0) {
touch->destroy.notify(&touch->destroy, NULL);
break;
}
--devn;
}
}
}
}
void
destroy_output(char *line, struct cg_server *server) {
if(wl_list_length(&server->outputs) < 2) {
@ -534,4 +559,5 @@ destroy_output(char *line, struct cg_server *server) {
--outpn;
}
}
it->damage_destroy.notify(&it->damage_destroy, NULL);
}

View file

@ -1,5 +1,10 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2018-2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#ifndef CG_FUZZ_LIB_H
#define CG_FUZZ_LIB_H
@ -21,7 +26,7 @@ extern struct wlr_xcursor_manager *xcursor_manager;
#endif
void
cleanup(void);
cleanup();
int
LLVMFuzzerInitialize(int *argc, char ***argv);

View file

@ -1,5 +1,10 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2018-2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#define _POSIX_C_SOURCE 200812L
@ -29,10 +34,11 @@
int
set_configuration(struct cg_server *server, char *content) {
char *line;
while((line = strtok_r(NULL, "\n", &content)) != NULL) {
for(unsigned int line_num = 1;
(line = strtok_r(NULL, "\n", &content)) != NULL; ++line_num) {
line[strcspn(line, "\n")] = '\0';
if(*line != '\0' && *line != '#') {
char *errstr = NULL;
char *errstr;
server->running = true;
if(parse_rc_line(server, line, &errstr) != 0) {
if(errstr != NULL) {
@ -50,9 +56,10 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if(size == 0) {
return 0;
}
char *str = malloc(sizeof(char) * size);
strncpy(str, (char *)data, size);
str[size - 1] = 0;
int max_line_size = 256 > size ? size : 256;
char *str = malloc(sizeof(char) * max_line_size);
strncpy(str, (char *)data, max_line_size);
str[max_line_size - 1] = 0;
set_configuration(&server, str);
free(str);
keybinding_list_free(server.keybindings);

35
fuzz/meson.build Normal file
View file

@ -0,0 +1,35 @@
fuzz_sources = [
'fuzz-parse.c',
'fuzz-lib.c',
]
fuzz_headers = [
'../parse.h',
'fuzz-lib.h',
]
inc = include_directories(['..','../build/'])
fuzz_dependencies = cagebreak_dependencies
if fuzzing_engine.found()
fuzz_dependencies += fuzzing_engine
else
link_args = [ '-fsanitize=fuzzer', ]
endif
override_lib = shared_library('execl_override',
[ 'execl_override.c' ],
dependencies: [ pixman,cairo,pango,pangocairo ],
install: false
)
executable(
'fuzz-parse',
fuzz_sources + fuzz_headers + cagebreak_headers + cagebreak_sources,
dependencies: fuzz_dependencies,
install: false,
include_directories: inc,
link_args: link_args + fuzz_link_args,
c_args: fuzz_compile_args,
link_with: override_lib,
)

View file

@ -1,9 +1,15 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2020 The Cagebreak Authors
* Copyright (C) 2018-2019 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#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,13 +21,20 @@ 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_notifier_v1_set_inhibited(server->idle, inhibited);
wlr_idle_set_enabled(server->idle, NULL, !inhibited);
}
#if CG_HAS_FANALYZE
#pragma GCC diagnostic pop
#endif
static void
handle_destroy(struct wl_listener *listener, void *data) {

View file

@ -1,5 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_IDLE_INHIBIT_H
#define CG_IDLE_INHIBIT_H

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 2 KiB

22
input.h
View file

@ -1,22 +0,0 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef _CG_INPUT_H
#define _CG_INPUT_H
#include <stdbool.h>
struct cg_input_device;
struct cg_input_config;
struct cg_server;
void
cg_input_configure_libinput_device(struct cg_input_device *device);
void
cg_input_apply_config(struct cg_input_config *config, struct cg_server *server);
bool
cg_libinput_device_is_builtin(struct cg_input_device *device);
#endif

View file

@ -1,447 +0,0 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#define _POSIX_C_SOURCE 200812L
#include "input_manager.h"
#include "config.h"
#include "input.h"
#include "seat.h"
#include "server.h"
#include <ctype.h>
#include <float.h>
#include <libevdev/libevdev.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/backend/libinput.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/util/log.h>
void
strip_whitespace(char *str) {
static const char whitespace[] = " \f\n\r\t\v";
size_t len = strlen(str);
size_t start = strspn(str, whitespace);
memmove(str, &str[start], len + 1 - start);
if(*str) {
for(len -= start + 1; isspace(str[len]); --len) {
}
str[len + 1] = '\0';
}
}
char *
input_device_get_identifier(struct wlr_input_device *device) {
int vendor = device->vendor;
int product = device->product;
char *name = strdup(device->name ? device->name : "");
strip_whitespace(name);
char *p = name;
for(; *p; ++p) {
// There are in fact input devices with unprintable characters in its
// name
if(*p == ' ' || !isprint(*p)) {
*p = '_';
}
}
const char *fmt = "%d:%d:%s";
int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1;
char *identifier = malloc(len);
if(!identifier) {
wlr_log(WLR_ERROR, "Unable to allocate unique input device name");
free(name);
return NULL;
}
snprintf(identifier, len, fmt, vendor, product, name);
free(name);
return identifier;
}
void
input_manager_handle_device_destroy(struct wl_listener *listener, void *data) {
struct cg_input_device *input_device =
wl_container_of(listener, input_device, device_destroy);
if(!input_device) {
wlr_log(WLR_ERROR, "Could not find cagebreak input device to destroy");
return;
}
seat_remove_device(input_device->server->seat, input_device);
wl_list_remove(&input_device->link);
wl_list_remove(&input_device->device_destroy.link);
free(input_device->identifier);
free(input_device);
}
struct cg_input_config *
input_manager_create_empty_input_config(void) {
struct cg_input_config *cfg = calloc(1, sizeof(struct cg_input_config));
if(cfg == NULL) {
return NULL;
}
/* Libinput devices */
cfg->tap = INT_MIN;
cfg->tap_button_map = INT_MIN;
cfg->drag = INT_MIN;
cfg->drag_lock = INT_MIN;
cfg->dwt = INT_MIN;
cfg->send_events = INT_MIN;
cfg->click_method = INT_MIN;
cfg->middle_emulation = INT_MIN;
cfg->natural_scroll = INT_MIN;
cfg->accel_profile = INT_MIN;
cfg->pointer_accel = FLT_MIN;
cfg->scroll_factor = FLT_MIN;
cfg->scroll_button = INT_MIN;
cfg->scroll_method = INT_MIN;
cfg->left_handed = INT_MIN;
/*cfg->repeat_delay = INT_MIN;
cfg->repeat_rate = INT_MIN;
cfg->xkb_numlock = INT_MIN;
cfg->xkb_capslock = INT_MIN;
cfg->xkb_file_is_set = false;
wl_list_init(&cfg->tools);*/
/* Keyboards */
cfg->enable_keybindings = -1;
cfg->repeat_delay = -1;
cfg->repeat_rate = -1;
return cfg;
}
/* cfg1 has precedence */
struct cg_input_config *
input_manager_merge_input_configs(struct cg_input_config *cfg1,
struct cg_input_config *cfg2) {
struct cg_input_config *out_cfg = calloc(1, sizeof(struct cg_input_config));
if(cfg1->identifier == NULL) {
if(cfg2->identifier != NULL) {
out_cfg->identifier = strdup(cfg2->identifier);
}
} else {
out_cfg->identifier = strdup(cfg1->identifier);
}
if(out_cfg == NULL) {
return NULL;
}
if(cfg1->tap == INT_MIN) {
out_cfg->tap = cfg2->tap;
} else {
out_cfg->tap = cfg1->tap;
}
if(cfg1->send_events == INT_MIN) {
out_cfg->send_events = cfg2->send_events;
} else {
out_cfg->send_events = cfg1->send_events;
}
if(cfg1->dwt == INT_MIN) {
out_cfg->dwt = cfg2->dwt;
} else {
out_cfg->dwt = cfg1->dwt;
}
if(cfg1->drag_lock == INT_MIN) {
out_cfg->drag_lock = cfg2->drag_lock;
} else {
out_cfg->drag_lock = cfg1->drag_lock;
}
if(cfg1->drag == INT_MIN) {
out_cfg->drag = cfg2->drag;
} else {
out_cfg->drag = cfg1->drag;
}
if(cfg1->tap_button_map == INT_MIN) {
out_cfg->tap_button_map = cfg2->tap_button_map;
} else {
out_cfg->tap_button_map = cfg1->tap_button_map;
}
if(cfg1->left_handed == INT_MIN) {
out_cfg->left_handed = cfg2->left_handed;
} else {
out_cfg->left_handed = cfg1->left_handed;
}
if(cfg1->scroll_method == INT_MIN) {
out_cfg->scroll_method = cfg2->scroll_method;
} else {
out_cfg->scroll_method = cfg1->scroll_method;
}
if(cfg1->scroll_button == INT_MIN) {
out_cfg->scroll_button = cfg2->scroll_button;
} else {
out_cfg->scroll_button = cfg1->scroll_button;
}
if(cfg1->scroll_factor == FLT_MIN) {
out_cfg->scroll_factor = cfg2->scroll_factor;
} else {
out_cfg->scroll_factor = cfg1->scroll_factor;
}
if(cfg1->pointer_accel == FLT_MIN) {
out_cfg->pointer_accel = cfg2->pointer_accel;
} else {
out_cfg->pointer_accel = cfg1->pointer_accel;
}
if(cfg1->accel_profile == INT_MIN) {
out_cfg->accel_profile = cfg2->accel_profile;
} else {
out_cfg->accel_profile = cfg1->accel_profile;
}
if(cfg1->natural_scroll == INT_MIN) {
out_cfg->natural_scroll = cfg2->natural_scroll;
} else {
out_cfg->natural_scroll = cfg1->natural_scroll;
}
if(cfg1->middle_emulation == INT_MIN) {
out_cfg->middle_emulation = cfg2->middle_emulation;
} else {
out_cfg->middle_emulation = cfg1->middle_emulation;
}
if(cfg1->click_method == INT_MIN) {
out_cfg->click_method = cfg2->click_method;
} else {
out_cfg->click_method = cfg1->click_method;
}
if(cfg1->enable_keybindings == -1) {
out_cfg->enable_keybindings = cfg2->enable_keybindings;
} else {
out_cfg->enable_keybindings = cfg1->enable_keybindings;
}
if(cfg1->repeat_delay == -1) {
out_cfg->repeat_delay = cfg2->repeat_delay;
} else {
out_cfg->repeat_delay = cfg1->repeat_delay;
}
if(cfg1->repeat_rate == -1) {
out_cfg->repeat_rate = cfg2->repeat_rate;
} 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;
}
void
apply_keyboard_group_config(struct cg_input_config *config,
struct cg_keyboard_group *group) {
if(config->enable_keybindings != -1) {
group->enable_keybindings = config->enable_keybindings;
}
int repeat_delay = 600, repeat_rate = 25;
if(config->repeat_delay != -1) {
repeat_delay = config->repeat_delay;
}
if(config->repeat_rate != -1) {
repeat_rate = config->repeat_rate;
}
wlr_keyboard_set_repeat_info(&group->wlr_group->keyboard, repeat_rate,
repeat_delay);
}
void
cg_input_manager_configure_keyboard_group(struct cg_keyboard_group *group) {
struct cg_server *server = group->seat->server;
struct cg_input_config *tot_cfg = input_manager_create_empty_input_config();
if(tot_cfg == NULL) {
return;
}
struct cg_input_config *tmp_cfg, *config = NULL;
wl_list_for_each(config, &server->input_config, link) {
if(strcmp(config->identifier, group->identifier) == 0 ||
strcmp(config->identifier, "*") == 0 ||
(strncmp(config->identifier, "type:", 5) == 0 &&
strcmp(config->identifier + 5, "keyboard") == 0)) {
tmp_cfg = tot_cfg;
if(tot_cfg->identifier == NULL ||
strcmp(tot_cfg->identifier, "*") == 0 ||
strcmp(config->identifier, group->identifier)) {
tot_cfg = input_manager_merge_input_configs(config, tot_cfg);
} else {
tot_cfg = input_manager_merge_input_configs(tot_cfg, config);
}
if(tmp_cfg->identifier != NULL) {
free(tmp_cfg->identifier);
}
free(tmp_cfg);
}
}
apply_keyboard_group_config(tot_cfg, group);
if(tot_cfg->identifier != NULL) {
free(tot_cfg->identifier);
}
free(tot_cfg);
}
void
cg_input_manager_configure(struct cg_server *server) {
struct cg_input_device *device = NULL;
wl_list_for_each(device, &server->input->devices, link) {
cg_input_configure_libinput_device(device);
}
struct cg_keyboard_group *group = NULL;
wl_list_for_each(group, &server->seat->keyboard_groups, link) {
cg_input_manager_configure_keyboard_group(group);
}
}
static void
new_input(struct cg_input_manager *input, struct wlr_input_device *device,
bool virtual) {
struct cg_input_device *input_device =
calloc(1, sizeof(struct cg_input_device));
if(!input_device) {
wlr_log(WLR_ERROR, "Could not allocate input device");
return;
}
device->data = input_device;
input_device->is_virtual = virtual;
input_device->wlr_device = device;
input_device->identifier = input_device_get_identifier(device);
input_device->server = input->server;
input_device->pointer = NULL;
input_device->touch = NULL;
wl_list_insert(&input->devices, &input_device->link);
cg_input_configure_libinput_device(input_device);
wl_signal_add(&device->events.destroy, &input_device->device_destroy);
input_device->device_destroy.notify = input_manager_handle_device_destroy;
struct cg_seat *seat = input->server->seat;
seat_add_device(seat, input_device);
}
static void
handle_new_input(struct wl_listener *listener, void *data) {
struct cg_input_manager *input =
wl_container_of(listener, input, new_input);
struct wlr_input_device *device = data;
new_input(input, device, false);
}
void
handle_virtual_keyboard(struct wl_listener *listener, void *data) {
struct cg_input_manager *input =
wl_container_of(listener, input, virtual_keyboard_new);
struct wlr_virtual_keyboard_v1 *keyboard = data;
struct wlr_input_device *device = &keyboard->keyboard.base;
new_input(input, device, true);
}
void
handle_virtual_pointer(struct wl_listener *listener, void *data) {
struct cg_input_manager *input_manager =
wl_container_of(listener, input_manager, virtual_pointer_new);
struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
struct wlr_input_device *device = &pointer->pointer.base;
new_input(input_manager, device, true);
if(event->suggested_output) {
wlr_cursor_map_input_to_output(input_manager->server->seat->cursor,
device, event->suggested_output);
}
}
struct cg_input_manager *
input_manager_create(struct cg_server *server) {
struct cg_input_manager *input = calloc(1, sizeof(struct cg_input_manager));
if(!input) {
return NULL;
}
wl_list_init(&input->devices);
input->server = server;
input->new_input.notify = handle_new_input;
wl_signal_add(&server->backend->events.new_input, &input->new_input);
input->virtual_keyboard =
wlr_virtual_keyboard_manager_v1_create(server->wl_display);
wl_signal_add(&input->virtual_keyboard->events.new_virtual_keyboard,
&input->virtual_keyboard_new);
input->virtual_keyboard_new.notify = handle_virtual_keyboard;
input->virtual_pointer =
wlr_virtual_pointer_manager_v1_create(server->wl_display);
wl_signal_add(&input->virtual_pointer->events.new_virtual_pointer,
&input->virtual_pointer_new);
input->virtual_pointer_new.notify = handle_virtual_pointer;
return input;
}
uint32_t
get_mouse_bindsym(const char *name, char **error) {
// Get event code from name
int code = libevdev_event_code_from_name(EV_KEY, name);
if(code == -1) {
size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1;
*error = malloc(len);
if(*error) {
snprintf(*error, len, "Unknown event %s", name);
}
return 0;
}
return code;
}
uint32_t
get_mouse_bindcode(const char *name, char **error) {
// Validate event code
errno = 0;
char *endptr;
int code = strtol(name, &endptr, 10);
if(endptr == name && code <= 0) {
*error = strdup("Button event code must be a positive integer.");
return 0;
} else if(errno == ERANGE) {
*error = strdup("Button event code out of range.");
return 0;
}
const char *event = libevdev_event_code_get_name(EV_KEY, code);
if(!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button",
code, event ? event : "(null)") +
1;
*error = malloc(len);
if(*error) {
snprintf(*error, len, "Event code %d (%s) is not a button", code,
event ? event : "(null)");
}
return 0;
}
return code;
}
uint32_t
input_manager_get_mouse_button(const char *name, char **error) {
uint32_t button = get_mouse_bindsym(name, error);
if(!button && !*error) {
button = get_mouse_bindcode(name, error);
}
return button;
}

View file

@ -1,127 +0,0 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_INPUT_MANAGER_H
#define CG_INPUT_MANAGER_H
#include "seat.h"
#include "server.h"
#include <wayland-server-core.h>
#include <wlr/util/box.h>
struct cg_input_manager *
input_manager_create(struct cg_server *server);
void
input_manager_handle_device_destroy(struct wl_listener *listener, void *data);
uint32_t
input_manager_get_mouse_button(const char *name, char **error);
struct cg_input_config *
input_manager_create_empty_input_config(void);
struct cg_input_config *
input_manager_merge_input_configs(struct cg_input_config *cfg1,
struct cg_input_config *cfg2);
void
cg_input_manager_configure(struct cg_server *server);
void
cg_input_manager_configure_keyboard_group(struct cg_keyboard_group *group);
struct cg_input_manager {
struct wl_list devices;
struct cg_server *server;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
struct wl_listener new_input;
struct wl_listener virtual_keyboard_new;
struct wl_listener virtual_pointer_new;
};
struct cg_input_config_mapped_from_region {
double x1, y1;
double x2, y2;
bool mm;
};
struct calibration_matrix {
bool configured;
float matrix[6];
};
enum cg_input_config_mapped_to {
MAPPED_TO_DEFAULT,
MAPPED_TO_OUTPUT,
MAPPED_TO_REGION,
};
/**
* options for input devices
*/
struct cg_input_config {
char *identifier;
/* Libinput devices */
int accel_profile;
struct calibration_matrix calibration_matrix;
int click_method;
int drag;
int drag_lock;
int dwt;
int left_handed;
int middle_emulation;
int natural_scroll;
float pointer_accel;
float scroll_factor;
/*int repeat_delay;
int repeat_rate;*/
int scroll_button;
int scroll_method;
int send_events;
int tap;
int tap_button_map;
/*char *xkb_layout;
char *xkb_model;
char *xkb_options;
char *xkb_rules;
char *xkb_variant;
char *xkb_file;
bool xkb_file_is_set;
int xkb_numlock;
int xkb_capslock;*/
struct wl_list link;
struct cg_input_config_mapped_from_region *mapped_from_region;
enum cg_input_config_mapped_to mapped_to;
char *mapped_to_output;
/*struct wlr_box *mapped_to_region;*/
/*struct wl_list tools;*/
bool capturable;
struct wlr_box region;
/* Keyboards */
int enable_keybindings;
int repeat_delay;
int repeat_rate;
};
struct cg_input_device {
char *identifier;
struct cg_server *server;
struct wlr_input_device *wlr_device;
struct wl_list link; // input_manager::devices
struct wl_listener device_destroy;
bool is_virtual;
/* Only one of the following is non-NULL depending on the type of the input
* device */
struct cg_pointer *pointer;
struct cg_touch *touch;
};
#endif

View file

@ -1,27 +1,27 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2020 The Cagebreak Authors
* Copyright (C) 2018-2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#define _DEFAULT_SOURCE
#define _POSIX_C_SOURCE 200112L
#include "ipc_server.h"
#include "message.h"
#include "parse.h"
#include "server.h"
#include "util.h"
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include <wlr/util/log.h>
static const char ipc_magic[] = {'c', 'g', '-', 'i', 'p', 'c'};
#define IPC_HEADER_SIZE sizeof(ipc_magic)
static void
handle_display_destroy(struct wl_listener *listener, void *data) {
struct cg_ipc_handle *ipc = wl_container_of(listener, ipc, display_destroy);
@ -43,9 +43,6 @@ handle_display_destroy(struct wl_listener *listener, void *data) {
int
ipc_init(struct cg_server *server) {
if(server->enable_socket == false) {
return 0;
}
struct cg_ipc_handle *ipc = &server->ipc;
ipc->socket = socket(AF_UNIX, SOCK_STREAM, 0);
if(ipc->socket == -1) {
@ -99,7 +96,6 @@ ipc_init(struct cg_server *server) {
return -1;
}
chmod(ipc->sockaddr->sun_path, 0700);
setenv("CAGEBREAK_SOCKET", ipc->sockaddr->sun_path, 1);
wl_list_init(&ipc->client_list);
@ -113,46 +109,6 @@ ipc_init(struct cg_server *server) {
return 0;
}
int
ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
struct cg_ipc_client *client = data;
if(mask & WL_EVENT_ERROR) {
ipc_client_disconnect(client);
return 0;
}
if(mask & WL_EVENT_HANGUP) {
ipc_client_disconnect(client);
return 0;
}
if(fcntl(client->fd, F_GETFD) == -1) {
return 0;
}
ssize_t written =
write(client->fd, client->write_buffer, client->write_buffer_len);
if(written == -1 && errno == EAGAIN) {
return 0;
} else if(written == -1) {
wlr_log(WLR_ERROR, "Unable to send data from queue to IPC client");
ipc_client_disconnect(client);
return 0;
}
memmove(client->write_buffer, client->write_buffer + written,
client->write_buffer_len - written);
client->write_buffer_len -= written;
if(client->write_buffer_len == 0 && client->writable_event_source) {
wl_event_source_remove(client->writable_event_source);
client->writable_event_source = NULL;
}
return 0;
}
int
ipc_handle_connection(int fd, uint32_t mask, void *data) {
(void)fd;
@ -189,8 +145,8 @@ ipc_handle_connection(int fd, uint32_t mask, void *data) {
close(client_fd);
return 0;
}
client->read_buf_cap = 64;
client->read_buffer = calloc(client->read_buf_cap, sizeof(char));
// +1 for \n and +1 for \0
client->read_buffer = malloc(sizeof(char) * (MAX_LINE_SIZE + 2));
client->read_buf_len = 0;
client->read_discard = 0;
client->server = server;
@ -198,9 +154,7 @@ ipc_handle_connection(int fd, uint32_t mask, void *data) {
client->event_source =
wl_event_loop_add_fd(server->event_loop, client_fd, WL_EVENT_READABLE,
ipc_client_handle_readable, client);
client->writable_event_source =
wl_event_loop_add_fd(server->event_loop, client_fd, WL_EVENT_WRITABLE,
ipc_client_handle_writable, client);
client->writable_event_source = NULL;
client->write_buffer_size = 128;
client->write_buffer_len = 0;
@ -237,22 +191,12 @@ ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
return 0;
}
while(read_available + client->read_buf_len >
(int32_t)client->read_buf_cap - 1) {
client->read_buf_cap *= 2;
client->read_buffer = reallocarray(client->read_buffer,
client->read_buf_cap, sizeof(char));
if(client->read_buffer == NULL) {
wlr_log(WLR_ERROR, "Unable to allocate buffer large enough to hold "
"client read data");
ipc_client_disconnect(client);
return 0;
}
}
int read_size = read_available < MAX_LINE_SIZE + 1 - client->read_buf_len
? read_available
: MAX_LINE_SIZE + 1 - client->read_buf_len;
// Append to buffer
ssize_t received =
recv(client_fd, client->read_buffer + client->read_buf_len,
read_available, 0);
ssize_t received = recv(
client_fd, client->read_buffer + client->read_buf_len, read_size, 0);
if(received == -1) {
wlr_log(WLR_ERROR, "Unable to receive data from IPC client");
ipc_client_disconnect(client);
@ -280,12 +224,8 @@ ipc_client_disconnect(struct cg_ipc_client *client) {
wl_event_source_remove(client->writable_event_source);
}
wl_list_remove(&client->link);
if(client->write_buffer != NULL) {
free(client->write_buffer);
}
if(client->read_buffer != NULL) {
free(client->read_buffer);
}
free(client->write_buffer);
free(client->read_buffer);
close(client->fd);
free(client);
}
@ -322,78 +262,16 @@ ipc_client_handle_command(struct cg_ipc_client *client) {
}
offset = (nl_pos - client->read_buffer) + 1;
}
if(offset == 0) {
wlr_log(WLR_ERROR, "Line received was longer that %d, discarding it",
MAX_LINE_SIZE);
client->read_buf_len = 0;
client->read_discard = 1;
return;
}
if(offset < client->read_buf_len) {
memmove(client->read_buffer, client->read_buffer + offset,
client->read_buf_len - offset);
}
client->read_buf_len -= offset;
}
void
ipc_send_event_client(struct cg_ipc_client *client, const char *payload,
uint32_t payload_length) {
char data[IPC_HEADER_SIZE];
memcpy(data, ipc_magic, sizeof(ipc_magic));
// +1 for terminating null character
while(client->write_buffer_len + IPC_HEADER_SIZE + payload_length + 1 >=
client->write_buffer_size) {
client->write_buffer_size *= 2;
}
if(client->write_buffer_size > 4e6) { // 4 MB
wlr_log(WLR_ERROR,
"Client write buffer too big (%zu), disconnecting client",
client->write_buffer_size);
ipc_client_disconnect(client);
return;
}
char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
if(!new_buffer) {
wlr_log(WLR_ERROR, "Unable to reallocate ipc client write buffer");
ipc_client_disconnect(client);
return;
}
client->write_buffer = new_buffer;
memcpy(client->write_buffer + client->write_buffer_len, data,
IPC_HEADER_SIZE);
client->write_buffer_len += IPC_HEADER_SIZE;
memcpy(client->write_buffer + client->write_buffer_len, payload,
payload_length);
client->write_buffer_len += payload_length;
memcpy(client->write_buffer + client->write_buffer_len, "\0", 1);
client->write_buffer_len += 1;
}
void
ipc_send_event(struct cg_server *server, const char *fmt, ...) {
if(server->enable_socket == false) {
return;
}
if(wl_list_empty(&server->ipc.client_list)) {
return;
}
va_list args;
va_start(args, fmt);
char *msg = malloc_vsprintf_va_list(fmt, args);
if(msg == NULL) {
wlr_log(WLR_ERROR, "Unable to allocate memory for ipc event");
va_end(args);
return;
}
va_end(args);
struct cg_ipc_client *it, *tmp;
uint32_t len = strlen(msg);
wl_list_for_each_safe(it, tmp, &server->ipc.client_list, link) {
if(it->writable_event_source == NULL) {
it->writable_event_source = wl_event_loop_add_fd(
server->event_loop, it->fd, WL_EVENT_WRITABLE,
ipc_client_handle_writable, it);
}
ipc_send_event_client(it, msg, len);
}
free(msg);
}

View file

@ -1,6 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_IPC_SERVER_H
#define CG_IPC_SERVER_H
@ -24,7 +21,6 @@ struct cg_ipc_client {
char *write_buffer;
// The following is for storing data between event_loop calls
uint16_t read_buf_len;
size_t read_buf_cap;
uint8_t read_discard; // 1 if the current line is to be discarded
char *read_buffer;
};
@ -37,8 +33,6 @@ struct cg_ipc_handle {
struct sockaddr_un *sockaddr;
};
void
ipc_send_event(struct cg_server *server, const char *fmt, ...);
int
ipc_init(struct cg_server *server);
int

File diff suppressed because it is too large Load diff

View file

@ -1,99 +1,57 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef KEYBINDING_H
#define KEYBINDING_H
#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <xkbcommon/xkbcommon.h>
struct cg_server;
#define FOREACH_KEYBINDING(KEYBINDING) \
KEYBINDING(KEYBINDING_RUN_COMMAND, \
exec) /* data.c is the string to execute */ \
KEYBINDING(KEYBINDING_CLOSE_VIEW, close) \
KEYBINDING(KEYBINDING_SPLIT_VERTICAL, vsplit) \
KEYBINDING(KEYBINDING_SPLIT_HORIZONTAL, hsplit) \
KEYBINDING(KEYBINDING_CHANGE_TTY, switchvt) /*data.u is the desired tty*/ \
KEYBINDING(KEYBINDING_LAYOUT_FULLSCREEN, only) \
KEYBINDING(KEYBINDING_CYCLE_VIEWS, \
cycle_views) /* data.b is 0 if forward, 1 if reverse */ \
KEYBINDING(KEYBINDING_CYCLE_TILES, \
cycle_tiles) /* data.b is 0 if forward, 1 if reverse */ \
KEYBINDING(KEYBINDING_CYCLE_OUTPUT, \
cycle_outputs) /* data.b is 0 if forward, 1 if reverse */ \
KEYBINDING(KEYBINDING_CONFIGURE_OUTPUT, \
output) /* data.o_cfg is the desired output */ \
\
KEYBINDING(KEYBINDING_CONFIGURE_MESSAGE, \
configure_message) /* data.m_cfg is the desired config */ \
KEYBINDING(KEYBINDING_CONFIGURE_INPUT, \
input) /* data.i_cfg is the desired input configuration */ \
\
KEYBINDING(KEYBINDING_QUIT, quit) \
KEYBINDING(KEYBINDING_NOOP, abort) \
KEYBINDING(KEYBINDING_SWITCH_OUTPUT, \
screen) /* data.u is the desired output */ \
KEYBINDING(KEYBINDING_SWITCH_WORKSPACE, \
workspace) /* data.u is the desired workspace */ \
KEYBINDING(KEYBINDING_SWITCH_MODE, mode) /* data.u is the desired mode */ \
KEYBINDING(KEYBINDING_SWITCH_DEFAULT_MODE, \
setmode) /* data.u is the desired mode */ \
KEYBINDING( \
KEYBINDING_RESIZE_TILE_HORIZONTAL, \
resize_tile_horizontal) /* data.i is the number of pixels to add */ \
\
KEYBINDING( \
KEYBINDING_RESIZE_TILE_VERTICAL, \
resize_tile_vertical) /* data.i is the number of pixels to add to */ \
\
KEYBINDING(KEYBINDING_MOVE_VIEW_TO_WORKSPACE, \
movetoworkspace) /* data.u is the desired workspace */ \
KEYBINDING(KEYBINDING_MOVE_VIEW_TO_OUTPUT, \
movetoscreen) /* data.u is the desired output */ \
KEYBINDING(KEYBINDING_MOVE_VIEW_TO_CYCLE_OUTPUT, \
move_view_to_cycle_output) /* data.b is 0 if forward, 1 if */ \
\
KEYBINDING(KEYBINDING_DUMP, dump) \
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) \
KEYBINDING(KEYBINDING_SWAP_RIGHT, exchangeright) \
KEYBINDING(KEYBINDING_SWAP_TOP, exchangeup) \
KEYBINDING(KEYBINDING_SWAP_BOTTOM, exchangedown) \
\
KEYBINDING(KEYBINDING_FOCUS_LEFT, focusleft) \
KEYBINDING(KEYBINDING_FOCUS_RIGHT, focusright) \
KEYBINDING(KEYBINDING_FOCUS_TOP, focusup) \
KEYBINDING(KEYBINDING_FOCUS_BOTTOM, focusdown) \
\
KEYBINDING(KEYBINDING_DEFINEKEY, \
definekey) /* data.kb is the keybinding definition */ \
KEYBINDING(KEYBINDING_BACKGROUND, \
background) /* data.color is the background color */ \
KEYBINDING(KEYBINDING_DEFINEMODE, \
definemode) /* data.c is the mode name */ \
KEYBINDING(KEYBINDING_WORKSPACES, \
workspaces) /* data.i is the number of workspaces */
#define GENERATE_ENUM(ENUM, NAME) ENUM,
#define GENERATE_STRING(STRING, NAME) #NAME,
/* Important: if you add a keybinding which uses data.c or requires "free"
* to be called, don't forget to add it to the function "keybinding_list_free"
* in keybinding.c */
enum keybinding_action { FOREACH_KEYBINDING(GENERATE_ENUM) };
enum keybinding_action {
KEYBINDING_RUN_COMMAND, // data.c is the string to execute
KEYBINDING_CLOSE_VIEW,
KEYBINDING_SPLIT_VERTICAL,
KEYBINDING_SPLIT_HORIZONTAL,
KEYBINDING_CHANGE_TTY, // data.u is the desired tty
KEYBINDING_LAYOUT_FULLSCREEN,
KEYBINDING_CYCLE_VIEWS, // data.b is 0 if forward, 1 if reverse
KEYBINDING_CYCLE_TILES, // data.b is 0 if forward, 1 if reverse
KEYBINDING_CYCLE_OUTPUT, // data.b is 0 if forward, 1 if reverse
KEYBINDING_CONFIGURE_OUTPUT, // data.o_cfg is the desired output
// configuration
KEYBINDING_QUIT,
KEYBINDING_NOOP,
KEYBINDING_SWITCH_WORKSPACE, // data.u is the desired workspace
KEYBINDING_SWITCH_MODE, // data.u is the desired mode
KEYBINDING_SWITCH_DEFAULT_MODE, // data.u is the desired mode
KEYBINDING_RESIZE_TILE_HORIZONTAL, // data.i is the number of pixels to add
// to the current width
KEYBINDING_RESIZE_TILE_VERTICAL, // data.i is the number of pixels to add to
// the current height
KEYBINDING_MOVE_VIEW_TO_WORKSPACE, // data.u is the desired workspace
KEYBINDING_MOVE_VIEW_TO_NEXT_OUTPUT,
KEYBINDING_SHOW_TIME,
extern char *keybinding_action_string[];
KEYBINDING_SWAP_LEFT,
KEYBINDING_SWAP_RIGHT,
KEYBINDING_SWAP_TOP,
KEYBINDING_SWAP_BOTTOM,
KEYBINDING_FOCUS_LEFT,
KEYBINDING_FOCUS_RIGHT,
KEYBINDING_FOCUS_TOP,
KEYBINDING_FOCUS_BOTTOM,
KEYBINDING_DEFINEKEY, // data.kb is the keybinding definition
KEYBINDING_BACKGROUND, // data.color is the background color
KEYBINDING_DEFINEMODE, // data.c is the mode name
KEYBINDING_WORKSPACES, // data.i is the number of workspaces
};
union keybinding_params {
char *c;
@ -103,8 +61,6 @@ union keybinding_params {
float color[3];
struct keybinding *kb;
struct cg_output_config *o_cfg;
struct cg_input_config *i_cfg;
struct cg_message_config *m_cfg;
};
struct keybinding {
@ -127,13 +83,12 @@ keybinding_list_push(struct keybinding_list *list,
void
keybinding_list_free(struct keybinding_list *list);
void
keybinding_cycle_outputs(struct cg_server *server, bool reverse,
bool trigger_event);
keybinding_cycle_outputs(struct cg_server *server, bool reverse);
struct keybinding **
find_keybinding(const struct keybinding_list *list,
const struct keybinding *keybinding);
struct keybinding_list *
keybinding_list_init(void);
keybinding_list_init();
int
run_action(enum keybinding_action action, struct cg_server *server,

View file

@ -1,76 +1,123 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
6arp
=AorA
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
LA==
=UJ+r
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -1,123 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
LA==
=UJ+r
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -1,76 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
PbvoKi4FeWdszeakeWuqdmKEi/+ltIk=
=uqsg
-----END PGP PUBLIC KEY BLOCK-----

View file

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

View file

@ -1,76 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
PbvoKi4FeWdszeakeWuqdmKEi/+ltIk=
=uqsg
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -1,64 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGQh0WABEADQBLQTo24k8CzFUKX4F9ROwyXLEg8HUxgfqq3jeH+0EdNs6uaT
W9IWn+Trd2iL6lvfcPpdAU737FiYLFU3GN7mMpTrdkf9HQD8FqwRtH6ikqrhXsZR
6AZLV+4K3YadV4rSkYiEM8w3wg6usMepGjO4yglIXFTW48QnkIQF6NjLeZ2alSon
OJqb//4ZoendW9GtFljUVKbpi7TRMGQuuSA1joGmBXv9TyvrrAPvG4bCqlsz4IqR
nsNSo4vs7kD9Sx4/beAYhSlqryWmB5QUK2QMi0cNN4foF9mrTQYGsoXosen1yay3
vYClDdE1ehyJylmIrq3XDC9lS1HCF7c75ru3NEXyQgYiy2sYTfB3yWkK2cU61pYl
+K50WcT6Ko2h93LGSpehAT/OaliPY+kQ9BkOPjCIVkn504O/1mpK8COCrD3pcJhA
OnACIrxSCRBKlUARtzAQ2kz+HosBGaalEPT2XJErsdEXLz/QgNjocnAmMikIghP6
3NhhsqDhL4ds044/AMUtUfo7svTYU3gOGvdHJlAqX/Tk7qAsecrBzgwzUkS2X+bN
T4SwfXJFigTl0Vntylu8tYIIDap8pLJXwRm3Y0tZOLKa1yIE0GDE78BFdYJ+Fael
pirh1qHrDySU30FOVTaEIAQodMwsAdYT9XdaXXZg5F9WJ3WpGwGIDN4PYQARAQAB
tENDYWdlYnJlYWsgU2lnbmluZyBLZXkgMTEgPGNhZ2VicmVha19zaWduaW5nX2tl
eV8xMUBwcm9qZWN0LXJlcG8uY28+iQJUBBMBCAA+FiEEToLHLGs+WKe8T/hVSQn4
TKg7uGcFAmQh0WACGwMFCQHhM4AFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
SQn4TKg7uGeEJA//ZRYkUrzOpwRLxKa11Y6QULuTMBptz9JLAZcXGUiOv4e2gZgV
nMg79iXsuqP3Za7sVaqvUZpeQcaUvYi1cnyG7JW+gombFUcBo2fqxPxykQ/LLi2s
4iFM9R9kI6NLHQt3ZcHWLNGYglA+uep5oJVNS+WN7TvTObvR7JZMzplnOu8SBoiZ
VGD7SVGYCzBGv4EFjlAy6oxjbCtZTC2j1+dxYyi987+F78bUOfH66QbYEZ+iQSYh
1+5Pj7K4WSEBhjTL3C7FjuL2NE+zTmYNNRDaDraV8t60V1lt8uYFz8+/ddDqGKet
0mFibaNTBQxjxttxcdRPvGJJPPdnbpodDmp24t40ELJ/aDb/aEb7L7HSelDAx38y
78zLgC9Of8zaZ3QryZ3svWRRURAIbb64l1QWDLQ7evZVf7iSOtc+DCRcfMPTAIXj
RNI3jZm83xLDW14y3CAhg2oyGD9oei29mjSZrhZ8LahnOW35O79EkjpGSgwRm1yS
PN1dkZX5PlXnt2/dh4kk8s86xz/gD77cK0/zNyPxqI6Ofj+/pGzm+X+apjINDl7k
r9kFqS1ksDOR/984pVY1hcuT6qiToQvH09SNXwdF1IcUndzTz8iT8ph0fNpXs1ot
m5OQCAIozso92RT/ESx1UpprCiwuFKlOxRmAEAxAdBYx/RVtI2sHKfJUDWaJAjME
EAEIAB0WIQS+Le03Ioe8TrIhPhOgx0OEimOJVQUCZCHd5wAKCRCgx0OEimOJVbyN
D/9iy+xqXGF+fdvOtgAoSL9xrwqzS/rXw37Wg7h4I0ajGheE2KlR6KGGcYTnJhkO
debD5H6bhuD5+ajaajknksCc/ikRZXvxC+rUIQtgm+HIGNgtlAYWgf4SvNVaOK4k
f8DdWqj0on+CZdNN/mh3HLbjU8quGf+iS5+5T6yVZEExT8Rf18ROM2xGHlti9zdJ
FjeY76PFQ51TKvTec8hiz7+DkogcFl9YY/I1vsRZG3/0T7JzuiXJOQvGWFYKsd7G
L92UbjD8B8agGdLeBYZcgLLNFpRDZUgPcSpo6jbA36Chnytu/Mwnsm8L/SVgb221
zsYGUAE4h+UAb6DqiGcIhEvhA89nKzM2ek5j0L2swaS67i/SIMmb1ZkTzHUNVdQX
VDpNt2eNeJnJWY0cMKeynUc/SBJK/CweKBlCjHKxgJ8U4WbYUr5p/6GJw0/l610R
IIMHLuAYMChJjXkFygGpbc5zNl/RwbkS8jIfeLMmiafRDv9EJHkPqVGKBRaj7Rp3
CsJbB2Lm+M0bB6xLtKrM18PkaGE9CuccWiQgB4g0gxPhteltRde2BozpJZQl4dDv
uRUjsC9GFgP4vaQCDHyyDRHEE9y/guo6l9m+az07HWvw2fo3zDCTP6CL7PhEmRlR
rw5M57AW2KRHaIoS1mG+aYTDuVOqcEXIOfqktc3euut3JLkCDQRkIdFgARAA4MaD
Ny6YUbkxdxsfvaUMMK/umk0U1yDNcEtjl53rzYbPTGRz28DMgZcD85w1eBPvUZ/0
0OEgpmQ/EqCnu65Enwy1uyYgN64yiU0iGpOBm6eL1gd+AdTqEGXzs8N0oWZoUOtT
9bwShSBc7Zf8SlqPy6zL8RaGy0OXerCXHy3n5jQjjVfrfPP33NaitsL579WWW7cB
exvaPeEZnbr5BfH+aOfMzmZ1qseKSbNb7juh/lvq5iGYltCULALvQkL1tDBiS72g
SRVIliEe7ir3wukdtLAYInuMMwC8T5+36gkHjJ3zL0y8w4MQVSfSmScO68MrdCNl
6yPWGjvOyQgAeBqBeg1k9zn+Bo2HyvE3ubWDgmsnIzaDCXpRkPzpUw3re7/f6fXz
VdwvGvB1aQmcOKRRXs55g8PfE/i62bx/2THxKekwW3RuAEudUvChGqxogwCZEtDy
CiP+/f7AZ3Po+z8uTTbvonReKwA1hD0lgO0X43qtDGzunwaVkpL0erjYp9JVUYo6
0oGgnKs9kKZcLXO709pwL7yyubAnWHjXLdMsOXBh9wwEaig87QsTuYMwxNkphAh7
mZRhHODXEAtD6C5B5o1HvFfYJcZ8hStqtYbIOPaW1yOKnoW1CuQ8/0D4YFZ1I25d
nK36KPNLEcg6r32te3jAugk1z+PT0eJiwYSJeFsAEQEAAYkCPAQYAQgAJhYhBE6C
xyxrPlinvE/4VUkJ+EyoO7hnBQJkIdFgAhsMBQkB4TOAAAoJEEkJ+EyoO7hnjrUQ
ALAALHGlJAGuZiS0D/4qaXk+H53b6AeVymQn909nHmt7BQqzULoMPDrykh8o9Hom
Lc0qmd0PjN54Y4kSVZgaYtHgOvTSc2q8HTGOTEbBtS6ZT9jsRilV6XF6YKygYdU0
IWhntciRCRtr9Xs6Ynb9p2g1Ji13Ic0CAZ6cEvt43ERUzU9nfTDH2GkhpQ4Rm98d
q3+SpCrY5XzlWJr7wOqKL1yLq2uW9RrxgEO+7l6OXtZ/+JzasxQeysB+zCmKJSR3
QDT0LEliFRV1x01NdJnzLiMcTwKyaRCajgLb4rZO5JI06GTuAeqafLfZlr8XbKDe
O2QoWWiGQIYPfNx6zXBuJixKeM1GnpSaCeZakBq2Ex5fIGhPzUbsM6a+c9SC0f6R
zpYOJyDge84+YwEfqb8Cn2ytgRBX6a6vBGXRIR0MqCbM4TAqbFu4v5NznITYIWAh
dYJDF1mqKgE5b4xazl48XycHArkqxCEqPChKecwAFeHYr2LAMsa4vpRUFnQCD0TC
ny1tbvSUSuEdUJH4QT/F76d6augsvrAmfLXTn4KPhs3b7r6CNS7Ii13lvPOPATXa
P5KsJ+us//WBstRfPfatVpB6nS++BXI5oI1cM7/mhDfrnPVp9/FfGGE0S3DyPKvL
b/KPMkus9TOonKoUJ0Gp4Pl391/CekGmuOhEpvSeJr9n
=aQvd
-----END PGP PUBLIC KEY BLOCK-----

View file

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

View file

@ -1,76 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
XPUssBeVi6uNhWON/EjKc0cLAfNwuBrjj6I=
=5Ie4
-----END PGP PUBLIC KEY BLOCK-----

View file

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

View file

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

View file

@ -1,372 +0,0 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#include "input.h"
#include "input_manager.h"
#include "output.h"
#include <float.h>
#include <libinput.h>
#include <libudev.h>
#include <limits.h>
#include <strings.h>
#include <wlr/backend/libinput.h>
#include <wlr/util/log.h>
static void
log_status(enum libinput_config_status status) {
if(status != LIBINPUT_CONFIG_STATUS_SUCCESS) {
wlr_log(WLR_ERROR, "Failed to apply libinput config: %s",
libinput_config_status_to_str(status));
}
}
static bool
set_send_events(struct libinput_device *device, uint32_t mode) {
if(libinput_device_config_send_events_get_mode(device) == mode) {
return false;
}
wlr_log(WLR_DEBUG, "send_events_set_mode(%" PRIu32 ")", mode);
log_status(libinput_device_config_send_events_set_mode(device, mode));
return true;
}
static bool
set_tap(struct libinput_device *device, enum libinput_config_tap_state tap) {
if(libinput_device_config_tap_get_finger_count(device) <= 0 ||
libinput_device_config_tap_get_enabled(device) == tap) {
return false;
}
wlr_log(WLR_DEBUG, "tap_set_enabled(%d)", tap);
log_status(libinput_device_config_tap_set_enabled(device, tap));
return true;
}
static bool
set_tap_button_map(struct libinput_device *device,
enum libinput_config_tap_button_map map) {
if(libinput_device_config_tap_get_finger_count(device) <= 0 ||
libinput_device_config_tap_get_button_map(device) == map) {
return false;
}
wlr_log(WLR_DEBUG, "tap_set_button_map(%d)", map);
log_status(libinput_device_config_tap_set_button_map(device, map));
return true;
}
static bool
set_tap_drag(struct libinput_device *device,
enum libinput_config_drag_state drag) {
if(libinput_device_config_tap_get_finger_count(device) <= 0 ||
libinput_device_config_tap_get_drag_enabled(device) == drag) {
return false;
}
wlr_log(WLR_DEBUG, "tap_set_drag_enabled(%d)", drag);
log_status(libinput_device_config_tap_set_drag_enabled(device, drag));
return true;
}
static bool
set_tap_drag_lock(struct libinput_device *device,
enum libinput_config_drag_lock_state lock) {
if(libinput_device_config_tap_get_finger_count(device) <= 0 ||
libinput_device_config_tap_get_drag_lock_enabled(device) == lock) {
return false;
}
wlr_log(WLR_DEBUG, "tap_set_drag_lock_enabled(%d)", lock);
log_status(libinput_device_config_tap_set_drag_lock_enabled(device, lock));
return true;
}
static bool
set_accel_speed(struct libinput_device *device, double speed) {
if(!libinput_device_config_accel_is_available(device) ||
libinput_device_config_accel_get_speed(device) == speed) {
return false;
}
wlr_log(WLR_DEBUG, "accel_set_speed(%f)", speed);
log_status(libinput_device_config_accel_set_speed(device, speed));
return true;
}
static bool
set_accel_profile(struct libinput_device *device,
enum libinput_config_accel_profile profile) {
if(!libinput_device_config_accel_is_available(device) ||
libinput_device_config_accel_get_profile(device) == profile) {
return false;
}
wlr_log(WLR_DEBUG, "accel_set_profile(%d)", profile);
log_status(libinput_device_config_accel_set_profile(device, profile));
return true;
}
static bool
set_natural_scroll(struct libinput_device *d, bool n) {
if(!libinput_device_config_scroll_has_natural_scroll(d) ||
libinput_device_config_scroll_get_natural_scroll_enabled(d) == n) {
return false;
}
wlr_log(WLR_DEBUG, "scroll_set_natural_scroll(%d)", n);
log_status(libinput_device_config_scroll_set_natural_scroll_enabled(d, n));
return true;
}
static bool
set_left_handed(struct libinput_device *device, bool left) {
if(!libinput_device_config_left_handed_is_available(device) ||
libinput_device_config_left_handed_get(device) == left) {
return false;
}
wlr_log(WLR_DEBUG, "left_handed_set(%d)", left);
log_status(libinput_device_config_left_handed_set(device, left));
return true;
}
static bool
set_click_method(struct libinput_device *device,
enum libinput_config_click_method method) {
uint32_t click = libinput_device_config_click_get_methods(device);
if((click & ~LIBINPUT_CONFIG_CLICK_METHOD_NONE) == 0 ||
libinput_device_config_click_get_method(device) == method) {
return false;
}
wlr_log(WLR_DEBUG, "click_set_method(%d)", method);
log_status(libinput_device_config_click_set_method(device, method));
return true;
}
static bool
set_middle_emulation(struct libinput_device *dev,
enum libinput_config_middle_emulation_state mid) {
if(!libinput_device_config_middle_emulation_is_available(dev) ||
libinput_device_config_middle_emulation_get_enabled(dev) == mid) {
return false;
}
wlr_log(WLR_DEBUG, "middle_emulation_set_enabled(%d)", mid);
log_status(libinput_device_config_middle_emulation_set_enabled(dev, mid));
return true;
}
static bool
set_scroll_method(struct libinput_device *device,
enum libinput_config_scroll_method method) {
uint32_t scroll = libinput_device_config_scroll_get_methods(device);
if((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 ||
libinput_device_config_scroll_get_method(device) == method) {
return false;
}
wlr_log(WLR_DEBUG, "scroll_set_method(%d)", method);
log_status(libinput_device_config_scroll_set_method(device, method));
return true;
}
static bool
set_scroll_button(struct libinput_device *dev, uint32_t button) {
uint32_t scroll = libinput_device_config_scroll_get_methods(dev);
if((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 ||
libinput_device_config_scroll_get_button(dev) == button) {
return false;
}
wlr_log(WLR_DEBUG, "scroll_set_button(%" PRIu32 ")", button);
log_status(libinput_device_config_scroll_set_button(dev, button));
return true;
}
static bool
set_dwt(struct libinput_device *device, bool dwt) {
if(!libinput_device_config_dwt_is_available(device) ||
libinput_device_config_dwt_get_enabled(device) == dwt) {
return false;
}
wlr_log(WLR_DEBUG, "dwt_set_enabled(%d)", dwt);
log_status(libinput_device_config_dwt_set_enabled(device, dwt));
return true;
}
static bool
set_calibration_matrix(struct libinput_device *dev, float mat[6]) {
if(!libinput_device_config_calibration_has_matrix(dev)) {
return false;
}
bool changed = false;
float current[6];
libinput_device_config_calibration_get_matrix(dev, current);
for(int i = 0; i < 6; i++) {
if(current[i] != mat[i]) {
changed = true;
break;
}
}
if(changed) {
wlr_log(WLR_DEBUG, "calibration_set_matrix(%f, %f, %f, %f, %f, %f)",
mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
log_status(libinput_device_config_calibration_set_matrix(dev, mat));
}
return changed;
}
void
output_get_identifier(char *identifier, size_t len, struct cg_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
snprintf(identifier, len, "%s %s %s", wlr_output->make, wlr_output->model,
wlr_output->serial);
}
struct cg_output *
output_by_name_or_id(const char *name_or_id, struct cg_server *server) {
struct cg_output *output = NULL;
wl_list_for_each(output, &server->outputs, link) {
char identifier[128];
output_get_identifier(identifier, sizeof(identifier), output);
if(strcasecmp(identifier, name_or_id) == 0 ||
strcasecmp(output->name, name_or_id) == 0) {
return output;
}
}
return NULL;
}
static bool
device_is_touchpad(struct cg_input_device *device) {
if(device->wlr_device->type != WLR_INPUT_DEVICE_POINTER ||
!wlr_input_device_is_libinput(device->wlr_device)) {
return false;
}
struct libinput_device *libinput_device =
wlr_libinput_get_device_handle(device->wlr_device);
return libinput_device_config_tap_get_finger_count(libinput_device) > 0;
}
const char *
input_device_get_type(struct cg_input_device *device) {
switch(device->wlr_device->type) {
case WLR_INPUT_DEVICE_POINTER:
if(device_is_touchpad(device)) {
return "touchpad";
} else {
return "pointer";
}
case WLR_INPUT_DEVICE_KEYBOARD:
return "keyboard";
case WLR_INPUT_DEVICE_TOUCH:
return "touch";
case WLR_INPUT_DEVICE_TABLET_TOOL:
return "tablet_tool";
case WLR_INPUT_DEVICE_TABLET_PAD:
return "tablet_pad";
case WLR_INPUT_DEVICE_SWITCH:
return "switch";
}
return "unknown";
}
void
apply_config_to_device(struct cg_input_config *config,
struct cg_input_device *input_device) {
if(wlr_input_device_is_libinput(input_device->wlr_device)) {
struct libinput_device *device =
wlr_libinput_get_device_handle(input_device->wlr_device);
if(config->mapped_to_output &&
!output_by_name_or_id(config->mapped_to_output,
input_device->server)) {
wlr_log(WLR_DEBUG,
"'%s' is mapped to offline output '%s'; disabling input",
config->identifier, config->mapped_to_output);
set_send_events(device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
} else if(config->send_events != INT_MIN) {
set_send_events(device, config->send_events);
} else {
// Have to reset to the default mode here, otherwise if
// ic->send_events is unset and a mapped output just came online
// after being disabled, we'd remain stuck sending no events.
set_send_events(
device,
libinput_device_config_send_events_get_default_mode(device));
}
if(config->tap != INT_MIN) {
set_tap(device, config->tap);
}
if(config->tap_button_map != INT_MIN) {
set_tap_button_map(device, config->tap_button_map);
}
if(config->drag != INT_MIN) {
set_tap_drag(device, config->drag);
}
if(config->drag_lock != INT_MIN) {
set_tap_drag_lock(device, config->drag_lock);
}
if(config->pointer_accel != FLT_MIN) {
set_accel_speed(device, config->pointer_accel);
}
if(config->accel_profile != INT_MIN) {
set_accel_profile(device, config->accel_profile);
}
if(config->natural_scroll != INT_MIN) {
set_natural_scroll(device, config->natural_scroll);
}
if(config->left_handed != INT_MIN) {
set_left_handed(device, config->left_handed);
}
if(config->click_method != INT_MIN) {
set_click_method(device, config->click_method);
}
if(config->middle_emulation != INT_MIN) {
set_middle_emulation(device, config->middle_emulation);
}
if(config->scroll_method != INT_MIN) {
set_scroll_method(device, config->scroll_method);
}
if(config->scroll_button != INT_MIN) {
set_scroll_button(device, config->scroll_button);
}
if(config->dwt != INT_MIN) {
set_dwt(device, config->dwt);
}
if(config->calibration_matrix.configured) {
set_calibration_matrix(device, config->calibration_matrix.matrix);
}
}
}
void
cg_input_configure_libinput_device(struct cg_input_device *input_device) {
struct cg_server *server = input_device->server;
struct cg_input_config *config = NULL;
wl_list_for_each(config, &server->input_config, link) {
const char *device_type = input_device_get_type(input_device);
if(strcmp(config->identifier, input_device->identifier) == 0 ||
strcmp(config->identifier, "*") == 0 ||
(strncmp(config->identifier, "type:", 5) == 0 &&
strcmp(config->identifier + 5, device_type) == 0)) {
apply_config_to_device(config, input_device);
}
}
}
bool
cg_libinput_device_is_builtin(struct cg_input_device *cg_device) {
if(!wlr_input_device_is_libinput(cg_device->wlr_device)) {
return false;
}
struct libinput_device *device =
wlr_libinput_get_device_handle(cg_device->wlr_device);
struct udev_device *udev_device = libinput_device_get_udev_device(device);
if(!udev_device) {
return false;
}
const char *id_path =
udev_device_get_property_value(udev_device, "ID_PATH");
if(!id_path) {
return false;
}
const char prefix[] = "platform-";
return strncmp(id_path, prefix, strlen(prefix)) == 0;
}

View file

@ -1,8 +1,8 @@
cagebreak-config(5) "Version 2.3.1" "Cagebreak Manual"
cagebreak-config(1) "Version 1.7.2" "Cagebreak Manual"
# NAME
*cagebreak-config* Cagebreak configuration file
*cagebreak-config* Cagebreak config file
# SYNOPSIS
@ -10,352 +10,141 @@ cagebreak-config(5) "Version 2.3.1" "Cagebreak Manual"
# DESCRIPTION
The cagebreak configuration is a plain text file.
Each line consists of a comment or a command and its arguments which
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.
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.
The cagebreak configuration file is a simple plain text file which configures
the way cagebreak behaves.
Each line constitutes a separate command which is parsed
independently from the rest of the file. Comments can be added
by prepending a line with the # symbol.
## COMMANDS
*abort*
Return to default mode
Return to the default mode without running any command
*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.
*background - Set background color*
Set the background color. This command expects three floating point numbers
between 0 and 1, specifying the r, g and b values respectively.
(e.g. "background 1.0 0.0 0.0" sets to background color to red)
There is no support for specifying a background image.
```
# Set background to red
background 1.0 0.0 0.0
```
*bind - Bind key to command in root mode*
This command requires a key (see *KEY DEFINITIONS*) and a command (see *COMMANDS*) as an argument.
Subsequently, pressing this key while in command mode executes the
supplied action. bind <key> <command> is equivalent to
definekey root <key> <command>
*bind <key\> <command\>*
Bind <key\> to execute <command\> if pressed in root mode
*close - Close current window*
This command closes the current window. It may be useful for windows of applications which
do not offer any method of closing them.
```
bind <key> <command>
# is equivalent to
definekey root <key> <command>
```
*definekey - Bind key to action in arbitrary mode*
This command behaves similarly to the *bind* command with the
difference that the mode in which the keybinding is activated is
specified by the user. A call to this function is to be structured as follows:
*close*
Close current window - This may be useful for windows of
applications which do not offer any method of closing them.
definekey <mode> <key> <command>
*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 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.
*definemode*
This command requires a single argument; the name of the mode to be defined.
Subsequent to a call to this function, the defined mode may be used along with
the definekey command to create a custom key mapping. Synopsis:
```
# Set font
## Set example X code font
configure_message font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
## Set example FreeType font description
configure_message font pango:monospace 10
definemode <mode>
# Set foreground RGBA to red
configure_message fg_color 1.0 0.0 0.0 1.0
# Set background RGBA to red
configure_message bg_color 1.0 0.0 0.0 1.0
# Set duration for message display to four seconds
configure_message display_time 4
```
*cursor [enable|disable]*
Enable or disable cursor
This simply hides the cursor. Pointing and clicking is
still possible.
*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.
```
# define new mode and create a mapping for it
definemode foo
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>
# is equivalent to
definekey top <key> mode root
```
*escape*
Defines the key with which the current mode can be changed to "root".
escape <key> is equivalent to definekey top <key> switch_mode root
*exchangedown*
Exchange current window with window in the tile to the bottom
Exchange the current window with the window in the tile to the bottom
*exchangeleft*
Exchange current window with window in the tile to the left
Exchange the current window with the window in the tile to the left
*exchangeright*
Exchange current window with window in the tile to the right
Exchange the current window with the window in the tile to the right
*exchangeup*
Exchange current window with window in the tile to the top
Exchange the current window with the window in the tile to the top
*exec <command\>*
Execute <command\> using *sh -c*
*exec*
Executes the supplied shell command using *sh -c "<command>"*. Synopsis:
exec <command>
*focus*
Focus next tile
*focusdown*
Focus tile to the bottom
Focus the tile to the bottom
*focusleft*
Focus tile to the left
Focus the tile to the left
*focusprev*
Focus previous tile
*focusright*
Focus tile to the right
Focus the tile to the right
*focusup*
Focus tile to the top
Focus the tile to the top
*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
for example by *cagebreak -s*. The supported input types are
- touchpad
- pointer
- keyboard
- touch
- tablet_tool
- tablet_pad
- switch
Configurations are applied sequentially. Currently, only libinput
devices may be configured. The available settings and their
corresponding values are as follows:
*accel_profile adaptive|flat*
Set pointer acceleration profile for specified input device
*calibration_matrix <6 space-separated floating point values\>*
Set calibration matrix
*click_method none|button_areas|clickfinger*
Change click method for the specified device
*drag enabled|disabled*
Enable or disable tap-and-drag for specified input device
*drag_lock enabled|disabled*
Enable or disable drag lock for specified input device
*dwt enabled|disabled*
Enable or disable disable-while-typing for specified input
device
*events enabled|disabled|disabled_on_external_mouse*
Enable or disable send_events for specified input device -
Disabling send_events disables the input device.
*keybindings [enabled|disabled]*
Enable or disable keybinding interpretation for a specific keyboard.
*left_handed enabled|disabled*
Enable or disable left handed mode for specified input device
*middle_emulation enabled|disabled*
Enable or disable middle click emulation
*natural_scroll enabled|disabled*
Enable or disable natural (inverted) scrolling for specified
input device
*pointer_accel [<-1|1\>]*
Change the pointer acceleration for specified input device
*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\>*
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 in ms for keyboards only
*repeat_rate <n\>*
Repeat rate in 1/s for keyboards only
*tap enabled|disabled*
Enable or disable tap for specified input device
*tap_button_map lrm|lmr*
Specify which button mapping to use for tapping - _lrm_ treats 1
finger as left click, 2 fingers as right click, and 3 fingers as
middle click. _lmr_ treats 1 finger as left click, 2 fingers as
middle click, and 3 fingers as right click.
message <text\>
Display a line of arbitrary text.
*mode <mode\>*
Enter mode "<mode\>" - Returns to default mode, after a command is
executed.
*mode <mode>*
Enter mode "<mode>". After a keybinding is processed, return to default mode
*movetonextscreen*
Move currently focused window to next screen
See *output* for differences between screen and output.
Move the current window to the next screen
*movetoprevscreen*
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
See *output* for differences between screen and output.
*movetoworkspace <n\>*
Move currently focused window to <n\>-th workspace
See *output* for differences between screen and output.
*movetoworkspace <n>*
Move the currently focused window to the n-th workspace
*next*
Focus next window in current tile
*nextscreen*
Focus next screen
See *output* for differences between screen and output.
Focus the next screen
*only*
Remove all splits and make current window fill the entire screen
Remove all splits and make the current window fill the entire screen
*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
no effect.
- 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,
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
counter-clockwise.
```
# Don't rotate
output DP-1 rotate 0
# rotate 90 degrees counter-clockwise
output DP-1 rotate 1
# rotate 180 degrees counter-clockwise
output DP-1 rotate 2
# rotate 270 degrees counter-clockwise
output DP-1 rotate 3
```
*output* and the *screen* family of commands are similar in that they
both deal with monitors on some level.
- *output* addresses outputs by their name and is vaguely symmetric
to *input*.
- Any *screen* command deals with the number identifying a
monitor within a Cagebreak session either explicitly or
implicitly (i.e. the commands containing next and prev).
*output <name> [[pos <xpos> <ypos> res <width>x<height> rate <rate>] | enable | disable]*
Configure the 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 and <rate> sets the refresh rate of
the monitor (often this is 50 or 60). The options enable and disable
enable or disable the output <name>. Note that if <output> is the only enabled
output, *output <output> disable* has no effect.
*prev*
Focus previous window in current tile
*prevscreen*
Focus previous screen
Focus the previous screen
*quit*
Exit cagebreak
*resizedown*
Resize current tile towards the bottom
Resize the current tile towards the bottom
*resizeleft*
Resize current tile towards the left
Resize the current tile towards the left
*resizeright*
Resize current tile towards the right
Resize the current tile towards the right
*resizeup*
Resize current tile towards the top
Resize the current tile towards the top
*screen <n\>*
Change to <n\>-th screen
See *output* for differences between screen and output.
*setmode <mode>*
Set the default mode to <mode>
*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\>
*switchvt <n\>*
Switch to tty <n\>
*switchvt <n>*
Switch to tty n
*time*
Display time
@ -363,40 +152,34 @@ output DP-1 rotate 3
*vsplit*
Split current tile vertically
*workspace <n\>*
Change to <n\>-th workspace
*workspace <n>*
Change to the n-th workspace
*workspaces <n\>*
Set number of workspaces to <n\> - <n\> is a single integer larger than 1
and less than 30.
*workspaces*
Requires a single integer larger than 1 and less than 30 as an argument. Sets the number of
workspaces to the supplied number
# MODES
By default, three modes are defined:
*top*
Default mode - Keybindings defined in this mode can be accessed
directly.
- *definekey* can be used to set keybindings for top mode.
- *setmode* can be used to set a different default mode.
The default mode. Keybindings defined in this mode can be accessed
directly, without the use of an escape key.
*root*
Command mode - Keybindings defined in this mode can be accessed
after pressing the key defined by *escape*.
- *bind* can be used to set keybindings for root mode.
The command mode. Keybindings defined in this mode can be accessed
after pressing the key defined by the *escape* command.
*resize*
Resize mode - Used to resize tiles.
*definemode* can be used to create additional modes.
Resize mode. This mode is used for resizing tiles.
# KEY DEFINITIONS
Keys are specified by their names as displayed for example by *xev*.
In addition, modifiers can be specified using the following syntax:
Modifiers can be specified using the following syntax:
<mod\>-<key\>
<mod>-<key>
The supported modifiers are:
@ -408,42 +191,30 @@ The supported modifiers are:
*S - Shift*
*2 - Mod 2*
*2 - Mod2*
*3 - Mod 3*
*5 - Mod 5*
For example to specify the keybinding Control+t, the expression
For example to specify the keybinding Control+t, the expression:
```
C-t
```
C-t
is used.
# SEE ALSO
*cagebreak(1)*
*cagebreak-socket(7)*
# BUGS
See GitHub Issues: <https://github.com/project-repo/cagebreak/issues>
Mail contact: `cagebreak @ project-repo . co`
GPG Fingerprints:
- 0A268C188D7949FEB39FD1462F2AD980247E4918
- 283D10F54201B0C6CCEE2C561DE04E4B056C749D
# LICENSE
Copyright (c) 2020-2024 The Cagebreak authors
Copyright (c) 2020-2021 The Cagebreak authors
Copyright (c) 2018-2020 Jente Hidskes
Copyright (c) 2019 The Sway authors
Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,736 +0,0 @@
cagebreak-socket(7) "Version 2.3.1" "Cagebreak Manual"
# NAME
*cagebreak-socket* Cagebreak socket
# SYNOPSIS
*ipc-socket-capable-tool \$CAGEBREAK_SOCKET*
# DESCRIPTION
The cagebreak socket is an ipc socket.
The socket is enabled if cagebreak is invoked with the `-e` flag.
The socket accepts cagebreak commands as input (see *cagebreak-config(5)* for more information).
Events are provided as output as specified in this man page.
## EVENTS
Events have a general structure as follows:
```
"cg-ipc"json object depending on the eventNULL
```
Here is an example of how this works using *only* as a command sent over the socket.
```
only
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
type of the values of each event.
*background*
- Trigger: *background* command
- JSON
- event_name: "background"
- old_bg: list of three floating point numbers denoting the old background in rgb
- new_bg: list of three floating point numbers denoting the new background in rgb
```
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]}
```
*close*
- Trigger: *close* command
- JSON
- event_name: "close"
- view_id: view id as an integer
- tile_id: tile id as an integer
- view_pid: pid of the process
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
close
cg-ipc{"event_name":"close",
"view_id":47,
"view_pid":30456,
"tile_id":47,
"workspace":1,
"output":"eDP-1",
"output_id":1}
```
*configure_input*
- Trigger: *input* command
- JSON
- event_name: "configure_input"
- input: the input as a string, as per cagebreak-config(5)
```
input * accel_profile flat
cg-ipc{"event_name":"configure_input","input":"*"}
```
*configure_message*
- Trigger: *configure_message* command
- JSON
- event_name: "configure_message"
```
configure_message fg_color 1.0 1.0 0 0
cg-ipc{"event_name":"configure_message"}
```
*configure_output*
- Trigger: *output* command
- JSON
- event_name: "configure_output"
- output: name of the output as a string
- output_id: id of the output as an integer
```
output eDP-1 rotate 0
cg-ipc{"event_name":"configure_output","output":"eDP-1","output_id":1}
```
*cursor_switch_tile*
- Trigger: Cursor crosses the border between tiles
- JSON
- event_name: "cursor_switch_tile"
- old_output: name of the old output as a string
- old_output_id: old output id as an integer
- old_tile: number of the old tile as an integer
- new_output: name of the new output as a string
- new_output_id: new output id as an integer
- new_tile: number of the new tile as an integer
```
# 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}
```
*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*
- Trigger: *nextscreen* and *prevscreen* commands
- JSON
- event_name: "cycle_outputs"
- old_output: old output name as string
- old_output_id: old output id as an integer
- new_output: new output name as string
- new_output_id: new output id as an integer
- reverse: "0" if *nextscreen* or "1" if *prevscreen*
```
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}
```
*cycle_views*
- Trigger: *next* and *prev* commands
- JSON
- event_name: "cycle_views"
- old_view_id: old view id as an integer
- old_view_pid: pid of old view
- new_view_id: new view id as an interger
- new_view_pid: pid of new view
- tile_id: tile id as an integer
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
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}
```
*definekey*
- Trigger: *definekey* command
- JSON
- event_name: "definekey"
- modifiers: number denoting the modifier as described below
- 0: no modifier
- 1: shift
- 2: alt
- 3: ctrl
- 4: logo key
- 5: modifier 2
- 6: modifier 3
- 7: modifier 5
- key: key as a number
- command: command as a string - CAVEAT: This is an internal representation of
commands which is not in one-to-one correspondance with the commands available in the config file. The differences are as follows:
- "cycle_tiles": represents any *exchange* command (e.g. *exchangeright*)
- "cycle_views": represents both the *next* and the *prev* command
- "cycle_outputs": represents *nextscreen*, *movetoprevscreen* and *prevscreen* commands
- "resize_tile_vertical": represents *resizedown* and *resizeup* commands
- "resize_tile_horizontal": represents *resizeleft* and *resizeright* commands
```
definemode foo
cg-ipc{"event_name":"definemode","mode":"foo"}
definekey foo e only
cg-ipc{"event_name":"definekey","modifiers":0,"key":101,"command":"only"}
```
*definemode*
- Trigger: *definemode* command
- JSON
- event_name: "definemode"
- mode: name of mode as string
```
definemode foo
cg-ipc{"event_name":"definemode","mode":"foo"}
```
*destroy_output*
- Trigger: removal of an output
- JSON
- event_name: "destroy_output"
- output: name of the output as a string
- output_id: id of the output as an integer
```
# remove output from the device
cg-ipc{"event_name":"destroy_output","output":"HDMI-A-1","output_id":2}
```
*dump*
- Trigger: *dump* command
- JSON
- event_name: "dump"
- nws: number of workspaces as an integer
- bg_color: list of three floating point numbers denoting the new background in rgb
- views_curr_id: id of the currently focussed view as an integer
- tiles_curr_id: id of the currently focussed tile as in integer
- 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
- id: view id as an integer
- pid: pid of the process which opened the view as an integer
- coords: object of x and y coordinates
- type: ["xdg"|"xwayland"]
- tiles: list of objects for all tiles
- id: tile id as an integer
- coords: object of x and y coordinates
- size: object of width and height
- view: view id as an integer
- keyboards: object of objects for each keyboard group
- keyboard name as a string
- commands_enabled: 0 if keybindings are disabled for the keyboard, 1 otherwise
- repeat_delay: repeat delay in milliseconds as an integer
- repeat_rate: repeat rate in 1/sec as an integer
- input_devices: object of objects for each keyboard
- identifier for a keyboard as a string
- is_virtual: 1 if virtual, 0 otherwise
- type: [keyboard|pointer|switch]
- cursor_coords: object of x and y coordinates
```
dump
cg-ipc{"event_name":"dump","nws":1,
"bg_color":[0.000000,0.000000,0.000000],
"views_curr_id":80,
"tiles_curr_id":8,
"curr_output":"eDP-1",
"default_mode":"top",
"modes":["top","root","resize"],
"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,
"pid": 2505,
"coords": {"x":0,"y":0},
"type": "xwayland"
},{
"id": 72,
"pid": 11243,
"coords": {"x":0,"y":0},
"type": "xdg"
},{
"id": 56,
"pid": 6700,
"coords": {"x":1280,"y":0},
"type": "xdg"
}],"tiles": [{
"id": 6,
"coords": {"x":0,"y":0},
"size": {"width":1280,"height":1440},
"view": 78
},{
"id": 7,
"coords": {"x":1280,"y":0},
"size": {"width":1280,"height":1440},
"view": 42
}]}]
}}
,"keyboards": {"0:1:Power_Button": {
"commands_enabled": 1,
"repeat_delay": 600,
"repeat_rate": 25
}}
,"input_devices": {"6058:20564:ThinkPad_Extra_Buttons": {
"is_virtual": 0,
"type": "switch",
},"6058:20564:ThinkPad_Extra_Buttons": {
"is_virtual": 0,
"type": "keyboard",
},"2:10:TPPS/2_Elan_TrackPoint": {
"is_virtual": 0,
"type": "pointer",
},"1:1:AT_Translated_Set_2_keyboard": {
"is_virtual": 0,
"type": "keyboard",
},"0:0:sof-hda-dsp_Headphone": {
"is_virtual": 0,
"type": "keyboard",
},"1739:52619:SYNA8004:00_06CB:CD8B_Touchpad": {
"is_virtual": 0,
"type": "pointer",
},"1739:52619:SYNA8004:00_06CB:CD8B_Mouse": {
"is_virtual": 0,
"type": "pointer",
},"0:3:Sleep_Button": {
"is_virtual": 0,
"type": "keyboard",
},"0:5:Lid_Switch": {
"is_virtual": 0,
"type": "switch",
},"0:6:Video_Bus": {
"is_virtual": 0,
"type": "keyboard",
},"0:1:Power_Button": {
"is_virtual": 0,
"type": "keyboard",
}}
,"cursor_coords":{"x":972.821761,"y":670.836215}
}
```
*focus_tile*
- Trigger: *focus* command
- JSON
- event_name: "focus_tile"
- old_tile_id: old tile id as an integer
- new_tile_id: new tile id as an integer
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
focus
cg-ipc{"event_name":"focus_tile",
"old_tile_id":14,
"new_tile_id":13,
"workspace":1,
"output":"eDP-1",
"output_id":1}
```
*fullscreen*
- Trigger: *only* command
- JSON
- event_name: "fullscreen"
- tile_id: tile id as an integer
- workspace: workspace number as an integer
- output: output as a string
- output_id: id of the output as an integer
```
only
cg-ipc{"event_name":"fullscreen",
"tile_id":3,
"workspace":1,
"output":"eDP-1",
"output_id":1}
```
*move_view_to_cycle_output*
- Trigger: *movetonextscreen* and similar commands
- JSON
- event_name: "move_view_to_cycle_output"
- view_id: view id as an integer
- view_pid: pid of the process
- old_output: name of the old output as a string
- old_output_id: old output id as an integer
- new_output: name of the new output as a string
- old_output_id: old output id as an integer
```
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}
```
*move_view_to_output*
- Trigger: *movetoscreen* command
- JSON
- event_name: "move_view_to_output"
- view_id: view id as an integer
- old_output: old output name as string
- new_output: new output name as string
```
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"}
```
*move_view_to_ws*
- Trigger: *movetoworkspace* command
- JSON
- event_name: "move_view_to_ws"
- view_id: view id as an integer
- old_workspace: old workspace number as an integer
- new_workspace: new workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
- view_pid: pid of the process
```
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}
```
*new_output*
- Trigger: a new output is physically attached
- JSON
- event_name: "new_output"
- output: new output name as a string
- output_id: id of the new output as an integer
- priority: priority as per *output* prio <n> in *cagebreak-config(5)* or default
```
# a new output is attached
cg-ipc{"event_name":"new_output","output":"HDMI-A-1","output_id":2,"priority":-1}
```
*resize_tile*
- Trigger: the *resize* family of commands
- JSON
- event_name: "resize_tile"
- tile_id: tile id as an integer
- old_dims: list of coordinates [x coordinate of lower left corner, y coordinate of lower left corner, x coordinate of upper right corner, y coordinate of upper right corner]
- new_dims: list of coordinate [x coordinate of lower left corner, y coordinate of lower left corner, x coordinate of upper right corner, y coordinate of upper right corner]
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
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}
```
*set_nws*
- Trigger: *workspaces* command
- JSON
- event_name: "set_nws"
- old_nws: old number of workspaces as an integer
- new_nws: new number of workspaces as an integer
```
workspaces 2
cg-ipc{"event_name":"set_nws","old_nws":1,"new_nws":2}
```
*split*
- Trigger: *split* command
- JSON
- event_name: "split"
- tile_id: old tile id as an integer
- new_tile_id: new tile id as an integer
- workspace: workspace number as an integer
- output: output as a string
- output_id: id of the output as an integer
- vertical: 0 if horizontal split, 1 if not
```
hsplit
cg-ipc{"event_name":"split",
"tile_id":11,
"new_tile_id":12,
"workspace":1,
"output":"eDP-1",
"output_id":1,
"vertical":0}
```
*swap_tile*
- Trigger: the *exchange* family of commands
- JSON
- event_name: "swap_tile"
- tile_id: previous tile id as an integer
- tile_pid: pid of previous tile
- swap_tile_id: swap tile id as an integer
- swap_tile_pid: pid of swap tile
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
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"}
```
*switch_default_mode*
- Trigger: *setmode* command
- JSON
- event_name: "switch_default_mode"
- old_mode: old mode name
- mode: new mode name
```
setmode top
cg-ipc{"event_name":"switch_default_mode","old_mode":"top","mode":"root"}
```
switch_output
- Trigger. *screen* command
- JSON
- event_name: "switch_output"
- old_output: name of the old output as a string
- old_output_id: old output id as an integer
- new_output: name of the new output as a string
- new_output_id: new output id as an integer
```
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}
```
switch_ws
- Trigger: *workspace* command
- JSON
- event_name: "switch_ws"
- old_workspace: old workspace number as an integer
- new_workspace: new workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
```
workspace 2
cg-ipc{"event_name":"switch_ws",
"old_workspace":1,
"new_workspace":2,
"output":"eDP-1",
"output_id":1}
```
*view_map*
- Trigger: view is opened by a process
- JSON
- event_name: "view_map"
- view_id: view id as an integer
- tile_id: tile id as an integer
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
- view_pid: pid of the process
```
# 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}
```
*view_unmap*
- Trigger: view is closed by a process
- JSON
- event_name: "view_unmap"
- view_id: view id as an integer
- tile_id: tile id as an integer
- workspace: workspace number as an integer
- output: name of the output as a string
- output_id: id of the output as an integer
- view_pid: pid of the process
```
# 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}
```
## SECURITY
The socket has to be explicitly enabled using the `-e` flag.
The socket is restricted to the user for reading, writing and execution (700).
All user software can execute arbitrary code while the cagebreak socket is running.
## EXAMPLES
*nc -U $CAGEBREAK_SOCKET*
*ncat -U $CAGEBREAK_SOCKET*
# SEE ALSO
*cagebreak(1)*
*cagebreak-config(5)*
# BUGS
See GitHub Issues: <https://github.com/project-repo/cagebreak/issues>
Mail contact: `cagebreak @ project-repo . co`
GPG Fingerprints:
- 0A268C188D7949FEB39FD1462F2AD980247E4918
- 283D10F54201B0C6CCEE2C561DE04E4B056C749D
# LICENSE
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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,8 +1,8 @@
cagebreak(1) "Version 2.3.1" "Cagebreak Manual"
cagebreak(1) "Version 1.7.2" "Cagebreak Manual"
# NAME
cagebreak - A Wayland tiling compositor
cagebreak - A Wayland tiling compositor to the likes of ratpoison
# SYNOPSIS
@ -28,31 +28,19 @@ 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 on the screen.
are displayed in a message box at the top right of the screen.
# OPTIONS
*-c <path>*
Load configuration file from <path>
*-e*
Enable socket
*-h*
Display help message and exit
*-s*
Show all available inputs and outputs
*-r*
Rotate the output 90 degrees clockwise, can be specified up to three times
*-v*
Show version number and exit
*--bs*
"bad security". Enable features with potential security implications.
Currently, this option has the following effects (possible implications
in parentheses):
- Print view titles in `dump` output (an attacker may be able to read sensitive information contained in the view title).
# ENVIRONMENT
*CAGEBREAK_SOCKET*
@ -77,25 +65,15 @@ are displayed in a message box on the screen.
# SEE ALSO
*cagebreak-config(5)*
*cagebreak-socket(7)*
# BUGS
See GitHub Issues: <https://github.com/project-repo/cagebreak/issues>
Mail contact: `cagebreak @ project-repo . co`
GPG Fingerprints:
- 0A268C188D7949FEB39FD1462F2AD980247E4918
- 283D10F54201B0C6CCEE2C561DE04E4B056C749D
# LICENSE
Copyright (c) 2020-2024 The Cagebreak authors
Copyright (c) 2020-2021 The Cagebreak authors
Copyright (c) 2018-2020 Jente Hidskes
Copyright (c) 2019 The Sway authors
Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +0,0 @@
# 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,17 +1,15 @@
# Copyright 2020 - 2024, project-repo and the cagebreak contributors
# SPDX-License-Identifier: MIT
project(
'cagebreak',
'c',
version : '2.3.1',
license : 'MIT',
default_options : ['c_std=c11', 'warning_level=3']
project('cagebreak', 'c',
version: '1.7.2',
license: 'MIT',
default_options: [
'c_std=c11',
'warning_level=3',
],
)
add_project_arguments(
[
'-DWLR_USE_UNSTABLE',
'-Werror=implicit-function-declaration',
'-Wundef',
'-Wno-unused-parameter',
],
@ -55,19 +53,17 @@ if is_freebsd
)
endif
wlroots = dependency('wlroots', version: ['>=0.17.0', '< 0.18.0'])
wlroots = dependency('wlroots', version: ['>=0.13.0', '< 0.14.0'])
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
wayland_server = dependency('wayland-server')
wayland_cursor = dependency('wayland-cursor')
wayland_client = dependency('wayland-client')
pixman = dependency('pixman-1')
xkbcommon = dependency('xkbcommon')
cairo = dependency('cairo')
pango = dependency('pango')
pangocairo = dependency('pangocairo')
fontconfig = dependency('fontconfig')
libinput = dependency('libinput')
libevdev = dependency('libevdev')
libudev = dependency('libudev')
math = cc.find_library('m')
wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
@ -127,17 +123,16 @@ conf_data.set_quoted('CG_VERSION', version)
cagebreak_main_file = [ 'cagebreak.c', ]
cagebreak_source_strings = [
'idle_inhibit_v1.c',
'input_manager.c',
'ipc_server.c',
'keybinding.c',
'workspace.c',
'output.c',
'parse.c',
'render.c',
'seat.c',
'util.c',
'view.c',
'xdg_shell.c',
'libinput.c',
'server.c',
'message.c',
'pango.c',
@ -150,6 +145,7 @@ cagebreak_header_strings = [
'workspace.h',
'output.h',
'parse.h',
'render.h',
'seat.h',
'server.h',
'util.h',
@ -190,9 +186,7 @@ cagebreak_dependencies_dict = {
'wlroots': [wlroots,true],
'xkbcommon': [xkbcommon,true],
'fontconfig': [fontconfig,true],
'libinput': [libinput,true],
'libevdev': [libevdev,true],
'libudev': [libudev,true],
'pixman': [pixman,true],
'pango': [pango,true],
'cairo': [cairo,true],
'pangocairo': [pangocairo,true],
@ -202,17 +196,15 @@ cagebreak_dependencies_dict = {
reproducible_build_versions = {
'server_protos': '-1',
'wayland_server': '1.19.0',
'wayland_client': '1.22.0',
'wayland_cursor': '1.22.0',
'wlroots': '0.17.1',
'xkbcommon': '1.6.0',
'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',
'wayland_client': '1.19.0',
'wayland_cursor': '1.19.0',
'wlroots': '0.13.0',
'xkbcommon': '1.3.0',
'fontconfig': '2.13.93',
'pixman': '0.40.0',
'pango': '1.48.4',
'cairo': '1.17.4',
'pangocairo': '1.48.4',
'math': '-1'
}
@ -226,11 +218,11 @@ foreach name, dep : cagebreak_dependencies_dict
if reproducible_build_versions[name] != '-1'
if dep[1] == false
if dep[0].version() < reproducible_build_versions[name]
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') is older than the one used to generate the binary specified in Hashes.md (' + reproducible_build_versions[name] + '). It is recommended to use an up-to-date version for compiling cagebreak.'
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') is older than the one used to generate the binary specified in the README section "Reproducible Builds" (' + reproducible_build_versions[name] + '). It is recommended to use an up-to-date version for compiling cagebreak.'
)
endif
elif reproducible_build_versions[name] != dep[0].version()
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') differs from the one used to generate the binary specified in Hashes.md (' + reproducible_build_versions[name] + '). Cagebreak does not guarantee a reproducible build for this configuration.'
warning('The installed version of "' + name + '" on your machine (' + dep[0].version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" (' + reproducible_build_versions[name] + '). Cagebreak does not guarantee a reproducible build for this configuration.'
)
break
endif
@ -238,12 +230,12 @@ foreach name, dep : cagebreak_dependencies_dict
endforeach
reproducible_build_compiler = 'gcc'
reproducible_build_compiler_version = '13.2.1'
reproducible_build_compiler_version = '11.1.0'
if cc.get_id() != reproducible_build_compiler
warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in Hashes.md (' + reproducible_build_compiler + ').')
warning('The compiler "' + cc.get_id() + '" differs from the one used to generate to binary specified in the README section "Reproducible Builds" (' + reproducible_build_compiler + ').')
elif cc.version() != reproducible_build_compiler_version
warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in Hashes.md ' + reproducible_build_compiler_version + '.')
warning('The version of ' + cc.get_id() + ' (' + cc.version() + ') differs from the one used to generate the binary specified in the README section "Reproducible Builds" ' + reproducible_build_compiler_version + '.')
endif
executable(
@ -255,23 +247,17 @@ executable(
c_args: fuzz_compile_args,
)
install_data('examples/config', install_dir : '/etc/xdg/cagebreak')
install_data('LICENSE', install_dir : '/usr/share/licenses/' + meson.project_name() + '/')
if get_option('man-pages')
scdoc = find_program('scdoc')
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')
mandir5 = join_paths(get_option('mandir'), 'man5')
mandir7 = join_paths(get_option('mandir'), 'man7')
cagebreak_man = custom_target('cagebreak_man',
output : 'cagebreak.1',
input : 'man/cagebreak.1.md',
capture : true,
command : [sh, '-c', shcommand],
capture : true,
command : [sh, '-c', 'export SOURCE_DATE_EPOCH=1621324686 ; @0@ < @INPUT@'.format(scdoc.path())],
install: true,
install_dir: mandir1
)
@ -279,60 +265,15 @@ if get_option('man-pages')
cagebreak_man = custom_target('cagebreak_config_man',
output : 'cagebreak-config.5',
input : 'man/cagebreak-config.5.md',
capture : true,
command : [sh, '-c', shcommand],
capture : true,
command : [sh, '-c', 'export SOURCE_DATE_EPOCH=1621324686 ; @0@ < @INPUT@'.format(scdoc.path())],
install: true,
install_dir: mandir5
)
cagebreak_man = custom_target('cagebreak_socket_man',
output : 'cagebreak-socket.7',
input : 'man/cagebreak-socket.7.md',
capture : true,
command : [sh, '-c', shcommand],
install: true,
install_dir: mandir7
)
endif
fuzz_sources = [
'fuzz/fuzz-parse.c',
'fuzz/fuzz-lib.c',
]
fuzz_headers = [
'parse.h',
'fuzz/fuzz-lib.h',
]
fuzz_override_lib = [ 'fuzz/execl_override.c' ]
if get_option('fuzz')
inc = include_directories(['.','build/'])
fuzz_dependencies = cagebreak_dependencies
if fuzzing_engine.found()
fuzz_dependencies += fuzzing_engine
else
link_args = [ '-fsanitize=fuzzer', ]
endif
override_lib = shared_library('execl_override',
[ fuzz_override_lib ],
dependencies: [ cairo,pango,pangocairo ],
install: false
)
executable(
'fuzz-parse',
fuzz_sources + fuzz_headers + cagebreak_headers + cagebreak_sources,
dependencies: fuzz_dependencies,
install: false,
include_directories: inc,
link_args: link_args + fuzz_link_args,
c_args: fuzz_compile_args,
link_with: override_lib,
)
subdir('fuzz')
endif
summary = [
@ -343,49 +284,3 @@ 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('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,8 +1,4 @@
# 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')

259
message.c
View file

@ -1,88 +1,18 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#include <cairo/cairo.h>
#include <drm_fourcc.h>
#include <pango/pangocairo.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wlr/backend.h>
#include <wlr/interfaces/wlr_buffer.h>
#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>
#include "message.h"
#include "output.h"
#include "pango.h"
#include "server.h"
#include "util.h"
struct msg_buffer {
struct wlr_buffer base;
void *data;
uint32_t format;
size_t stride;
};
static void
msg_buffer_destroy(struct wlr_buffer *wlr_buffer) {
struct msg_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
free(buffer->data);
free(buffer);
}
static bool
msg_buffer_begin_data_ptr_access(struct wlr_buffer *wlr_buffer, uint32_t flags,
void **data, uint32_t *format,
size_t *stride) {
struct msg_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
if(data != NULL) {
*data = (void *)buffer->data;
}
if(format != NULL) {
*format = buffer->format;
}
if(stride != NULL) {
*stride = buffer->stride;
}
return true;
}
static void
msg_buffer_end_data_ptr_access(struct wlr_buffer *wlr_buffer) {
// This space is intentionally left blank
}
static const struct wlr_buffer_impl msg_buffer_impl = {
.destroy = msg_buffer_destroy,
.begin_data_ptr_access = msg_buffer_begin_data_ptr_access,
.end_data_ptr_access = msg_buffer_end_data_ptr_access,
};
static struct msg_buffer *
msg_buffer_create(uint32_t width, uint32_t height, uint32_t stride) {
struct msg_buffer *buffer = calloc(1, sizeof(*buffer));
if(buffer == NULL) {
return NULL;
}
wlr_buffer_init(&buffer->base, &msg_buffer_impl, width, height);
buffer->format = DRM_FORMAT_ARGB8888;
buffer->stride = stride;
buffer->data = malloc(buffer->stride * height);
if(buffer->data == NULL) {
free(buffer);
return NULL;
}
return buffer;
}
cairo_subpixel_order_t
to_cairo_subpixel_order(const enum wl_output_subpixel subpixel) {
switch(subpixel) {
@ -100,14 +30,16 @@ to_cairo_subpixel_order(const enum wl_output_subpixel subpixel) {
return CAIRO_SUBPIXEL_ORDER_DEFAULT;
}
struct msg_buffer *
struct wlr_texture *
create_message_texture(const char *string, const struct cg_output *output) {
const int WIDTH_PADDING = 8;
const int HEIGHT_PADDING = 2;
const int PADDING = 2;
const int MESSAGE_HEIGHT = 17 + 2 * PADDING;
const char *font = "pango:Monospace 10";
struct wlr_texture *texture;
double scale = output->wlr_output->scale;
int width = 0;
int height = 0;
int height = MESSAGE_HEIGHT * scale;
// We must use a non-nil cairo_t for cairo_set_font_options to work.
// Therefore, we cannot use cairo_create(NULL).
@ -127,10 +59,8 @@ create_message_texture(const char *string, const struct cg_output *output) {
cairo_font_options_set_subpixel_order(
fo, to_cairo_subpixel_order(output->wlr_output->subpixel));
cairo_set_font_options(c, fo);
get_text_size(c, output->server->message_config.font, &width, &height, NULL,
scale, "%s", string);
width += 2 * WIDTH_PADDING;
height += 2 * HEIGHT_PADDING;
get_text_size(c, font, &width, NULL, NULL, scale, "%s", string);
width += 2 * PADDING;
cairo_surface_destroy(dummy_surface);
cairo_destroy(c);
@ -140,126 +70,90 @@ create_message_texture(const char *string, const struct cg_output *output) {
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
cairo_set_font_options(cairo, fo);
cairo_font_options_destroy(fo);
float *bg_col = output->server->message_config.bg_color;
cairo_set_source_rgba(cairo, bg_col[0], bg_col[1], bg_col[2], bg_col[3]);
cairo_set_source_rgba(cairo, 0.9, 0.85, 0.85, 1.0);
cairo_paint(cairo);
float *fg_col = output->server->message_config.fg_color;
cairo_set_source_rgba(cairo, fg_col[0], fg_col[1], fg_col[2], fg_col[3]);
PangoContext *pango = pango_cairo_create_context(cairo);
cairo_set_source_rgba(cairo, 0, 0, 0, 1);
cairo_set_line_width(cairo, 2);
cairo_rectangle(cairo, 0, 0, width, height);
cairo_stroke(cairo);
cairo_move_to(cairo, WIDTH_PADDING, HEIGHT_PADDING);
cairo_move_to(cairo, PADDING, PADDING);
pango_printf(cairo, output->server->message_config.font, scale, "%s",
string);
pango_printf(cairo, font, scale, "%s", string);
cairo_surface_flush(surface);
unsigned char *data = cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
struct msg_buffer *buf = msg_buffer_create(width, height, stride);
void *data_ptr;
if(!wlr_buffer_begin_data_ptr_access(&buf->base,
WLR_BUFFER_DATA_PTR_ACCESS_WRITE,
&data_ptr, NULL, NULL)) {
wlr_log(WLR_ERROR, "Failed to get pointer access to message buffer");
return NULL;
}
memcpy(data_ptr, data, stride * height);
wlr_buffer_end_data_ptr_access(&buf->base);
struct wlr_renderer *renderer =
wlr_backend_get_renderer(output->wlr_output->backend);
texture = wlr_texture_from_pixels(renderer, DRM_FORMAT_ARGB8888, stride,
width, height, data);
cairo_surface_destroy(surface);
g_object_unref(pango);
cairo_destroy(cairo);
return buf;
return texture;
}
#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_anchor anchor) {
struct wlr_box *box, enum cg_message_align align) {
struct cg_message *message = malloc(sizeof(struct cg_message));
if(!message) {
wlr_log(WLR_ERROR, "Error allocating message structure");
free(box);
return;
}
struct msg_buffer *buf = create_message_texture(string, output);
if(!buf) {
wlr_log(WLR_ERROR, "Could not create message texture");
free(box);
free(message);
return;
}
message->message = create_message_texture(string, output);
message->position = box;
wl_list_insert(&output->messages, &message->link);
double scale = output->wlr_output->scale;
int width = buf->base.width / scale;
int height = buf->base.height / scale;
int width, height;
wlr_texture_get_size(message->message, &width, &height);
message->position->width = width;
message->position->height = height;
switch(anchor) {
case CG_MESSAGE_TOP_LEFT:
message->position->x = 0;
message->position->y = 0;
break;
case CG_MESSAGE_TOP_CENTER:
message->position->x -= width / 2;
message->position->y = 0;
break;
case CG_MESSAGE_TOP_RIGHT:
switch(align) {
case CG_MESSAGE_TOP_RIGHT: {
message->position->x -= width;
message->position->y = 0;
break;
case CG_MESSAGE_BOTTOM_LEFT:
message->position->x = 0;
}
case CG_MESSAGE_BOTTOM_LEFT: {
message->position->y -= height;
break;
case CG_MESSAGE_BOTTOM_CENTER:
message->position->x -= width / 2;
message->position->y -= height;
break;
case CG_MESSAGE_BOTTOM_RIGHT:
}
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;
}
struct wlr_scene_output *scene_output =
wlr_scene_get_scene_output(output->server->scene, output->wlr_output);
if(scene_output == NULL) {
return;
}
message->message =
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);
wlr_scene_buffer_set_dest_size(message->message, width, height);
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);
wlr_output_damage_add_box(output->damage, message->position);
}
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);
va_end(ap);
uint16_t buf_len = 256;
char *buffer = (char *)malloc(buf_len * sizeof(char));
if(buffer == NULL) {
wlr_log(WLR_ERROR, "Failed to allocate buffer in message_printf");
return;
}
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, buf_len, fmt, ap);
va_end(ap);
struct wlr_box *box = malloc(sizeof(struct wlr_box));
if(box == NULL) {
@ -267,55 +161,25 @@ message_printf(struct cg_output *output, const char *fmt, ...) {
free(buffer);
return;
}
struct wlr_box output_box = output_get_layout_box(output);
struct wlr_box *output_box = wlr_output_layout_get_box(
output->server->output_layout, output->wlr_output);
box->x = output_box->width;
box->y = 0;
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,
output->server->message_config.anchor);
message_set_output(output, buffer, box, CG_MESSAGE_TOP_RIGHT);
free(buffer);
alarm(output->server->message_config.display_time);
alarm(output->server->message_timeout);
}
#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_anchor anchor, const char *fmt, ...) {
if(output->destroyed) {
free(position);
return;
}
const enum cg_message_align align, const char *fmt, ...) {
uint16_t buf_len = 256;
char *buffer = (char *)malloc(buf_len * sizeof(char));
va_list ap;
@ -324,9 +188,9 @@ 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, anchor);
message_set_output(output, buffer, position, align);
free(buffer);
alarm(output->server->message_config.display_time);
alarm(output->server->message_timeout);
}
void
@ -334,10 +198,9 @@ message_clear(struct cg_output *output) {
struct cg_message *message, *tmp;
wl_list_for_each_safe(message, tmp, &output->messages, link) {
wl_list_remove(&message->link);
struct wlr_buffer *buf = message->message->buffer;
wlr_scene_node_destroy(&message->message->node);
wlr_output_damage_add_box(output->damage, message->position);
wlr_texture_destroy(message->message);
free(message->position);
buf->impl->destroy(buf);
free(message);
}
}

View file

@ -1,6 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef MESSAGE_H
#define MESSAGE_H
@ -9,31 +6,19 @@
struct cg_output;
struct wlr_box;
struct wlr_buffer;
struct wlr_texture;
enum cg_message_anchor {
enum cg_message_align {
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 {
char *font;
int display_time;
float bg_color[4];
float fg_color[4];
enum cg_message_anchor anchor;
};
struct cg_message {
struct wlr_box *position;
struct wlr_scene_buffer *message;
struct wl_surface *surface;
struct wlr_texture *message;
struct wl_list link;
};
@ -41,7 +26,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_anchor, const char *fmt, ...);
enum cg_message_align, const char *fmt, ...);
void
message_clear(struct cg_output *output);

1085
output.c

File diff suppressed because it is too large Load diff

View file

@ -1,61 +1,40 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_OUTPUT_H
#define CG_OUTPUT_H
#include <wayland-server-core.h>
#include <wlr/util/box.h>
#include <wlr/types/wlr_box.h>
struct cg_server;
struct cg_view;
struct wlr_output;
struct wlr_output_damage;
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 wlr_output_damage *damage;
struct wl_listener mode;
struct wl_listener commit;
struct wl_listener destroy;
struct wl_listener frame;
struct wl_listener damage_frame;
struct wl_listener damage_destroy;
struct cg_workspace **workspaces;
struct wl_list messages;
struct wlr_box layout_box;
int curr_workspace;
int priority;
enum output_role role;
bool destroyed;
char *name;
struct cg_view *last_scanned_out_view;
struct wl_list link; // cg_server::outputs
};
struct cg_output_priorities {
char *ident;
int priority;
struct wl_list link;
};
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;
float scale;
int priority;
int angle; // enum wl_output_transform, -1 signifies "unspecified"
struct wl_list link; // cg_server::output_config
};
@ -63,20 +42,29 @@ 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
output_configure(struct cg_server *server, struct cg_output *output);
void
output_surface_for_each_surface(struct cg_output *output,
struct wlr_surface *surface, double ox,
double oy, cg_surface_iterator_func_t iterator,
void *user_data);
void
output_view_for_each_popup(struct cg_output *output, struct cg_view *view,
cg_surface_iterator_func_t iterator,
void *user_data);
void
output_drag_icons_for_each_surface(struct cg_output *output,
struct wl_list *drag_icons,
cg_surface_iterator_func_t iterator,
void *user_data);
void
output_damage_surface(struct cg_output *output, struct wlr_surface *surface,
double ox, double oy, bool whole);
void
output_set_window_title(struct cg_output *output, const char *title);
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,6 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#include <cairo.h>
#include <cairo/cairo.h>
#include <pango/pangocairo.h>
@ -28,7 +25,7 @@ get_pango_layout(cairo_t *cairo, const char *font, const char *text,
pango_attr_list_insert(attrs, pango_attr_scale_new(scale));
PangoFontDescription *desc = pango_font_description_from_string(font);
pango_layout_set_font_description(layout, desc);
pango_layout_set_single_paragraph_mode(layout, false);
pango_layout_set_single_paragraph_mode(layout, 1);
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
pango_font_description_free(desc);

View file

@ -1,6 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef _SWAY_PANGO_H
#define _SWAY_PANGO_H
#include <cairo/cairo.h>

649
parse.c
View file

@ -1,27 +1,30 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#define _POSIX_C_SOURCE 200812L
#include <float.h>
#include <libinput.h>
#include <limits.h>
#include <string.h>
#include <wlr/util/log.h>
#include "input_manager.h"
#include "keybinding.h"
#include "message.h"
#include "output.h"
#include "parse.h"
#include "server.h"
#include "util.h"
char *
malloc_vsprintf(const char *fmt, va_list ap) {
va_list ap2;
va_copy(ap2, ap);
int len = vsnprintf(NULL, 0, fmt, ap);
char *ret = malloc(sizeof(char) * (len + 1));
vsnprintf(ret, len + 1, fmt, ap2);
va_end(ap2);
return ret;
}
char *
log_error(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char *ret = malloc_vsprintf_va_list(fmt, args);
char *ret = malloc_vsprintf(fmt, args);
if(ret != NULL) {
wlr_log(WLR_ERROR, "%s", ret);
}
@ -78,13 +81,12 @@ parse_key(struct keybinding *keybinding, const char *key_def, char **errstr) {
int
parse_command(struct cg_server *server, struct keybinding *keybinding,
char *saveptr, char **errstr, int nesting_level);
char *saveptr, char **errstr);
/* Parse a keybinding definition and return it if successful, else return NULL
*/
struct keybinding *
parse_keybinding(struct cg_server *server, char **saveptr, char **errstr,
int nesting_level) {
parse_keybinding(struct cg_server *server, char **saveptr, char **errstr) {
struct keybinding *keybinding = malloc(sizeof(struct keybinding));
if(keybinding == NULL) {
*errstr = log_error(
@ -97,306 +99,16 @@ parse_keybinding(struct cg_server *server, char **saveptr, char **errstr,
free(keybinding);
return NULL;
}
if(parse_command(server, keybinding, *saveptr, errstr, nesting_level + 1) !=
0) {
if(parse_command(server, keybinding, *saveptr, errstr) != 0) {
free(keybinding);
return NULL;
}
return keybinding;
}
float
parse_float(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a float, got nothing");
return -1;
}
float ufloat = strtof(uint_str, NULL);
if(ufloat != NAN && ufloat != INFINITY && errno != ERANGE) {
return ufloat;
} else {
wlr_log(WLR_ERROR, "Error parsing float");
return FLT_MIN;
}
}
int
parse_uint(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a non-negative integer, got nothing");
return -1;
}
long uint = strtol(uint_str, NULL, 10);
if(uint >= 0 && uint <= INT_MAX) {
return uint;
} else {
wlr_log(WLR_ERROR,
"Error parsing non-negative integer. Must be a number larger "
"or equal to 0 and less or equal to %d",
INT_MAX);
return -1;
}
}
struct cg_input_config *
parse_input_config(char **saveptr, char **errstr) {
struct cg_input_config *cfg = input_manager_create_empty_input_config();
char *value = NULL;
char *ident = NULL;
if(cfg == NULL) {
*errstr =
log_error("Failed to allocate memory for input configuration");
goto error;
}
ident = strtok_r(NULL, " ", saveptr);
if(ident == NULL) {
*errstr = log_error(
"Expected identifier of input device to configure, got none");
goto error;
}
cfg->identifier = strdup(ident);
char *setting = strtok_r(NULL, " ", saveptr);
if(setting == NULL) {
*errstr =
log_error("Expected setting to be set on input device, got none");
goto error;
}
value = strdup(*saveptr);
if(value == NULL) {
*errstr = log_error("Failed to obtain value for input device "
"configuration of device \"%s\"",
ident);
goto error;
}
if(strcmp(setting, "accel_profile") == 0) {
if(strcmp(value, "adaptive") == 0) {
cfg->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
} else if(strcmp(value, "flat") == 0) {
cfg->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
} else {
*errstr = log_error(
"Invalid profile \"%s\" for accel_profile configuration",
value);
goto error;
}
} else if(strcmp(setting, "calibration_matrix") == 0) {
cfg->calibration_matrix.configured = true;
for(int i = 0; i < 6; ++i) {
cfg->calibration_matrix.matrix[i] = parse_float(saveptr, " ");
if(cfg->calibration_matrix.matrix[i] == FLT_MIN) {
*errstr =
log_error("Failed to read calibration matrix, expected 6 "
"floating point values separated by spaces");
goto error;
}
}
} else if(strcmp(setting, "click_method") == 0) {
if(strcmp(value, "none")) {
cfg->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
} else if(strcmp(value, "button_areas")) {
cfg->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
} else if(strcmp(value, "clickfinger")) {
cfg->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
} else {
*errstr = log_error(
"Invalid method \"%s\" for click_method configuration", value);
goto error;
}
} else if(strcmp(setting, "drag") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->drag = LIBINPUT_CONFIG_DRAG_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->drag = LIBINPUT_CONFIG_DRAG_DISABLED;
} else {
*errstr =
log_error("Invalid option \"%s\" to setting \"drag\"", value);
goto error;
}
} else if(strcmp(setting, "drag_lock") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"drag_lock\"", value);
goto error;
}
} else if(strcmp(setting, "dwt") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->dwt = LIBINPUT_CONFIG_DWT_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
} else {
*errstr =
log_error("Invalid option \"%s\" to setting \"dwt\"", value);
goto error;
}
} else if(strcmp(setting, "events") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
} else if(strcmp(value, "disabled_on_external_mouse") == 0) {
cfg->send_events =
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
} else {
*errstr =
log_error("Invalid option \"%s\" to setting \"events\"", value);
goto error;
}
} else if(strcmp(setting, "left_handed") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->left_handed = true;
} else if(strcmp(value, "disabled") == 0) {
cfg->left_handed = false;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"left_handed\"", value);
goto error;
}
} else if(strcmp(setting, "middle_emulation") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"middle_emulation\"", value);
goto error;
}
} else if(strcmp(setting, "natural_scroll") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->natural_scroll = true;
} else if(strcmp(value, "disabled") == 0) {
cfg->natural_scroll = false;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"natural_scroll\"", value);
goto error;
}
} else if(strcmp(setting, "pointer_accel") == 0) {
cfg->pointer_accel = parse_float(saveptr, " ");
if(cfg->pointer_accel == FLT_MIN) {
*errstr = log_error("Invalid option \"%s\" to setting "
"\"pointer_accel\", expected float value",
value);
goto error;
}
} else if(strcmp(setting, "scroll_button") == 0) {
char *err = NULL;
cfg->scroll_button = input_manager_get_mouse_button(value, &err);
if(err) {
*errstr = log_error("Error parsing button for \"scroll_button\" "
"setting. Returned error \"%s\"",
err);
free(err);
goto error;
}
} else if(strcmp(setting, "scroll_factor") == 0) {
cfg->scroll_factor = parse_float(saveptr, " ");
if(cfg->scroll_factor == FLT_MIN) {
*errstr = log_error("Invalid option \"%s\" to setting "
"\"scroll_factor\", expected float value",
value);
goto error;
}
} else if(strcmp(setting, "scroll_method") == 0) {
if(strcmp(value, "none") == 0) {
cfg->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
} else if(strcmp(value, "two_finger") == 0) {
cfg->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
} else if(strcmp(value, "edge") == 0) {
cfg->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
} else if(strcmp(value, "on_button_down") == 0) {
cfg->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"scroll_method\"", value);
goto error;
}
} else if(strcmp(setting, "tap") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->tap = LIBINPUT_CONFIG_TAP_ENABLED;
} else if(strcmp(value, "disabled") == 0) {
cfg->tap = LIBINPUT_CONFIG_TAP_DISABLED;
} else {
*errstr =
log_error("Invalid option \"%s\" to setting \"tap\"", value);
goto error;
}
} else if(strcmp(setting, "tap_button_map") == 0) {
if(strcmp(value, "lrm") == 0) {
cfg->tap = LIBINPUT_CONFIG_TAP_MAP_LRM;
} else if(strcmp(value, "lmr") == 0) {
cfg->tap = LIBINPUT_CONFIG_TAP_MAP_LMR;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"tap_button_map\"", value);
goto error;
}
} else if(strcmp(setting, "keybindings") == 0) {
if(strcmp(value, "enabled") == 0) {
cfg->enable_keybindings = true;
} else if(strcmp(value, "disabled") == 0) {
cfg->enable_keybindings = false;
} else {
*errstr = log_error(
"Invalid option \"%s\" to setting \"keybindings\"", value);
goto error;
}
} else if(strcmp(setting, "repeat_delay") == 0) {
cfg->repeat_delay = parse_uint(saveptr, " ");
if(cfg->repeat_delay < 0) {
*errstr = log_error("Invalid option \"%s\" to setting "
"\"repeat_delay\", expected positive integer",
value);
goto error;
}
} else if(strcmp(setting, "repeat_rate") == 0) {
cfg->repeat_rate = parse_uint(saveptr, " ");
if(cfg->repeat_rate < 0) {
*errstr = log_error("Invalid option \"%s\" to setting "
"\"repeat_rate\", expected positive integer",
value);
goto error;
}
} else {
*errstr = log_error("Invalid option to command \"input\"");
goto error;
}
free(value);
return cfg;
error:
if(cfg) {
if(cfg->identifier) {
free(cfg->identifier);
}
free(cfg);
}
if(value) {
free(value);
}
wlr_log(WLR_ERROR, "Input configuration must be of the form 'input "
"\"<ident>\" <setting> <value>'");
return NULL;
}
struct keybinding *
parse_bind(struct cg_server *server, char **saveptr, char **errstr,
int nesting_level) {
struct keybinding *keybinding =
parse_keybinding(server, saveptr, errstr, nesting_level);
parse_bind(struct cg_server *server, char **saveptr, char **errstr) {
struct keybinding *keybinding = parse_keybinding(server, saveptr, errstr);
if(keybinding == NULL) {
wlr_log(WLR_ERROR, "Could not parse keybinding for \"bind\".");
return NULL;
@ -406,8 +118,7 @@ parse_bind(struct cg_server *server, char **saveptr, char **errstr,
}
struct keybinding *
parse_definekey(struct cg_server *server, char **saveptr, char **errstr,
int nesting_level) {
parse_definekey(struct cg_server *server, char **saveptr, char **errstr) {
char *mode = strtok_r(NULL, " ", saveptr);
if(mode == NULL) {
*errstr =
@ -419,8 +130,7 @@ parse_definekey(struct cg_server *server, char **saveptr, char **errstr,
*errstr = log_error("Unknown mode \"%s\"", mode);
return NULL;
}
struct keybinding *keybinding =
parse_keybinding(server, saveptr, errstr, nesting_level);
struct keybinding *keybinding = parse_keybinding(server, saveptr, errstr);
if(keybinding == NULL) {
wlr_log(WLR_ERROR, "Could not parse keybinding for \"definekey\"");
return NULL;
@ -486,21 +196,6 @@ parse_escape(char **saveptr, char **errstr) {
return keybinding;
}
int
parse_cursor(char **saveptr, char **errstr) {
if(strcmp(*saveptr, "enable") == 0) {
return 1;
} else if(strcmp(*saveptr, "disable") == 0) {
return 0;
} else {
wlr_log(WLR_ERROR,
"Invalid option \"%s\" for \"cursor\". Expected \"enable\" or "
"\"disable\".",
*saveptr);
return -1;
}
}
char *
parse_definemode(char **saveptr, char **errstr) {
char *mode = strtok_r(NULL, " ", saveptr);
@ -528,6 +223,42 @@ parse_workspaces(char **saveptr, char **errstr) {
return nws;
}
int
parse_uint(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a non-negative integer, got nothing");
return -1;
}
long uint = strtol(uint_str, NULL, 10);
if(uint >= 0 && uint <= INT_MAX) {
return uint;
} else {
wlr_log(WLR_ERROR,
"Error parsing non-negative integer. Must be a number larger "
"or equal to 0 and less or equal to %d",
INT_MAX);
return -1;
}
}
float
parse_float(char **saveptr, const char *delim) {
char *uint_str = strtok_r(NULL, delim, saveptr);
if(uint_str == NULL) {
wlr_log(WLR_ERROR, "Expected a non-negative float, got nothing");
return -1;
}
float ufloat = strtof(uint_str, NULL);
if(ufloat >= 0) {
return ufloat;
} else {
wlr_log(WLR_ERROR, "Error parsing non-negative float. Must be a number "
"larger or equal to 0");
return -1;
}
}
int
parse_output_config_keyword(char *key_str, enum output_status *status) {
if(key_str == NULL) {
@ -535,18 +266,8 @@ parse_output_config_keyword(char *key_str, enum output_status *status) {
}
if(strcmp(key_str, "pos") == 0) {
*status = OUTPUT_DEFAULT;
} else if(strcmp(key_str, "prio") == 0) {
*status = OUTPUT_DEFAULT;
} else if(strcmp(key_str, "rotate") == 0) {
*status = OUTPUT_DEFAULT;
} else if(strcmp(key_str, "scale") == 0) {
*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 {
@ -563,14 +284,6 @@ parse_output_config(char **saveptr, char **errstr) {
log_error("Failed to allocate memory for output configuration");
goto error;
}
cfg->status = OUTPUT_DEFAULT;
cfg->pos.x = -1;
cfg->output_name = NULL;
cfg->refresh_rate = 0;
cfg->priority = -1;
cfg->scale = -1;
cfg->angle = -1;
cfg->role = OUTPUT_ROLE_DEFAULT;
char *name = strtok_r(NULL, " ", saveptr);
if(name == NULL) {
*errstr =
@ -579,9 +292,8 @@ 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\", "
"\"disable\", \"permanent\" or \"peripheral\" in "
"output configuration for output %s",
*errstr = log_error("Expected keyword \"pos\", \"enable\" or "
"\"disable\" in output configuration for output %s",
name);
goto error;
}
@ -590,56 +302,6 @@ parse_output_config(char **saveptr, char **errstr) {
return cfg;
}
if(strcmp(key_str, "rotate") == 0) {
uint32_t angle = parse_uint(saveptr, " ");
// 360 degrees is equivalent to 0 degrees
cfg->angle = angle % 4;
if(cfg->angle < 0) {
*errstr =
log_error("Error parsing option rotate for output %s", name);
goto error;
}
cfg->output_name = strdup(name);
return cfg;
}
if(strcmp(key_str, "prio") == 0) {
cfg->priority = parse_uint(saveptr, " ");
if(cfg->priority < 0) {
*errstr = log_error(
"Error parsing priority of output configuration for output %s",
name);
goto error;
}
cfg->output_name = strdup(name);
return cfg;
}
if(strcmp(key_str, "scale") == 0) {
cfg->scale = parse_float(saveptr, " ");
if(cfg->scale <= 0.0) {
*errstr =
log_error("Error parsing scale of output configuration for "
"output %s, expected positive float",
name);
goto error;
}
cfg->output_name = strdup(name);
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(
@ -690,10 +352,9 @@ parse_output_config(char **saveptr, char **errstr) {
cfg->refresh_rate = parse_float(saveptr, " ");
if(cfg->refresh_rate <= 0.0) {
*errstr =
log_error("Error parsing refresh rate of output configuration for "
"output %s, expected positive float",
name);
*errstr = log_error(
"Error parsing refresh rate of output configuration for output %s",
name);
goto error;
}
@ -707,103 +368,10 @@ error:
return NULL;
}
struct cg_message_config *
parse_message_config(char **saveptr, char **errstr) {
struct cg_message_config *cfg = calloc(1, sizeof(struct cg_message_config));
if(cfg == NULL) {
*errstr =
log_error("Failed to allocate memory for message configuration");
goto error;
}
cfg->bg_color[0] = -1;
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) {
*errstr = log_error(
"Expected setting to be set for message configuration, got none");
goto error;
}
if(strcmp(setting, "font") == 0) {
cfg->font = strdup(*saveptr);
if(cfg->font == NULL) {
*errstr = log_error("Unable to allocate memory for font descrition "
"in command \"message\"");
goto error;
}
} else if(strcmp(setting, "display_time") == 0) {
cfg->display_time = parse_uint(saveptr, " ");
if(cfg->display_time < 0) {
*errstr =
log_error("Error parsing command \"configure_message "
"display_time\", expected a non-negative integer");
goto error;
}
} else if(strcmp(setting, "bg_color") == 0) {
for(int i = 0; i < 4; ++i) {
cfg->bg_color[i] = parse_float(saveptr, " ");
if(cfg->bg_color[i] == FLT_MIN) {
*errstr = log_error(
"Error parsing command \"configure_message bg_color\", "
"expected 4 float values separated by spaces");
goto error;
}
}
} else if(strcmp(setting, "fg_color") == 0) {
for(int i = 0; i < 4; ++i) {
cfg->fg_color[i] = parse_float(saveptr, " ");
if(cfg->fg_color[i] == FLT_MIN) {
*errstr = log_error(
"Error parsing command \"configure_message bg_color\", "
"expected 4 float values separated by spaces");
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;
}
return cfg;
error:
if(cfg != NULL) {
free(cfg);
}
wlr_log(WLR_ERROR, "Message configuration must be of the form "
"'configure_message <setting> <value>'");
return NULL;
}
int
parse_command(struct cg_server *server, struct keybinding *keybinding,
char *saveptr, char **errstr, int nesting_level) {
char *saveptr, char **errstr) {
char *action = strtok_r(NULL, " ", &saveptr);
if(nesting_level >= MAX_NESTING_LEVEL) {
*errstr =
log_error("Nesting level of commands is too deep. Giving up.");
return -1;
}
if(action == NULL) {
*errstr = log_error("Expexted an action to parse, got none.");
return -1;
@ -815,10 +383,6 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
keybinding->action = KEYBINDING_SPLIT_HORIZONTAL;
} else if(strcmp(action, "quit") == 0) {
keybinding->action = KEYBINDING_QUIT;
} else if(strcmp(action, "dump") == 0) {
keybinding->action = KEYBINDING_DUMP;
} else if(strcmp(action, "show_info") == 0) {
keybinding->action = KEYBINDING_SHOW_INFO;
} else if(strcmp(action, "close") == 0) {
keybinding->action = KEYBINDING_CLOSE_VIEW;
} else if(strcmp(action, "focus") == 0) {
@ -837,24 +401,6 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
keybinding->action = KEYBINDING_LAYOUT_FULLSCREEN;
} else if(strcmp(action, "abort") == 0) {
keybinding->action = KEYBINDING_NOOP;
} else if(strcmp(action, "message") == 0) {
keybinding->action = KEYBINDING_DISPLAY_MESSAGE;
if(saveptr == NULL) {
*errstr =
log_error("Not enough paramaters to \"message\". Expected "
"string to display.");
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) {
@ -883,23 +429,6 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
} else if(strcmp(action, "resizeup") == 0) {
keybinding->action = KEYBINDING_RESIZE_TILE_VERTICAL;
keybinding->data.i = -10;
} else if(strcmp(action, "screen") == 0) {
keybinding->action = KEYBINDING_SWITCH_OUTPUT;
char *noutp_str = strtok_r(NULL, " ", &saveptr);
if(noutp_str == NULL) {
*errstr =
log_error("Expected argument for \"output\" action, got none.");
return -1;
}
long outp = strtol(noutp_str, NULL, 10);
if(outp < 1) {
*errstr = log_error("Workspace number must be an integer number "
"larger or equal to 1. Got %ld",
outp);
return -1;
}
keybinding->data.u = outp;
} else if(strcmp(action, "workspace") == 0) {
keybinding->action = KEYBINDING_SWITCH_WORKSPACE;
char *nws_str = strtok_r(NULL, " ", &saveptr);
@ -917,29 +446,12 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
return -1;
}
keybinding->data.u = ws - 1;
} else if(strcmp(action, "movetoscreen") == 0) {
keybinding->action = KEYBINDING_MOVE_VIEW_TO_OUTPUT;
char *noutp_str = strtok_r(NULL, " ", &saveptr);
if(noutp_str == NULL) {
*errstr = log_error(
"Expected argument for \"movetoscreen\" action, got none.");
return -1;
}
long outp = strtol(noutp_str, NULL, 10);
if(outp < 1) {
*errstr = log_error("Output number must be an integer larger or "
"equal to 1. Got %ld",
outp);
return -1;
}
keybinding->data.u = outp;
} else if(strcmp(action, "movetoworkspace") == 0) {
keybinding->action = KEYBINDING_MOVE_VIEW_TO_WORKSPACE;
char *nws_str = strtok_r(NULL, " ", &saveptr);
if(nws_str == NULL) {
*errstr = log_error(
"Expected argument for \"movetoworkspace\" action, got none.");
"Expected argument for \"workspace\" action, got none.");
return -1;
}
@ -968,11 +480,7 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
} else if(strcmp(action, "focusdown") == 0) {
keybinding->action = KEYBINDING_FOCUS_BOTTOM;
} else if(strcmp(action, "movetonextscreen") == 0) {
keybinding->action = KEYBINDING_MOVE_VIEW_TO_CYCLE_OUTPUT;
keybinding->data.b = false;
} else if(strcmp(action, "movetoprevscreen") == 0) {
keybinding->action = KEYBINDING_MOVE_VIEW_TO_CYCLE_OUTPUT;
keybinding->data.b = true;
keybinding->action = KEYBINDING_MOVE_VIEW_TO_NEXT_OUTPUT;
} else if(strcmp(action, "switchvt") == 0) {
keybinding->action = KEYBINDING_CHANGE_TTY;
char *ntty = strtok_r(NULL, " ", &saveptr);
@ -987,12 +495,13 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
keybinding->action = KEYBINDING_SWITCH_MODE;
char *mode = strtok_r(NULL, " ", &saveptr);
if(mode == NULL) {
*errstr = log_error("Expected mode after \"mode\". Got nothing.");
*errstr =
log_error("Expected mode after \"switch_mode\". Got nothing.");
return -1;
}
int mode_idx = get_mode_index_from_name(server->modes, mode);
if(mode_idx == -1) {
*errstr = log_error("Unknown mode \"%s\" for \"mode\"", mode);
*errstr = log_error("Unknown mode \"%s\" for switch_mode", mode);
return -1;
}
keybinding->data.u = (unsigned int)mode_idx;
@ -1013,15 +522,13 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
keybinding->data.u = (unsigned int)mode_idx;
} else if(strcmp(action, "bind") == 0) {
keybinding->action = KEYBINDING_DEFINEKEY;
keybinding->data.kb =
parse_bind(server, &saveptr, errstr, nesting_level);
keybinding->data.kb = parse_bind(server, &saveptr, errstr);
if(keybinding->data.kb == NULL) {
return -1;
}
} else if(strcmp(action, "definekey") == 0) {
keybinding->action = KEYBINDING_DEFINEKEY;
keybinding->data.kb =
parse_definekey(server, &saveptr, errstr, nesting_level);
keybinding->data.kb = parse_definekey(server, &saveptr, errstr);
if(keybinding->data.kb == NULL) {
return -1;
}
@ -1037,12 +544,6 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
if(keybinding->data.kb == NULL) {
return -1;
}
} else if(strcmp(action, "cursor") == 0) {
keybinding->action = KEYBINDING_CURSOR;
keybinding->data.i = parse_cursor(&saveptr, errstr);
if(keybinding->data.i < 0) {
return -1;
}
} else if(strcmp(action, "definemode") == 0) {
keybinding->action = KEYBINDING_DEFINEMODE;
keybinding->data.c = parse_definemode(&saveptr, errstr);
@ -1061,18 +562,6 @@ parse_command(struct cg_server *server, struct keybinding *keybinding,
if(keybinding->data.o_cfg == NULL) {
return -1;
}
} else if(strcmp(action, "input") == 0) {
keybinding->action = KEYBINDING_CONFIGURE_INPUT;
keybinding->data.i_cfg = parse_input_config(&saveptr, errstr);
if(keybinding->data.i_cfg == NULL) {
return -1;
}
} else if(strcmp(action, "configure_message") == 0) {
keybinding->action = KEYBINDING_CONFIGURE_MESSAGE;
keybinding->data.m_cfg = parse_message_config(&saveptr, errstr);
if(keybinding->data.m_cfg == NULL) {
return -1;
}
} else {
*errstr = log_error("Error, unsupported action \"%s\".", action);
return -1;
@ -1092,7 +581,7 @@ parse_rc_line(struct cg_server *server, char *line, char **errstr) {
free(saveptr);
return -1;
}
if(parse_command(server, keybinding, saveptr, errstr, 1) != 0) {
if(parse_command(server, keybinding, saveptr, errstr) != 0) {
wlr_log(WLR_ERROR, "Error parsing command.");
free(keybinding);
free(saveptr);

View file

@ -1,19 +1,12 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef PARSE_H
#define PARSE_H
#include <stdio.h>
#define MAX_LINE_SIZE 256
struct cg_server;
int
parse_rc_line(struct cg_server *server, char *line, char **errstr);
char *
parse_malloc_vsprintf(const char *fmt, ...);
char *
parse_malloc_vsprintf_va_list(const char *fmt, va_list list);
#endif /* end of include guard PARSE_H */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

277
render.c Normal file
View file

@ -0,0 +1,277 @@
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2020 The Cagebreak Authors
* Copyright (C) 2018-2020 Jente Hidskes
* Copyright (C) 2019 The Sway authors
*
* See the LICENSE file accompanying this file.
*/
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h>
#include <wlr/util/region.h>
#include "message.h"
#include "output.h"
#include "seat.h"
#include "server.h"
#include "util.h"
#include "view.h"
#include "workspace.h"
static void
scissor_output(struct wlr_output *output, pixman_box32_t *rect) {
struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend);
struct wlr_box box = {
.x = rect->x1,
.y = rect->y1,
.width = rect->x2 - rect->x1,
.height = rect->y2 - rect->y1,
};
int output_width, output_height;
wlr_output_transformed_resolution(output, &output_width, &output_height);
enum wl_output_transform transform =
wlr_output_transform_invert(output->transform);
wlr_box_transform(&box, &box, transform, output_width, output_height);
wlr_renderer_scissor(renderer, &box);
}
struct render_data {
pixman_region32_t *damage;
int tile_width, tile_height;
};
static void
render_texture(struct wlr_output *wlr_output, pixman_region32_t *output_damage,
struct wlr_texture *texture, const struct wlr_box *box,
const float matrix[static 9]) {
struct wlr_renderer *renderer =
wlr_backend_get_renderer(wlr_output->backend);
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_union_rect(&damage, &damage, box->x, box->y, box->width,
box->height);
pixman_region32_intersect(&damage, &damage, output_damage);
if(!pixman_region32_not_empty(&damage)) {
goto damage_finish;
}
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for(int i = 0; i < nrects; i++) {
scissor_output(wlr_output, &rects[i]);
wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0F);
}
damage_finish:
pixman_region32_fini(&damage);
}
static void
render_surface_iterator(struct cg_output *output, struct wlr_surface *surface,
struct wlr_box *box, void *user_data) {
struct render_data *data = user_data;
struct wlr_output *wlr_output = output->wlr_output;
pixman_region32_t *output_damage = data->damage;
struct wlr_texture *texture = wlr_surface_get_texture(surface);
if(!texture) {
wlr_log(WLR_DEBUG, "Cannot obtain surface texture");
return;
}
scale_box(box, wlr_output->scale);
float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current.transform);
wlr_matrix_project_box(matrix, box, transform, 0.0F,
wlr_output->transform_matrix);
if(data->tile_width != 0) {
box->width =
box->width > data->tile_width ? data->tile_width : box->width;
}
if(data->tile_height != 0) {
box->height =
box->height > data->tile_height ? data->tile_height : box->height;
}
render_texture(wlr_output, output_damage, texture, box, matrix);
}
static void
render_drag_icons(struct cg_output *output, pixman_region32_t *damage,
struct wl_list *drag_icons) {
struct render_data data = {
.damage = damage,
.tile_width = 0,
.tile_height = 0,
};
output_drag_icons_for_each_surface(output, drag_icons,
render_surface_iterator, &data);
}
/**
* Render all toplevels without descending into popups.
*/
static void
render_view_toplevels(struct cg_view *view, struct cg_output *output,
pixman_region32_t *damage) {
struct render_data data = {
.damage = damage,
.tile_width = 0,
.tile_height = 0,
};
struct cg_tile *view_tile = view_get_tile(view);
if(view_tile != NULL) {
if(view_tile->tile.width != view->wlr_surface->current.width ||
view_tile->tile.height != view->wlr_surface->current.height) {
view_damage_whole(view);
}
data.tile_width = view_tile->tile.width;
data.tile_height = view_tile->tile.height;
}
double ox, oy;
ox = view->ox;
oy = view->oy;
output_surface_for_each_surface(output, view->wlr_surface, ox, oy,
render_surface_iterator, &data);
}
static void
render_popup_iterator(struct cg_output *output, struct wlr_surface *surface,
struct wlr_box *box, void *data) {
/* Render this popup's surface. */
render_surface_iterator(output, surface, box, data);
/* Render this popup's child toplevels. */
output_surface_for_each_surface(output, surface, box->x, box->y,
render_surface_iterator, data);
}
static void
render_view_popups(struct cg_view *view, struct cg_output *output,
pixman_region32_t *damage) {
struct render_data data = {
.damage = damage,
.tile_width = 0,
.tile_height = 0,
};
output_view_for_each_popup(output, view, render_popup_iterator, &data);
}
void
output_render(struct cg_output *output, pixman_region32_t *damage) {
struct cg_server *server = output->server;
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_renderer *renderer =
wlr_backend_get_renderer(wlr_output->backend);
if(!renderer) {
wlr_log(WLR_DEBUG, "Expected the output backend to have a renderer");
return;
}
wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
if(!pixman_region32_not_empty(damage)) {
wlr_log(WLR_DEBUG, "Output isn't damaged but needs a buffer swap");
goto renderer_end;
}
#ifdef DEBUG
if(server->debug_damage_tracking) {
wlr_renderer_clear(renderer, (float[]){1.0F, 0.0F, 0.0F, 1.0F});
}
#endif
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
for(int i = 0; i < nrects; i++) {
scissor_output(wlr_output, &rects[i]);
wlr_renderer_clear(renderer, server->bg_color);
}
bool first = true;
for(struct cg_tile *tile =
output->workspaces[output->curr_workspace]->focused_tile;
first ||
tile != output->workspaces[output->curr_workspace]->focused_tile;
tile = tile->next) {
first = false;
/* Only render visible views */
if(tile->view != NULL) {
render_view_toplevels(tile->view, output, damage);
}
}
struct cg_view *view;
wl_list_for_each_reverse(
view, &output->workspaces[output->curr_workspace]->unmanaged_views,
link) {
render_view_toplevels(view, output, damage);
}
struct cg_view *focused_view = seat_get_focus(server->seat);
if(focused_view != NULL) {
render_view_popups(focused_view, output, damage);
}
struct cg_message *message;
wl_list_for_each_reverse(message, &output->messages, link) {
float matrix[9];
wlr_matrix_project_box(matrix, message->position,
WL_OUTPUT_TRANSFORM_NORMAL, 0.0F,
wlr_output->transform_matrix);
render_texture(output->wlr_output, damage, message->message,
message->position, matrix);
}
render_drag_icons(output, damage, &server->seat->drag_icons);
renderer_end:
/* Draw software cursor in case hardware cursors aren't
available. This is a no-op when they are. */
wlr_output_render_software_cursors(wlr_output, damage);
wlr_renderer_scissor(renderer, NULL);
wlr_renderer_end(renderer);
int output_width, output_height;
wlr_output_transformed_resolution(wlr_output, &output_width,
&output_height);
pixman_region32_t frame_damage;
pixman_region32_init(&frame_damage);
enum wl_output_transform transform =
wlr_output_transform_invert(wlr_output->transform);
wlr_region_transform(&frame_damage, &output->damage->current, transform,
output_width, output_height);
#ifdef DEBUG
if(server->debug_damage_tracking) {
pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0,
output_width, output_height);
}
#endif
wlr_output_set_damage(wlr_output, &frame_damage);
pixman_region32_fini(&frame_damage);
if(!wlr_output_commit(wlr_output)) {
wlr_log(WLR_ERROR, "Could not commit output");
}
}

9
render.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef CG_RENDER_H
#define CG_RENDER_H
struct cg_output;
void
output_render(struct cg_output *output, pixman_region32_t *damage);
#endif

View file

@ -1,13 +0,0 @@
#!/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

@ -1,40 +0,0 @@
#!/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

View file

@ -1,37 +0,0 @@
#!/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

View file

@ -1,17 +0,0 @@
#!/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

View file

@ -1,8 +0,0 @@
#!/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

@ -1,13 +0,0 @@
#!/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/*

View file

@ -1,50 +0,0 @@
#!/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

View file

@ -1,18 +0,0 @@
#!/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

613
seat.c

File diff suppressed because it is too large Load diff

31
seat.h
View file

@ -1,6 +1,3 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_SEAT_H
#define CG_SEAT_H
@ -10,12 +7,9 @@ struct cg_server;
struct cg_view;
struct wlr_cursor;
struct wlr_input_device;
struct cg_input_device;
struct wlr_seat;
struct wlr_xcursor_manager;
struct wlr_backend;
struct wlr_surface;
struct cg_input_config;
#define DEFAULT_XCURSOR "left_ptr"
#define XCURSOR_SIZE 24
@ -26,14 +20,11 @@ struct cg_seat {
struct wl_listener destroy;
struct wl_list keyboard_groups;
struct wl_list pointers;
struct wl_list touch;
struct wl_listener new_input;
uint16_t num_keyboards;
uint16_t num_pointers;
uint16_t num_touch;
bool enable_cursor;
struct wlr_cursor *cursor;
struct cg_tile *cursor_tile;
struct wlr_xcursor_manager *xcursor_manager;
struct wl_listener cursor_motion;
struct wl_listener cursor_motion_absolute;
@ -67,8 +58,6 @@ struct cg_seat {
struct cg_keyboard_group {
struct wlr_keyboard_group *wlr_group;
struct cg_seat *seat;
char *identifier;
int enable_keybindings;
struct wl_listener key;
struct wl_listener modifiers;
@ -81,20 +70,23 @@ struct cg_keyboard_group {
struct cg_pointer {
struct wl_list link; // seat::pointers
struct cg_seat *seat;
struct cg_input_device *device;
struct wlr_input_device *device;
struct wl_listener destroy;
};
struct cg_touch {
struct wl_list link; // seat::touch
struct cg_seat *seat;
struct cg_input_device *device;
struct wlr_input_device *device;
struct wl_listener destroy;
};
struct cg_drag_icon {
struct wl_list link; // seat::drag_icons
struct cg_seat *seat;
struct wlr_drag_icon *wlr_drag_icon;
struct wlr_scene_tree *scene_tree;
/* The drag icon has a position in layout coordinates. */
double lx, ly;
@ -110,8 +102,5 @@ struct cg_view *
seat_get_focus(const struct cg_seat *seat);
void
seat_set_focus(struct cg_seat *seat, struct cg_view *view);
void
seat_add_device(struct cg_seat *seat, struct cg_input_device *device);
void
seat_remove_device(struct cg_seat *seat, struct cg_input_device *device);
#endif

View file

@ -1,24 +1,26 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
/*
* Cagebreak: A Wayland tiling compositor.
*
* Copyright (C) 2020 The Cagebreak Authors
* Copyright (C) 2018-2019 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <string.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_output.h>
#include <wlr/util/box.h>
#include <wlr/types/wlr_box.h>
#include "input_manager.h"
#include "output.h"
#include "server.h"
#include "util.h"
void
display_terminate(struct cg_server *server) {
if(server == NULL) {
return;
}
server->running = false;
wl_display_terminate(server->wl_display);
}
@ -33,36 +35,3 @@ get_mode_index_from_name(char *const *modes, const char *mode_name) {
}
return -1;
}
char *
server_show_info(struct cg_server *server) {
char *output_str = strdup(""), *output_str_tmp;
struct cg_output *output;
wl_list_for_each(output, &server->outputs, link) {
if(!output_str) {
return NULL;
}
output_str_tmp = output_str;
output_str = malloc_vsprintf("%s\t * %s\n", output_str, output->name);
free(output_str_tmp);
}
char *input_str = strdup(""), *input_str_tmp;
struct cg_input_device *input;
wl_list_for_each(input, &server->input->devices, link) {
if(!input_str) {
free(output_str);
return NULL;
}
input_str_tmp = input_str;
if(strcmp(input->identifier, "") != 0) {
input_str =
malloc_vsprintf("%s\t * %s\n", input_str, input->identifier);
free(input_str_tmp);
}
}
char *ret =
malloc_vsprintf("Outputs:\n%sInputs:\n%s", output_str, input_str);
free(output_str);
free(input_str);
return ret;
}

View file

@ -1,12 +1,8 @@
// Copyright 2020 - 2024, project-repo and the cagebreak contributors
// SPDX-License-Identifier: MIT
#ifndef CG_SERVER_H
#define CG_SERVER_H
#include "config.h"
#include "ipc_server.h"
#include "message.h"
#include <wayland-server-core.h>
#include <wlr/types/wlr_xdg_decoration_v1.h>
@ -17,66 +13,50 @@ struct keybinding_list;
struct wlr_output_layout;
struct wlr_idle_inhibit_manager_v1;
struct cg_output_config;
struct cg_input_manager;
struct cg_server {
struct wl_display *wl_display;
struct wl_event_loop *event_loop;
struct cg_seat *seat;
struct cg_input_manager *input;
struct wlr_backend *backend;
struct wlr_idle_notifier_v1 *idle;
struct wlr_idle *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;
struct wlr_scene *scene;
struct wl_listener xdg_toplevel_decoration;
struct wl_listener new_xdg_shell_surface;
#if CG_HAS_XWAYLAND
struct wl_listener new_xwayland_surface;
struct wlr_xwayland *xwayland;
#endif
struct keybinding_list *keybindings;
struct wl_list output_config;
struct wl_list input_config;
struct cg_message_config message_config;
enum wl_output_transform output_transform;
struct cg_ipc_handle ipc;
bool enable_socket;
bool bs;
bool running;
char **modes;
uint16_t nws;
uint16_t message_timeout;
float *bg_color;
uint32_t views_curr_id;
uint32_t tiles_curr_id;
uint32_t xcursor_size;
#ifdef DEBUG
bool debug_damage_tracking;
#endif
};
void
display_terminate(struct cg_server *server);
int
get_mode_index_from_name(char *const *modes, const char *mode_name);
char *
server_show_info(struct cg_server *server);
#endif

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