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.
Layer shell clients may leave the output on which to display a layer
surface up to the compositor. Instead of always putting such surfaces
on the first output use the focused output of the default seat.
This command takes a mode, modifiers, button/event name, and pointer
action as arguments. It stores these in the config data structure.
The currently available pointer actions are move-view and resize-view,
which replace the previously hard-coded functionality.
Closing the hovered view with middle click has temorarily been removed
until it is decided if we wish to make this another special pointer
action or perhaps allow running any arbitrary command (which would of
course include close).
There is now a single iter() function which accepts a filter and context
allowing users of the api to filter the views in any arbitrary way. This
change allowed for a good amount of code cleanup, and this commit also
ensures that the correct properties are checked in each case, including
the new View.destroying field added in the previous commit. This fixes
at least one crash involving switching focus to a destroying view.
Focus was made double-buffered in 96a91fd. However, much of the code
still behaved as if focus was separate from the transaction system.
This commit completes the work started in 96a91fd and ensures that
focus is applied consistently in a single transaction.
- require the caller to use Root.startTransaction() directly
- introduce View.applyPending() to unify logic
- introduce View.shouldTrackConfigure() to unify more logic
- update all callsites to intelligently rearrange only what is necessary
When a button is held down and the cursor leaves a surface, events now
continue to be sent to the client. This allows e.g. dragging a scroll
bar from outside the surface.
- Double buffering focus state ensures that border color is kept in sync
with the transaction state of views in the layout.
- Using a counter instead of a bool will allow for proper handling of
multiple seats. This is done in the same commit to avoid more churn in
the future.
We don't rearrange the layout on fullscreening a view that is part of
the layout since the fullscreened view hides the layout. This means that
if a non-floating fullscreen view is closed the layout needs to be
rearranged.
When a floating view is returned to the layout or made fullscreen, it
now saves the dimesions it had while floating and returns to that same
position/size if made to float again.
Transactions are only useful when multiple views need to atomically
change size together. Float/fullscreen views are independant of the
layout and should bypass the transaction system.