Currently we hit a stack overflow as we do not check if the target view
already has keyboard focus before calling Seat.focus() in
Cursor.passthrough(). To fix this, simply add this check.
When an xdg toplevel, layer surface, etc is destroyed, it is not
guaranteed that all the children in the surface tree have already been
destroyed. If there are still children around, destroying the root of
the tree would leave dangling pointers.
To fix this, destroy all children when destroying any node in the tree.
The current format of #RRGGBBAA is problematic as # starts a comment
in POSIX compliant shells, requiring escaping/quoting and increasing
complexity.
This is a breaking change.
This arrange is actually required because the post_fullscreen box might
not hold the correct dimensions if the view was made fullscreen while
a transaction was already in progress.
Currently if a view is moved from layout to fullscreen while a
transaction involving that view is in progress the saved buffers are not
dropped, which causes stale state to be rendered.
This is guaranteed to already be set to the layout being committed. It
is set either when a client binds a new layout object or when the user
changes the layout namespace in use.
This is currently unused and I don't like the approach anymore
regardless. If/when we need positional arguments (probably when
implementing the upcoming river-control protocol in rivertile)
they should be handled separately from flags.
This commit also improves the CLI error reporting to always print the
usage string if invalid arguments were passed.
The previous commit re-introduced a bug fixed by a3c65713 which caused
the pointer enter event not to be sent until moving the pointer when
switching tag focus or otherwise manipulating the window manager caused
the cursor to end up over a new surface.
If the current Cursor.maybeResetState() function is called while in
passthrough mode, it will send a pointer motion event. This is
unnecessary as we have already sent the same pointer motion event at
least once.
Also refactor the code slightly and improve naming.
Handling output destroy now requires the wlr_output_layout to still be
around, as we need it to properly handle cursor state. In order to make
sure that all outputs are destroyed before the wlr_output_layout is,
simply destroy the backend before calling Root.deinit().
Now that we properly handle state changes during cursor operations,
blocking these commands if the target view is the target of a cursor
operation is unnecessary complexity. It is also inconsistent as we
don't block changing the tags of the view.
This was slightly out of sync with Cursor.surfaceAt() which did not
fullscreen or xwayland unmanaged views properly. Also simplify things
and improve correctness by always rendering all xdg popups. A view
losing focus does not always mean that all popups will be destroyed.
A transaction may move the current target of a cursor action to a
non-visible tag, make it fullscreen, or otherwise change things such
that the current cursor state no longer makes sense.
To handle this, check if we should reset cursor state every time a
transaction is committed.
Currently the spawn command takes any number of arguments and naively
joins them together with spaces before passing them as the single
argument of `/bin/sh -c`. This however produces unexpected results as
soon as shell quoting gets involved in the arguments passed to spawn.
For example, running
riverctl spawn foo "bar baz"
will execute `/bin/sh -c "foo bar baz"`, unexpectedly splitting bar and
baz into separate arguments. To avoid this confusion, make the spawn
command take only a single argument, forcing the user to quote properly
to spawn multi-argument commands.
- Remove advertise_view and advertise_done events. Using the information
provided by these for any purpose would make the layout far less
predictable. Futhermore, in the months this has been available for use,
to my knowledge nobody has actually used it for anything useful.
- Replace the set/mod layout value events with a single user_command
event. This simplifies the protocol and is more flexible for clients.
- Add a layout_name argument to the commit request. This name is an
arbitrary, user-facing string that might, for example, be displayed by a
status bar. This was present in early drafts of the protocol, but was
removed in favor of river-options. Since river-options itself has since
been removed and this feature is nice to have, re-add it.
- Rename main factor to main ratio in rivertile. The "factor" name was
just legacy from dwm, "ratio" is much more accurate.
This code is complex and increases maintenance burden but doesn't
add any functionality, only eye-candy.
Futhermore, neither I nor any of the core contributors use it.
There may be a place in river for such eye-candy down the line, in which
case this code could be revived. Currently river is early enough in its
development that our focus should be on core functionality instead.
A true "default" config doesn't make sense for river. Everyone who uses
river seriously will customize their init script. Futhermore, the
current behavior of embedding the install path of the default system
config in the river binary is complex and prone to breaking.
On output change, if the cursor is not already on the newly focused
output, it will now be warped to its center. The check is necessary,
since focusing outputs with the pointer will be implemented in
the future.
A client is free to change its mind and request a different
size/anchor/etc after recieving the initial configure but before
attaching and committing the first buffer. This means that we should
respond to such a situation with a new configure.
mako has been observed doing this in the wild for example.
Currently in handleUnmap() we call View.unmap() before removing
listeners. However View.unmap() may destroy the view before returning
if the transaction started doesn't have to wait on any configures.
To ensure that we don't try to remove listeners which have already been
free'd, do this before calling View.unmap().
The Layout struct holds a pointer to the Output which becomes invalid
when the Output is destroyed so we must ensure all the layouts of an
Output are destroyed first.
The transaction system exists to coordinate size changes of all views
in a layout in order to achieve frame perfection. Since many clients
do not need to commit a new buffer in response to a activated state
change alone, this breaks things when such a configure event is tracked
by the transaction system. Instead, simply send activated and fullscreen
configures right away but still track this state in a double-buffered
way so that e.g. border color changes based on focus are frame-perfect.
This also fixes a related issue with the transaction system where views
that did not need to commit in response to our first configure were not
rendered until their next frame.
This protocol involves far too much accidental complexity. The original
motivating use-case was to provide a convenient way to send arbitrary
data to layout clients at runtime in order to avoid layout clients
needing to implement their own IPC and do this over a side-channel.
Instead of implementing a quite complex but still rigid options protocol
and storing this state in the compositor, instead we will simply add
events to the layout protocol to support this use case.
Consider the status quo event sequence:
1. send get_option_handle request (riverctl)
2. roundtrip waiting for first event (riverctl)
3. send set_foo_value request (riverctl)
4. receive set_foo_value request (river)
5. send foo_value event to all current handles (river)
6. receive foo_value event (rivertile)
7. send parameters_changed request (rivertile)
8. receive parameters_changed request (river)
9. send layout_demand (river)
And compare with the event sequence after the proposed change:
1. send set_foo_value request (riverctl)
2. receive set_foo_value request (river)
3. send set_foo_value event (river)
4. send layout_demand (river)
This requires *much* less back and forth between the server and clients
and is clearly much simpler.
Options are now all global but may be overridden per-output. If an
output local value is requested but none has been set, the global value
is provided instead. This makes for much better ergonomics when
configuring layout related options in particular.
Run the init command in a new process group and send SIGTERM to the
entire group on exit. Without doing this, only the sh invocation used
for the `sh -c` would receive SIGTERM.
This is particularly useful when starting a per-session server manager
as the init command.
Replace the current layout mechanism based on passing args to a child
process and parsing it's stdout with a new wayland protocol. This much
more robust and allows for more featureful layout generators.
Co-authored-by: Isaac Freund <ifreund@ifreund.xyz>
This reverts commit c457b12cf3.
This attempted workaround seems to work fine if the output commit only
fails with EBUSY, but enters an infinite loop otherwise.
It kinda shows that this was the first protocol I ever implemented
server-side:
- Use client as well as ID for keys in the hashmap as IDs might
(and will) be the same between clients.
- Clear saved args after running a command.
This change is made in the interest of allowing users to simply re-run
their init script at runtime without errors. Making this an error
doesn't really gain us anything.
The ergonomics of remapping keys are currently quite bad as unmap
must first be called for every mapping before defining a new one.
Any benefit that might be gained by the current strictness of map/
map-pointer is outweighed by this fact.
In a similar spirit, silently ignore unmapping a non-existent mapping.
This is important to use instead of direct access as clients are not
strictly required to set a geometry, in which caese the dimensions
of the wl_surface are used instead.
Outputs now have a default option, "output_title". If this changes, the
outputs title is set to the option value. This title is currently only
relevant when run nested in a wayland/X11 session.
Co-authored-by: Isaac Freund <ifreund@ifreund.xyz>
This is done when river's internal Output struct is destroyed, not when
the advertised wl_output global is removed. This means that options will
persist when an output is disabled and re-enabled.
main is a better term to use here for several reasons:
1. It is more accurate: "master" implies that the designated views have
some kind of control over the other views, which is not the case. "main"
better expresses that the difference between the "main" view and others
is one of importance/focus.
2. It is a shorter word. 2 whole characters saved!
3. It reduces the chance of future development time being lost to
good-intentioned people complaining about usage of the word master as
has recently happened with regards to the default git branch name.
Recover more gracefully from being hotplugged down to 0 outputs and then
gaining a new one. Move all views to the new output and restore the
focused output tags of the last output to be removed.
Currently screencopy's copy_with_damage request is broken for
compositors not submitting damage. As a workaround simply damage
the whole output each frame.