This makes the behavior of floating containers more consistent with i3.
The coordinates of the container are scaled when the size of the
workspace it is on changes or when the container is moved
between workspaces on different outputs.
For scratchpad containers, add a new state that preserves the dimensions
of the last output the window appeared on. This is necessary because
after a container is hidden in the scratchpad, we expect it to be in the
same relative position on the output when it reappears. We can't just
use the container's attached workspace because that workspace's
dimensions might have been changed or the workspace as a whole could
have been destroyed.
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.
This changes the move command to better match i3
behavior after the layout changes.
workspace_rejigger handled the case where containers would
escape their workspace in an orthogonal move by changing
the layout to accomodate them, but this case is now handled
within the loop.
Some comparisons of current Sway versus i3 behavior:
1) T[T[T[app]]] + move left
* Sway: T[app]
* i3: T[T[app]]
2) H[V[H[V[app]]]] + move left
* Sway: H[app]
* i3: H[V[app]]
After this commit, Sway behavior matches i3. The intermediate states
are now:
T[T[T[app]]] -> T[T[app T[]]] -> T[T[app]]
H[V[H[V[app]]]] -> H[V[app H[V[]]]] -> H[V[app]]
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.)
Prior to this commit, having a layout like T[app1 V[app2]], focusing
app2, and then doing `move left` would result in T[app2 app1]. Now, the
resulting layout is T[app1 app2], which matches i3 behavior.
`container_flatten` updates `container->parent`, meaning that the
existing check would never be true.
If the mouse/cursor/pointer is near the edge of an output when a "move
position to pointer" command is run, then the floating container will be
constrained to fit inside the bounds of the output as much as possible.
This behavior matches what i3 does in this scenario. I also think it is
a better user experience.
Relates to #4906
The logic for the bounds check follows the implementation in i3: 7330778223/src/floating.c (L536)
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.
When moving to a scratchpad hidden container (using `move
[window|container] [to] mark <mark>`), this moves the container to the
scratchpad (equivalent to `move [window|container] [to] scratchpad`).
Previously, this would crash since the destination did not have a
workspace.
Instead of tracking gaps per child apply gaps in two logical places:
1. In tiled containers use the layout code to add the gaps between
windows. This is much simpler and guarantees that the sizing of children
is correct.
2. In the workspace itself apply all the gaps around the edge. Here
we're in the correct position to size inner and outer gaps correctly and
decide on smart gaps in a single location.
Fixes#4296
Instead of using container->width/height as both the input and output
of the layout calculation have container->width_fraction/height_fraction
as the share of the parent this container occupies and calculate the
layout based on that. That way the container arrangement can always be
recalculated even if width/height have been altered by things like
fullscreen.
To do this several parts are reworked:
- The vertical and horizontal arrangement code is ajusted to work with
fractions instead of directly with width/height
- The resize code is then changed to manipulate the fractions when
working on tiled containers.
- Finally the places that manipulated width/height are adjusted to
match. The adjusted parts are container split, swap, and the input
seat code.
It's possible that some parts of the code are now adjusting width and
height only for those to be immediately recalculated. That's harmless
and since non-tiled containers are still sized with width/height
directly it may avoid breaking other corner cases.
Fixes#3547Fixes#4297
Currently container_replace removes the container from the scratchpad
and re-adds it afterwards. For the split commands this results in the
container being send to the scratchpad, which results in a NULL segfault
if the same container should be shown.
Pass an optional workspace to root_scratchpad_add_container, if the
workspace is passed the window will continue to show on the workspace.
If NULL is passed it is sent to the scratchpad.
This was an issue if no other window except the scratchpad container was
on the workspace.
Fixes#4240
This adds support for the following commands for i3 compatibility:
- `move [window|container] [to] output current`
- `move workspace to [output] current`
- `move workspace [to] output current`
The above commands are only useful when used with criteria.
This modifies cmd_move to allow for the syntax options allowed by i3.
The following syntaxes are supported:
- `move left|right|up|down [<amount> [px]]`
- `move [--no-auto-back-and-forth] [window|container] [to] workspace
<name>|next|prev|next_on_output|prev_on_output|current|number <num>`
- `move [window|container] [to] output <name/id>|left|right|up|down`
- `move [window|container] [to] mark <mark>`
- `move workspace to [output] <name/id>|left|right|up|down`
- `move [window|container] [to] [absolute] position <x> [px] <y> [px]`
- `move [window|container] [to] [absolute] position center`
- `move [window|container] [to] position mouse|cursor|pointer`
This also allows retains the following syntax option that is not
supported by i3, but is supported in sway 1.0:
- `move workspace [to] output <name/id>|left|right|up|down`
The changes are:
- `window` and `container` are now optional
- `output` is now optional for `move workspace` when `to` is given
There is also stricter command checking now. If `absolute` or
`--no-auto-back-and-forth` are given for commands that do not support
them, it will be treated as invalid syntax instead of being silently
ignored.
When setting fullscreen on a hidden scratchpad container, there was a
check to see if there was an existing fullscreen container on the
workspace so it could be fullscreen disabled first. Since the workspace
is NULL, it would cause a SIGSEGV. This adds a NULL check to avoid the
crash.
This also changes the behavior of how fullscreen is handled when adding
a container to the scratchpad or changing visibility of a scratchpad
container to match i3's. The behavior is as follows:
- When adding a container to the scratchpad or hiding a container back
into the scratchpad, there is an implicit fullscreen disable
- When setting fullscreen on a container that is hidden in the
scratchpad, it will be fullscreen when shown (and fullscreen disabled
when hidden as stated above)
- When setting fullscreen global on a container that is hidden in the
scratchpad, it will be shown immediately as fullscreen global. The
container is not moved to a workspace and remains in the
scratchpad. The container will be visible until fullscreen disabled
or killed. Since the container is in the scratchpad, running
`scratchpad show` or `move container to scratchpad` will have no
effect
This also changes `container_replace` to transfer fullscreen and
scratchpad status.
This makes it so running `move [to] scratchpad` on a container already
in the scratchpad does not return an error. To match i3's behavior, a
visible scratchpad container will be hidden and a hidden scratchpad
container will be treated as a noop.
This modifies the places where output_get_active_workspace is called to
handle a NULL result. Some places already handled it and did not need a
change, some just have guard off code blocks, others return errors, and
some have sway_asserts since the case should never happen. A lot of this
is probably just safety precautions since they probably will never be
called when `output_get_active_workspace` is not fully configured with a
workspace.
Just a convenience function that improves readability of the code.
Other things worth noting:
* container_get_siblings and container_sibling_index no longer use the
const keyword
* container_handle_fullscreen_reparent is only ever called after
attaching the container to a workspace, so its con->workspace check has
been changed to an assertion
This removes the call to `root_scratchpad_show` from
`root_scratchpad_remove_container` and places it in the
`cmd_move_container`. This also moved the IPC `window::move` event to
`cmd_scratchpad`.
This commit mostly duplicates the wlr_log functions, although
with a sway_* prefix. (This is very similar to PR #2009.)
However, the logging function no longer needs to be replaceable,
so sway_log_init's second argument is used to set the exit
callback for sway_abort.
wlr_log_init is still invoked in sway/main.c
This commit makes it easier to remove the wlroots dependency for
the helper programs swaymsg, swaybg, swaybar, and swaynag.
This fixes the handling of hidden scratchpad containers for some
commands. For the most part, this just prevents running the commands on
hidden scratchpad containers, but there are some commands that have some
special handling for them.
Patch tested by compiling with `__attribute__ ((format (printf, 2, 3)))`
applied to `cmd_results_new`.
String usage constants have been converted from pointers to arrays when
encountered. General handler format strings were sometimes modified to
include the old input string, especially for unknown command errors.
This combines `output_by_name` and `output_by_identifier` into a single
function called `output_by_name_or_id`. This allows for output
identifiers to be used in all commands, simplifies the logic of the
callers, and is more efficient since worst case is a single pass through
the output list.
moving a container to a non-empty workspace will find a container to move
to in the destination workspace and call container_move_to_container,
which must not just skip floating containers