Add a subcommand for `smart_gaps` that enables outer gaps only
on workspaces with exactly one visible child.
Also add documentation for `smart_gaps toggle`.
If the focused container is floating by itself, create a new container
in tiling mode as a sibling of the inactive focused container instead of
creating it as a sibling of everything that is in tiling mode in that
workspace. This is the i3 behavior.
Prior to 62d90a8e, titlebar's font height (and other related values)
would change any time any titlebar's content changed, so these values
were recalculated each time any titlebar's content changed (or a new
titlebar was created).
However, since the above was merge, these values no longer change so
often and we only need to recalculate them when the configured font
changes (and stop calling `config_update_font_height` each time
titlebars are rendered).
This commit removes all the unecessary calls to this function and avoids
all those unecessary calculations. Whenever the font strays from the
default value, the `font` command is called, and it calls
`config_update_font_height`, which is enough to keep the value always up
to date.
I've also added a default value to the `font_baseline` config, since
otherwise that's zero for setups that don't explicitly specify a font.
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.
This fixes the following scenario:
- Place a floating window so its border is right at the edge of the
screen
- Create a new split
- The border disappears
- Moving the window does not restore the border
Instead of disabling it for some workspace subcommands, this explicitly
calls it only in the 2 places it's actually needed: for switching to a
named or numbered workspace.
This extracts the code to a separate workspace_auto_back_and_forth
function.
It also removes the bool argument by adding an extra if statement at the call
site, and repurposes the no_auto_back_and_forth variable to
auto_back_and_forth for simpler understanding.
remove view from its own unmap event listener so when subsurfaces
link try to remove themselves they won't run into it.
This fixes the following ASAN use-after-free error on a build slightly
modified to instrument wl_list operations:
==71705==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000829a0 at pc 0x000000508eb7 bp 0x7ffec8fd8030 sp 0x7ffec8fd8028
WRITE of size 8 at 0x6160000829a0 thread T0
#0 0x508eb6 in wl_list_remove ../common/list.c:181
#1 0x4f4998 in view_child_destroy ../sway/tree/view.c:1131
#2 0x4f38fa in subsurface_handle_destroy ../sway/tree/view.c:946
#3 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29
#4 0x7fda5072f0dd in subsurface_destroy ../types/wlr_surface.c:649
#5 0x7fda507312c4 in subsurface_handle_surface_destroy ../types/wlr_surface.c:1094
#6 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29
#7 0x7fda5072f305 in surface_handle_resource_destroy ../types/wlr_surface.c:677
#8 0x7fda508180ce in destroy_resource (/lib64/libwayland-server.so.0+0xc0ce)
#9 0x7fda508187f2 in wl_client_destroy (/lib64/libwayland-server.so.0+0xc7f2)
#10 0x7fda50818e5f in wl_client_connection_data (/lib64/libwayland-server.so.0+0xce5f)
#11 0x7fda50818219 in wl_event_loop_dispatch (/lib64/libwayland-server.so.0+0xc219)
#12 0x7fda50818984 in wl_display_run (/lib64/libwayland-server.so.0+0xc984)
#13 0x43122c in server_run ../sway/server.c:254
#14 0x42f47c in main ../sway/main.c:433
#15 0x7fda503cab74 in __libc_start_main (/lib64/libc.so.6+0x27b74)
#16 0x40f6fd in _start (/opt/wayland/bin/sway+0x40f6fd)
0x6160000829a0 is located 288 bytes inside of 592-byte region [0x616000082880,0x616000082ad0)
freed by thread T0 here:
#0 0x7fda50f01a27 in free (/lib64/libasan.so.6+0xaea27)
#1 0x4532d8 in destroy ../sway/desktop/xdg_shell.c:262
#2 0x4ed17b in view_destroy ../sway/tree/view.c:67
#3 0x4ed300 in view_begin_destroy ../sway/tree/view.c:83
#4 0x454a3f in handle_destroy ../sway/desktop/xdg_shell.c:507
#5 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29
#6 0x7fda506e2c87 in reset_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:481
#7 0x7fda506e3018 in destroy_xdg_surface ../types/xdg_shell/wlr_xdg_surface.c:516
#8 0x7fda506dfbe5 in xdg_client_handle_resource_destroy ../types/xdg_shell/wlr_xdg_shell.c:71
#9 0x7fda508180ce in destroy_resource (/lib64/libwayland-server.so.0+0xc0ce)
previously allocated by thread T0 here:
#0 0x7fda50f01ed7 in calloc (/lib64/libasan.so.6+0xaeed7)
#1 0x454bc8 in handle_xdg_shell_surface ../sway/desktop/xdg_shell.c:528
#2 0x7fda50744892 in wlr_signal_emit_safe ../util/signal.c:29
#3 0x7fda506e2363 in handle_xdg_surface_commit ../types/xdg_shell/wlr_xdg_surface.c:378
#4 0x7fda5072e368 in surface_commit_state ../types/wlr_surface.c:455
#5 0x7fda5072e51d in surface_commit_pending ../types/wlr_surface.c:474
#6 0x7fda5072ea58 in surface_commit ../types/wlr_surface.c:542
#7 0x7fda4fb3ac03 in ffi_call_unix64 (/lib64/libffi.so.6+0x6c03)
Fixes#5168
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.
view_child_init was calling view_init_subsurfaces, which did not set the
parent attribute for the subchildren. This lead to the subchildren
acting as standalone children. If the parent was an xdg_popup, this
would make the subchild unaware of the popup position.
Introduce view_child_init_subsurfaces for view_child_init to use
instead.
Closes: https://github.com/swaywm/sway/issues/6038
The subchildren lose their parent association at this point, so they
will not be able to see that the parent is unmapped.
Instead, just set the subchildren to be unmapped directly.
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.
The size of a tiled container cannot change in response to new buffer
sizes, so there is no need to commit a new transaction. Instead, simply
recenter the view with the new geometry, leaving the full transaction
flow for floating containers.
We need to use surface_x and surface_y when rendering and damaging saved
buffers as these compensate for views that have been centered due to
being smaller than their container.
Add them to the surface positions on the saved buffer so we have the
values from the time the buffer was saved.
Sway records pid, workspace, and output for every new process. However, if the
output gets disabled and the workspace disappears, the workspace is still
re-created on the disabled output. This commit adds a check for the enabled
flag, so that NULL will be passed to workspace_create() in this case.
For certain applications (e.g. JetBrains) the parent window controls
input. We need to adhere to the ICCCM input focus specification to
properly handle these cases.
Relates to swaywm/wlroots#2604
Instead of calling wlr_xdg_surface_for_each_popup and then
wlr_surface_for_each_surface, use the new for_each_popup_surface helper
introduced in [1] that does it in one go.
[1]: https://github.com/swaywm/wlroots/pull/2609
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.)
The function evacuate_sticky() was changed in commit 32788a93 to be used
by workspace_for_each_container() to make the code more readable. But I
overlooked that it is not safe to use workspace_for_each_container() to
remove container from a workspace. This commit restores the previous
implementation for evacuate_sticky().
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.
Sticky floating containers on an otherwise empty workspace can only be
evacuated if the new output has an active workspace. The noop output may
not have one and in that case we have to move the whole workspace to the
new output.
Currently, in view_autoconfigure, the only condition for show_border
is !view_is_only_visible. view_is_only_visible does not cross the
boundary between the workspace's tiling and floating lists and does not
differentiate between them.
The result is, that in a workspace with zero or more tiling containers
and a single floating container, the floating container will lose its
borders as soon as it is split, provided that a only one view is visible
within the floating container.
Fixed by adjusting the condition for show_borders.
Previously, we called output_disable prior to wlr_output_commit. This
mutates Sway's output state before the output commit actually succeeds.
This results in Sway's state getting out-of-sync with wlroots'.
An alternative fix [1] was to revert the changes made by output_disable
in case of failure. This is a little complicated. Instead, this patch
makes it so Sway's internal state is never changed before a successful
wlr_output commit.
We had two output flags: enabled and configured. However enabled was set
prior to the output becoming enabled, and was used to prevent the output
event handlers (specifically, the mode handler) from calling
apply_output_config again (infinite loop).
Rename enabled to enabling and use it exclusively for this purpose.
Rename configure to enabled, because that's what it really means.
[1]: https://github.com/swaywm/sway/pull/5521
Closes: https://github.com/swaywm/sway/issues/5483
xdg-shell doesn't allow clients to set the title to NULL, so we
shouldn't need to call wlr_foreign_toplevel_handle_v1_set_title with an
empty string to reset the old one.
Closes: https://github.com/swaywm/sway/issues/5488
If moving e.g. `T[app app]` into a new workspace with `workspace_layout
tabbed`, then post-move the tree in that workspace will be `T[T[app
app]]`. This still happens with horizontal or vertical workspace layout,
but is less visible since those containers have no decorations.
Fixes#5426.
It is not a part of the foreign-toplevel-management protocol to get the
class of a toplevel, only for getting the app_id.
For xwayland clients this is an issue because that means that you cannot
identify what application the toplevel refers to which is the point of
the app_id property.
By falling back to class when an app_id does not exist solves this problem.
Phoc also uses app_id and class interchangeably in their implementation
of foreign-toplevel-management, in fact they always do that and not only
for just this protocol.
c8d8a4c544/src/xwayland.c (L236)
During the execution of a resize transaction, the buffer associated
with a view's surface is saved and reused until the client acknowledges
the resulting configure event.
However, only one the main buffer of the main surface was stored and
rendered, meaning that subsurfaces disappear during resize.
Iterate over all, store and render buffers from all surfaces in the view
to ensure that correct rendering is preserved.
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.
Add a separate per-view shortcuts_inhibitor command that can be used
with criteria to override the per-seat defaults. This allows to e.g.
disable shortcuts inhibiting globally but enable it for specific,
known-good virtualization and remote desktop software or, alternatively,
to blacklist that one slightly broken piece of software that just
doesn't seem to get it right but insists on trying.
Add a flag to sway_view and handling logic in the input manager that
respects that flag if configured but falls back to per-seat config
otherwise. Add the actual command but with just enable and disable
subcommands since there's no value in duplicating the per-seat
activate/deactivate/toggle logic here. Split the inhibitor retrieval
helper in two so we can use the backend half in the command to retrieve
inhibitors for a specific surface and not just the currently focused
one. Extend the manual page with documentation of the command and
references to its per-seat sibling and usefulness with criteria.
Signed-off-by: Michael Weiser <michael.weiser@gmx.de>
See issue #5228. Currently, WL_OUTPUT_SUBPIXEL_NONE is ignored and
CAIRO_ANTIALIAS_SUBPIXEL is still set. This commit checks if subpixel is
set to none and if so, calls set_antialias with CAIRO_ANTIALIAS_GRAY.
This mirrors the functionality in Mako's
[PR261](https://github.com/emersion/mako/pull/261)
In the case of multiple overlapping floating windows, this commit fixes an issue where the wrong window would be focused in response to a cursor if one of the windows came from a different output (overhanging).
If a subsurface is created for a surface that is associated with a
scratchpad hidden view, do not attempt to send an enter to it. The
subsurface is not on any output and since there is no workspace
associated with the view, attempting to get the output for the NULL
workspace will result in a SIGSEGV.
The output manager config is created when the output is created. It is
updated when the mode, transform, scale, or layout for the output
changes, as well as, when the output is destroyed.
Since the output->enabled property was not being set before calling
apply_output_config, the output event handlers were early returning and
never updating the output manager config when the output state was
committed.
This fixes the issue by setting output->enabled in apply_output_config
below the output disabling section. There are also a few other minor
changes that are required to function.
Additionally, this renames output_enable to output_configure to better
describe the recent changes.
The only output_enable caller is now apply_output_config. Stop calling
apply_output_config from output_enable to simplify the code and avoid
the back-and-forth between these two functions.
output_enable is now the symmetric of output_disable: it just marks the
output as enabled and performs bookkeeping (e.g. creating teh default
workspace). It is called from apply_output_config after the output
commit, so that it can read the current output state and act
accordingly.
This change also allows us to avoid an extraneous wlr_output_commit.
References: https://github.com/swaywm/sway/issues/4921
The container_at_tabbed and container_at_stacked container were checking
the bounds along the y-axis, but not the x-axis. This made it possible
to cause a segfault for specific resolution, horizontal gap, and
workspace children lengths. The issue is that child_index was -1 and was
resulting in a buffer underflow. Adding the x-axis bound checks for
early returns should prevent this from happening.
When a container was being made fullscreen and it is on the focused
workspace for a seat, focus was being set to the container. However,
when the container was on a non-focused workspace, the focus stack
wasn't being touched. When assigning a fullscreen container to a
workspace or moving a fullscreen container to a different workspace,
this would make it so the fullscreen container was never added to the
focus stack for the workspace thus preventing access to the workspace.
This adds the container to the top of the focus stack, behind the
container on the focused workspace.
If a view is mapped to a workspace using an assign, the pid should still
be removed from the pid mapping list. This prevents child processes from
matching against it and mapping a view to a likely undesired workspace.
When gaps are resized for lack of space the calculation could result in
a gap size of non-integer pixels. This would result in containers
located at non-integer pixels which would be subtly broken.
Because the layout code rounds down the dimensions of the windows
resizing would often be off by one pixel. The width/height fraction
would not exactly reflect the final computed width and so the resize
code would end up calculating things wrong.
To fix this first snap the container size fractions to the pixel grid
and only then do the resize. Also use round() instead of floor() during
layout to avoid a slightly too small width. This applies in two cases:
1. For the container we are actually resizing using floor() might result
in being 1px too small.
2. For the other containers it might result in resizing them down by 1px
and then if the container being resized is the last all those extra
pixels would make the resize too large.
Fixes#4391