This change avoids a cyclic reference in the window tree when dragging a
container and dropping it into one of its descendants.
The drop target resolution logic previously only checked if the target node
was the container itself, but missed checking if the target was a descendant
of the dragged container.
Fixes: #7949
`seat_set_workspace_focus()` contains two references to the "last
workspace":
- `last_workspace` is the last focused workspace on all outputs.
- `new_output_last_ws` is the last focused workspace on the new
workspace output.
They are the same when using a single output, but with multiple outputs
they can diverge: `last_workspace` will be the focused workspace on the
previous output, `new_output_last_ws` will be the previously focused
workspace on the current output.
This confusion seems to have led to #9139 when `last_workspace` was used
instead of `new_output_last_ws`.
However, we can safely drop `last_workspace` and use
`new_output_last_ws` for everything that `seat_set_workspace_focus()`
does:
- Calling `node_set_dirty()` on the new output.
- Calling `wlr_ext_workspace_handle_v1_set_active()` on the last
workspace (this fixes#9139).
- Skip `workspace_consider_destroy()` on `last_workspace`, since the
other output still has it focused.
This commit also renames `new_output_last_ws` to `last_workspace` to
keep the name simple.
When a fullscreen view is present on a workspace that has panels (e.g. a
bar with exclusive zone), the view's content geometry extends beyond the
workspace's usable area. The edge-detection thresholds computed from the
view's content_x/content_width could then lie outside the parent
container's box, causing the indicator width or height to become
negative. This triggered an assertion in wlr_scene_rect_set_size. Fix
this by clamping the threshold coordinates to the parent container's
boundaries before using them to size the drop indicator.
fixes#9102
Before this change, with `workspace_layout tabbed`, moving T[app app] to
an empty workspace resulted in T[T[app] T[app]], as each child was
individually wrapped in a new split container.
It looks like commit 92891fb1 introduced workspace_unwrap_children to
fix an issue where moving a tabbed/stacked container to a new workspace
with workspace_layout tabbed would incorrectly nest the container,
creating T[T[app app]].
However, workspace_unwrap_children used workspace_add_tiling to add the
detached children to the workspace. Since commit ece6a1d4,
workspace_add_tiling checks for a configured default_layout and if it
finds one, calls container_split for every added window.
This commit changes the unwrapping logic to use
workspace_insert_tiling_direct instead of workspace_add_tiling,
avoiding the default_layout splitting behaviour.
When launching swaybar from the command line without a --bar-id flag,
default to the first configured bar.
This is a mirror of i3 PR https://github.com/i3/i3/pull/4231.
This makes it easier to call swaybar from the command line since the
majority of swaybar users have only one bar configured.
Anchored ^name$ and bare names are accepted; everything else,
including regex alternation, returns a clear error instead of
silently falling through to ATOM_LAST.
Strip C-style header comments before json parsing so the
i3-save-tree vim modeline does not break }\n{ concat detection.
Pass window_type to the criteria parser bare and unanchored,
since the parser treats it as an enum token and the i3 form
"^name$" was being silently dropped to ATOM_LAST.
--workspace was documented as accepting a name or a number, but
the lookup only compared against the IPC name, so common
workspaces such as "1: web" (num=1) could not be selected with
--workspace 1. Parse a numeric argument and also compare against
the num field. Update the manpage accordingly.
A placeholder leaf has view==NULL, so arrange_container routes it
to its view-less branch, which calls arrange_children with the
container's layout. arrange_children asserts on L_NONE, so a
plain { swallows: [...] } JSON entry crashed assert-enabled
builds before any window could match.
Default the layout to L_HORIZ when JSON does not specify one.
The placeholder has no children, so the iteration short-circuits
without rendering anything until promoted.
Swallow values were embedded directly into the synthesised
criteria string; a value containing " produced a malformed
[key="..."..."] that the criteria tokenizer could not parse, so
layouts with quoted titles failed to load. Escape " as \" before
embedding so the value survives the tokenizer and is recovered
by the existing criteria unescape.
workspace_add_tiling wraps each top-level container with
container_split when config->default_layout is set, mutating
restored layouts. Use workspace_insert_tiling_direct so the
parsed subtree is attached as-is.
ipc_json_describe_container emits the original swallows JSON for
unfilled placeholders. New sway-save-tree binary dumps a
workspace tiling tree as append_layout-compatible JSON,
synthesising swallows from app_id / class / instance.
Before container_create in view_map, look up an unfilled
placeholder whose swallows match. On hit, install the view in
place and skip the workspace/sibling placement path. Border
config is preserved; for_window still runs post-placement.
Parse i3-save-tree-style JSON into a detached subtree of
placeholder containers and append to a workspace. Reuses
criteria_parse for swallows. Tiling-only; floating_nodes are
skipped with a debug log.
The swallow walker matches against a view that has not yet been
attached to a container. Factor the view-intrinsic checks out of
criteria_matches_view and expose them as
criteria_matches_view_unmapped.
When a container is moved, `finalize_move` previously assumed that
calling `workspace_split` would always result in a workspace with exactly
1 child (the wrapper container). Consequently, it safely assumed that
inserting a container with `after = 1` was always valid.
However, if the moved container was the only child of its workspace,
calling `container_detach` drops the workspace's tiling length to 0.
Calling `workspace_split` on an empty workspace simply changes its
layout enum and returns, leaving the length at 0. Passing `after`
(which evaluates to 1 when moving right/down) into
`workspace_insert_tiling` then causes an out-of-bounds insertion and a
subsequent segmentation fault during `container_build_representation`.
This commit fixes the issue by dynamically calculating the insertion
index based on the actual length of the workspace's tiling list at the
moment of insertion, rather than overloading the `after` boolean flag
as a hardcoded index.
This fixes a race that causes UAF when turning on multiple outputs after
they've been off for a while.
When output_begin_destroy is called while a transaction that references
the output is in-flight, node_set_dirty adds the node to
server.dirty_nodes list and ntxnrefs is still held by that transaction.
Once the transaction completes and ntxnrefs drops to 0,
transaction_destroy frees the output, leaving a dangling pointer in
server.dirty_nodes. The next transaction_commit_dirty call then walks
the dirty_nodes list and crashes
The fix is to skip the free in transaction_destroy if node->dirty is
set, this means transaction_commit_dirty hasn't processed this node yet
and will bump ntxnrefs shortly. The free will happen once that
transaction completes and ntxnrefs reaches 0 again and
transaction_commit_dirty will allocate a fresh instruction and
increment ntxnrefs again when it processes the node.
When focus leaves a surface, ensure any active keyboard grab is
terminated. This prevents stale xdg-popup grabs from persisting
after the popup is destroyed, which could otherwise cause keyboard
input to remain stuck on the old window.
fixes#8919
It made sense to put it on the container level because the protocol cares
about the toplevel and that includes its decorations. But, this breaks
down when we consider if the container's view is fullscreen and the container
decorations are disabled. Moving it to the view manages this expected lifetime
better. Since the buffer is now part of the view, the buffer will get
negative coordinates to act as if it's part of the container when we
want to.
A known issue is that we will send spurious leave/enter events while
we reconfigure the scene for entering/exiting fullscreen. The fix for
this loops back to atomic updates to scene and that is outside of the scope
of this commit.
Fixes: #9000
server_init ignores all errors. In practice, theses result in a
segfault, potentially much later and losing any unsaved work.
Properly handle initialisation errors and bail immediately.
Sway renders fullscreen surfaces smaller than the output left-aligned.
From xdg-shell:
> If the surface doesn't cover the whole output, the compositor will
> position the surface in the center of the output and compensate with
> with border fill covering the rest of the output. The content of the
> border fill is undefined, but should be assumed to be in some way that
> attempts to blend into the surrounding area (e.g. solid black).
Render surfaces smaller than the output centred. Can be tested easily
with:
weston-simple-egl -f -r
Fixes: https://github.com/swaywm/sway/issues/8845
Maintain a 1:1 relationship between workspace groups and outputs, so
that moving a workspace across groups effectively moves it across
outputs.
ext_workspace_handle_v1::id is never emitted; sway has no concept of ids
or of stable vs temporary workspaces. Everything is ephemeral to the
current session.
ext_workspace_handle_v1::coordinates is never emitted; sway does not
organise workspaces into any sort of grid.
ext_workspace_handle_v1::assign is mostly untested, because no client
current implements this. Perhaps it's best to not-advertise the feature
for now?
Deactivating a workspace is a no-op. This functionality doesn't really
align with sway, although it could potentially be implemented to "switch
to previous workspace on this output" as a follow-up.
Removing a workspace is a no-op.
Implements: https://github.com/swaywm/sway/issues/8812
We never need a cairo context for anything here. Use
pango_cairo_font_map_get_default() and pango_font_map_create_context()
directly instead of bootstrapping via a nil cairo context.
Same as last commit, but just a cosmetic fix in this case since we don't
actually use the cairo context for anything
This fixes sway not being able to draw text on text nodes.
cairo_create(NULL) returns a nil object in an error state rather than
NULL, causing the null check to never trigger and passing a broken cairo
context to get_text_size, which was fine until 40e1dcd29f adding error
handling to it and causing pango_cairo_update_layout to fail with a NULL
pointer.
Layer shell popups were missing a handler for the xdg_popup reposition
event. When a client (e.g. GTK4) creates a popup and then sends a
reposition request, wlroots resets the scheduled geometry back to the
positioner's original value. Without a reposition handler, the
unconstrained geometry computed on the initial commit was lost, causing
popups such as tooltips to render outside the screen viewport.
This was most visible with GTK4 layer shell apps (e.g. taskbars) where
tooltips would appear below the bottom edge of the screen instead of
being flipped/slid into the visible area.
Also switch the destroy listener from wlr_popup->base->events.destroy
to wlr_popup->events.destroy so that cleanup runs before wlroots
asserts that all popup signal listeners have been removed.
Fixes#8518