We tried to synchronize layer shell popups with the parent layer shell
on commits, but this is subtly wrong because we would only update
the position for one layer shell that was committed, but not any other
layer that might be affected. By moving handling to the scene descriptor
we can iterate all popups and ensure they are synchronized.
This doesn't catch the error if a background changing command is
executed via swaymsg, but improves logging.
The additional checks at least propagate if e.g. forking failed.
```
Program terminated with signal SIGSEGV, Segmentation fault.
144 struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
[Current thread is 1 (Thread 0x7f1f7c5b3ac0 (LWP 2473))]
(gdb) bt
```
Add a NULL check in `find_mapped_layer_by_client` like the one in `arrange_surface`.
7e69a7076f ("Drop wl_drm") has dropped wl_drm, however a lot of
software wasn't quite ready for this (Xwayland, libva, amdvlk).
Keep wl_drm disabled by default to pressure the wl_drm phase-out,
but add a -Dlegacy-wl-drm flag for users to restore the previous
behavior in the meantime.
References: https://github.com/swaywm/sway/issues/7897
swaybg is out-of-tree so not relevant here. swaybar's tray doesn't
actually depend on gdk-pixbuf, but gdk-pixbuf enables more image
formats for swaybar tray when available.
Closes: https://github.com/swaywm/sway/issues/7913
```
Program terminated with signal SIGSEGV, Segmentation fault.
warning: Section `.reg-xstate/3960717' in core file too small.
0 container_get_siblings (container=0x55bcde4797f0) at ../sway/tree/container.c:1228
1228 if (list_find(container->pending.workspace->tiling, container) != -1) {
[Current thread is 1 (Thread 0x7fa23b4a2940 (LWP 3960717))]
(gdb) bt full=
No symbol "full" in current context.
(gdb) bt full
0 container_get_siblings (container=0x55bcde4797f0) at ../sway/tree/container.c:1228
1 0x000055bcdb62c704 in edge_is_external (cont=0x55bcde4797f0, edge=(WLR_EDGE_TOP | WLR_EDGE_LEFT))
at ../sway/input/seatop_default.c:54
siblings = 0x55bcde4797f0
index = 32766
layout = L_NONE
__PRETTY_FUNCTION__ = "edge_is_external"
2 0x000055bcdb62c96f in find_resize_edge (cont=0x55bcde4797f0, surface=0x0, cursor=0x55bcddd5c2e0)
at ../sway/input/seatop_default.c:106
edge = (WLR_EDGE_TOP | WLR_EDGE_LEFT)
3 0x000055bcdb620b3c in cursor_update_image (cursor=0x55bcddd5c2e0, node=0x55bcde4797f0) at ../sway/input/cursor.c:144
edge = WLR_EDGE_NONE
4 0x000055bcdb62eb8f in handle_rebase (seat=0x55bcddd5a740, time_msec=488992944) at ../sway/input/seatop_default.c:773
e = 0x55bcddd5c8e0
cursor = 0x55bcddd5c2e0
surface = 0x0
sx = 0
sy = 0
5 0x000055bcdb62c531 in seatop_rebase (seat=0x55bcddd5a740, time_msec=488992944) at ../sway/input/seat.c:1585
6 0x000055bcdb620a7d in cursor_rebase (cursor=0x55bcddd5c2e0) at ../sway/input/cursor.c:126
time_msec = 488992944
7 0x000055bcdb620ac4 in cursor_rebase_all () at ../sway/input/cursor.c:136
seat = 0x55bcddd5a740
8 0x000055bcdb61cc95 in transaction_apply (transaction=0x55bcde5b28c0) at ../sway/desktop/transaction.c:704
9 0x000055bcdb61ccdb in transaction_progress () at ../sway/desktop/transaction.c:716
10 0x000055bcdb61d1f9 in transaction_commit_pending () at ../sway/desktop/transaction.c:836
transaction = 0x55bcde5b28c0
11 0x000055bcdb61d596 in _transaction_commit_dirty (server_request=true) at ../sway/desktop/transaction.c:912
12 0x000055bcdb61d5ac in transaction_commit_dirty () at ../sway/desktop/transaction.c:916
13 0x000055bcdb65f579 in view_unmap (view=0x55bcde2ff180) at ../sway/tree/view.c:847
parent = 0x55bcde489010
ws = 0x55bcdde19080
seat = 0x55bcddd5a198
14 0x000055bcdb61e461 in handle_unmap (listener=0x55bcde2ff368, data=0x0) at ../sway/desktop/xdg_shell.c:394
xdg_shell_view = 0x55bcde2ff180
view = 0x55bcde2ff180
__PRETTY_FUNCTION__ = "handle_unmap"
15 0x00007fa23c4ae87f in wlr_signal_emit_safe (signal=0x55bcde46cf38, data=0x0) at ../util/signal.c:29
pos = 0x55bcde2ff368
l = 0x55bcde2ff368
cursor = {link = {prev = 0x55bcde2ff368, next = 0x7ffe240702a0}, notify = 0x7fa23c4ae7c9 <handle_noop>}
end = {link = {prev = 0x7ffe24070280, next = 0x55bcde46cf38}, notify = 0x7fa23c4ae7c9 <handle_noop>}
16 0x00007fa23c47c3c7 in unmap_xdg_surface (surface=0x55bcde46ce30) at ../types/xdg_shell/wlr_xdg_surface.c:40
__PRETTY_FUNCTION__ = "unmap_xdg_surface"
popup = 0x55bcde46ce60
popup_tmp = 0x55bcde46ce60
configure = 0x7ffe24070360
tmp = 0x55bcde488020
17 0x00007fa23c47cd47 in xdg_surface_role_precommit (wlr_surface=0x55bcde488020, state=0x55bcde4881a8)
at ../types/xdg_shell/wlr_xdg_surface.c:330
surface = 0x55bcde46ce30
18 0x00007fa23c4813b2 in surface_commit_state (surface=0x55bcde488020, next=0x55bcde4881a8) at ../types/wlr_compositor.c:407
__PRETTY_FUNCTION__ = "surface_commit_state"
invalid_buffer = false
subsurface = 0xbd8e9aecae023300
--Type <RET> for more, q to quit, c to continue without paging--
19 0x00007fa23c48192a in surface_handle_commit (client=0x55bcde488850, resource=0x55bcde2fdb80) at ../types/wlr_compositor.c:523
surface = 0x55bcde488020
20 0x00007fa23bb5ed4a in () at /usr/lib/libffi.so.8
21 0x00007fa23bb5e267 in () at /usr/lib/libffi.so.8
22 0x00007fa23c517323 in () at /usr/lib/libwayland-server.so.0
23 0x00007fa23c5125cc in () at /usr/lib/libwayland-server.so.0
24 0x00007fa23c5151ca in wl_event_loop_dispatch () at /usr/lib/libwayland-server.so.0
25 0x00007fa23c512d37 in wl_display_run () at /usr/lib/libwayland-server.so.0
26 0x000055bcdb616885 in server_run (server=0x55bcdb68c5c0 <server>) at ../sway/server.c:307
27 0x000055bcdb61594e in main (argc=3, argv=0x7ffe24070af8) at ../sway/main.c:433
```
It seems to be happening because of this set of events all happening
in the span of a single transaction:
1. You kill a tiled window that is the only window in a workplace.
2. Sway will destroy the workspace but not yet the container - this
makes `con->pending.workspace` NULL.
3. Cursor glyphs get recomputed causing sway to recompute if the cursor
is on a container edge.
4. That computation causes an access to the NULL workspace. Crash.
Instead of doing this roundabout thing where we get the surface from the
view, let's instead get it from the `wlr_surface_state` that we already
track in `handle_commit`. This makes the NULL state impossible which is
what the old `get_geometry` is checking for and generally cleans
things up a little bit.
Also don't check if the geometry x/y changed, those will always
be 0 for xwayland.
Across a wayland compositor, there are multiple shells: It can be
a toplevel, or a layer_shell, or even something more meta like a drag
icon or highlight indicators when dragging windows around.
This object lets us store values that represent these modes of operation
and keep track of what object is being represented.