Followup on 4e4898e90f.
If a view quickly maps and unmaps repeatedly, there will be multiple
destroyed containers with same view in a single transaction. Each of
these containers will then try to destroy this view, resulting in use
after free.
The container should only destroy the view if the view still belongs
to the container.
Simple reproducer: couple XMapWindow + XUnmapWindow in a loop followed
by XDestroyWindow.
See #6605
cairo_image_surface_create can fail, e.g. when running out of
memory or when the size is too big. Avoid crashing in this case.
Closes: https://github.com/swaywm/sway/issues/6531
The title itself and marks were being rendered by two very-similar yet
different functions, and any changes made to one had to be reflected on
the other.
This mostly prevents such oversights from happening, and keeps makes
sure we keep both consistent.
Use fixed titlebar heights. The default height is calculated based on
font metrics for the configured font and current locale.
Some testing with titles with emoji and CJK characters (which are
substantially higher in my setup) shows that the titlebars retain their
initial value, text does shift up or down, and all titlebars always
remain aligned.
Also drop some also now-unecessary title_height calculations.
Makes also needed to be updated, since they should be positioned with
the same rules.
The xdg-decoration protocol allows clients to request whether they want
to use server side decorations or client side decorations. Currently,
sway ignores this and always enforces whatever the server is currently
set to. Although tiled clients cannot be allowed to set borders, there
is no harm in listening requests from floating clients. Sidenote: also
fix an unrelated style error.
When setting the geometry from content for floating windows, the
coordinates for borders are normally taken into account. However in the
case of a floating fullscreen window, we should not be doing this. Since
the content of the container takes the space of the entire output, this
causes the calculated borders to neccesarily be outside of the output.
This later causes a problem when sending surface entrance events since
in a multi-monitor setup, the border coordinates will overlap with
another output despite the surface not actually being on that output at
all. The fix is to just ignore border coordinates for a floating
fullscreen container since fullscreen, of course, does not actually have
any borders. Fixes#6080.
the original behavior set fullscreen for all descendents of a container,
which causes issues when firefox is one of those children because it
sends its own set_fullscreen request in response to being fullscreened.
When a tiling container is floated, the focus stack needs to be
appropraitely modified to return the container to its original
position in the tree upon floating disable, like i3.
container_at checks if the position provided matches the currently
focused container with view_container_at as a fast path.
view_container_at checks using the main container geometry, which
includes the titlebar and border area. If a tabbed container is focused,
then positions over unfocused tabs are incorrectly reported as belonging
to the focused container, breaking focus on click.
Add view_container_content_at for use in the focused container fast path
which only tests container content area, and fall back to full workspace
scans for border and titlebar areas.
Closes: https://github.com/swaywm/sway/issues/6074
container_at would maintain the current focus as long as a position was
over one of the container view's surfaces. If an oversized surface was
being clipped, this lead to weird focus behavior.
Instead, use view_container_at for this test, which intersects the
container box before looking at surfaces.
When issuing a focus command on a specific container, users expect to
proceed it even if is hidden by a fullscreen window.
This matches the behavior of i3.
Pending state is currently inlined directly in the container struct,
while the current state is in a state struct. A side-effect of this is
that it is not immediately obvious that pending double-buffered state is
accessed, nor is it obvious what state is double-buffered.
Instead, use the state struct for both current and pending.
workspace_squash is container_flatten in the reverse
direction. Instead of eliminating redundant splits that are
parents of the target container, it eliminates pairs of
redundant H/V splits that are children of the workspace.
Splits are redundant if a con and its grandchild have the
same layout, and the immediate child has the opposite split.
For example, layouts are transformed like:
H[V[H[app1 app2]] app3] -> H[app1 app2 app3]
i3 uses this operation to simplify the tree after moving
heavily nested containers to a higher level in the tree via
an orthogonal move.
In i3, the workspace_layout command does not affect the
workspace layout. Instead, new workspace level containers
are wrapped in the desired layout and the workspace layout
always defaults to the output orientation.
To query whether a container is sticky, checking `con->is_sticky` is
insufficient. `container_is_floating_or_child` must also return true;
this led to a lot of repetition.
This commit introduces `container_is_sticky[_or_child]` functions, and
switches all stickiness checks to use them. (Including ones where the
container is already known to be floating, for consistency.)
Currently, when a floating container with a view is split and
children are added to it, the new views are rendered as tiled,
while the first view stays in floating style.
Here this is addressed by setting the view to tiled as soon
as the container is split, by duplicating the "view part" of
the logic in container_set_floating(..., false). Since the new
container of the view is no longer considered floating, it
makes sense to set the view to tiling at this point.
The view would have to be set back to floating if it was possible
to "unsplit" the container.
This fixes bugs where a floating container would take input way past its
borders when its parent was fullscreen, since the call to
`tiling_container_at` in input/cursor.c's `node_at_coords` did not check
bounds.