Since a6e2c15 focustop() returns the fullscreen client even when one of
its children is shown above it, so a dialog opened by a fullscreen client
(a file chooser, say) was shown on top but didn't get focus. Let focustop()
return the fullscreen client's children too, and keep fullscreen_bg on
while one of them is focused.
wlroots still lists the lock surface being destroyed, and inserts new ones
at the head, so when the focused surface was the newest one,
destroylocksurface() gave the focus back to it and then nothing had it:
the password could not be typed until an output changed. Happens e.g.
when unplugging a monitor while locked with waylock.
A client can destroy its xdg_toplevel and keep the xdg_surface. wlroots
keeps the role but sets toplevel to NULL, and xdg_surface->data still
points to the Client freed by destroynotify(), so e.g. a popup created on
that surface made toplevel_from_wlr_surface() read freed memory.
The listener was only removed after the popup's initial commit was handled.
If the popup went away before that (closed before its first commit, no
parent, or destroyed by commitpopup() because its client has no monitor),
it stayed on the surface: wlroots then asserts when the surface is
destroyed, and a commit in between dereferences a NULL popup.
wlr_swapchain_acquire() returns a locked buffer and
wlr_output_state_set_buffer() takes its own lock, so every output enabled
through output management (wlr-randr, kanshi) leaked a buffer. Unlock it
once the state holds it, as wlr_output_swapchain_manager does.
When the session goes away, e.g. seatd being stopped at shutdown, wlroots
destroys the backend by itself (wlr_auto_backend_monitor), and
wlr_backend_finish() aborts since dwl's new_output and new_input listeners
are still attached:
Assertion failed: wl_list_empty(&backend->events.new_input.listener_list)
Detach them and quit instead.