wlr_output is not well-suited to checking whether direct scan-out
is happening or not. Compositors may want to use their own external
swapchains, for instance.
Additionally, ab7eabac84 ("output: leverage
wlr_output_configure_primary_swapchain()") makes it so
output_basic_test() is called before the output swapchain is
initialized, resulting in false positives.
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3620
This allows callers to set a destination size different from the
buffer size to scale them.
The DRM backend supports this. The Wayland backend doesn't yet
(we'd need to wire up viewporter).
- Simplifies the backends
- Avoids having two ways to do the same thing: previously one could
disable a layer by either omitting it from wlr_output_state.layers,
or by passing a NULL buffer
- We can change our mind in the future: we can allow users to omit
some layers and define a meaning without breaking the API.
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4017#note_1783997
When a new client comes in and tries to create a
zwlr_gamma_control_v1 object for an output which already has one,
we were destroying the old object and early-returning. The early
return causes the new object to not be set up properly: it's not
inserted in the list and doesn't get the gamma_size event.
Fix this by destroying the new object, and leave the old object
intact, which is what was the intent I think.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3605
Replace our current logic to setup the primary swapchain with
wlr_output_configure_primary_swapchain().
- Removes some code, reducing duplication
- Stop overwriting wlr_output.swapchain with a yet-to-be-tested
swapchain: remove the error_destroy_swapchain label.
We've had this struct for a while. It'd be useful for compositors
if they want to manage the swap chains themselves instead of being
forced to use wlr_output's. Some compositors might also want to use
a swapchain without an output.
This is based on previous work [1] [2].
This new API allows compositors to display buffers without needing to
perform rendering operations. This API can be implemented on Wayland
using subsurfaces and on DRM using KMS planes.
Compared to [1], this approach leverages wlr_addon_set to let backends
attach their own private state to layers, removes the pending
state (necessary for interop with wlr_output_commit_state()) and
enum wlr_output_layer_state_field.
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/1985
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3447
options->scanout_primary_output indicates an output on which scanout is desirable.
Set the missing SCANOUT flag.
Fixes: 0c966f102c ("linux-dmabuf-v1: add wlr_linux_dmabuf_feedback_v1_init_with_options()")
This patch allows surfaces without keyboard focus
but with pointer focus to receive valid tokens.
This can be relevant for applications using an older version of
the layershell protocol which only provided the choice between
no keyboard focus and exclusive keyboard focus.
In output_ensure_buffer() we create a swapchain and attach an empty
buffer to the output if necessary. We do that during the first commit.
This is fine when the first commit enables the output, however this breaks
when the first commit disables the output. A commit which disables an
output and has a buffer attached is invalid (see output_basic_test()), and
makes the DRM backend crash:
00:00:00.780 [wlr] [backend/drm/drm.c:622] connector eDP-1: Turning off
../subprojects/wlroots/backend/drm/drm.c:652:44: runtime error: member access within null pointer of type 'struct wlr_drm_crtc'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2524==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f22e894afc1 bp 0x7ffe1d57c550 sp 0x7ffe1d57c420 T0)
==2524==The signal is caused by a READ memory access.
==2524==Hint: address points to the zero page.
#0 0x7f22e894afc1 in drm_connector_commit_state ../subprojects/wlroots/backend/drm/drm.c:652
#1 0x7f22e894b1f5 in drm_connector_commit ../subprojects/wlroots/backend/drm/drm.c:674
#2 0x7f22e89e8da9 in wlr_output_commit_state ../subprojects/wlroots/types/output/output.c:756
#3 0x555ab325624d in apply_output_config ../sway/config/output.c:517
#4 0x555ab31a1aa1 in handle_new_output ../sway/desktop/output.c:974
#5 0x7f22e9272f6d in wl_signal_emit_mutable (/usr/lib/libwayland-server.so.0+0x9f6d)
#6 0x7f22e899b012 in new_output_reemit ../subprojects/wlroots/backend/multi/backend.c:161
#7 0x7f22e9272f6d in wl_signal_emit_mutable (/usr/lib/libwayland-server.so.0+0x9f6d)
#8 0x7f22e895a153 in scan_drm_connectors ../subprojects/wlroots/backend/drm/drm.c:1488
#9 0x7f22e893c2e4 in backend_start ../subprojects/wlroots/backend/drm/backend.c:24
#10 0x7f22e892ed00 in wlr_backend_start ../subprojects/wlroots/backend/backend.c:56
#11 0x7f22e8999b83 in multi_backend_start ../subprojects/wlroots/backend/multi/backend.c:31
#12 0x7f22e892ed00 in wlr_backend_start ../subprojects/wlroots/backend/backend.c:56
#13 0x555ab317d5cc in server_start ../sway/server.c:316
#14 0x555ab317748d in main ../sway/main.c:400
#15 0x7f22e783c28f (/usr/lib/libc.so.6+0x2328f)
#16 0x7f22e783c349 in __libc_start_main (/usr/lib/libc.so.6+0x23349)
#17 0x555ab3134c84 in _start (/home/simon/src/sway/build/sway/sway+0x377c84)
Fixes: 3be6658ee7 ("output: allocate swapchain on first commit")
Closes: https://github.com/swaywm/sway/issues/7373
When a client attaches a NULL buffer to its wl_surface, it's
unmapped. This resets the xdg_surface in its initial state. An
extra NULL commit makes the compositor send an initial configure
event.
Note, wlr_xdg_toplevel.added is separate from wlr_xdg_surface.added.
Closes: https://github.com/swaywm/sway/issues/7397
The invalid_destroy and invalid_unlock protocol errors aren't currently
sent by wlroots and instead left up to the compositor. However, we can
handle these as well without much additional complexity.
This also adds a missing wl_resource_destroy() call if the lock is inert
in lock_handle_unlock_and_destroy().
wlroots uses "// private state" comments to denote structure fields
which shouldn't be accessed by compositors, so let's drop
wlr_output_layout_output_state and inline its fields into
wlr_output_layout_output; this also simplifies layout output creation.
With the Vulkan renderer we don't support implicit modifiers.
However wl_drm only supports implicit modifiers.
Stop advertising wl_drm formats when implicit modifiers are
unsupported.
Query the formats at init time, then forget about the renderer.
This will allow wl_drm to be created with a list of formats instead
of a renderer, and will behave better after a GPU reset.
The backend no longer changes the output state behind the
compositor's back. Instead, compositors can listen to the "commit"
event and check for WLR_OUTPUT_STATE_ENABLED/WLR_OUTPUT_STATE_MODE.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2300
Some compositors may want to use the linux-dmabuf-v1 implementation
with a completely custom renderer. Add a function to create the
global with a default feedback.
...when only one edge is anchored.
The layer-shell protocol specifies that a positive exclusive-zone value is
'meaningful' if the surface is anchored to either:
1. one edge
2. one edge and both perpendicular edges.
For example, if you wish to position a layer-shell client along the top
edge and make it exclusive, you should be able to either set anchor=TOP or
anchor=TOP|LEFT|RIGHT. It appears that many panels/bars use the latter
approach (anchor to an edge and also both perpendicular edges) which is
probably why this has not been reported previously.
This patch adds support for the first case and thereby makes exclusive
zone behaviour consistent with the protocol and also with sway's extant
layer-shell implementation.
Now, it is checked whether an output pixel corresponds to an integer
number of buffer pixels; if it doesn't, the region is altered to take
this into account.
This allows the backend to have access to the frame damage, as
reported by the scanned-out client. Some KMS drivers can make use
of it (e.g. for PSR, or optimized USB transfers in the GUD driver),
and the Wayland/X11 backends forward it to the parent compositor.
This is a first step towards moving texture uploading out of
wlr_compositor.
This commit allows compositors to opt-out of the texture uploading
by passing a NULL wlr_renderer. An immediate user of this is
gamescope, which currently implements a stub wlr_renderer just to
make wlr_compositor happy.
Fixes
In file included from /usr/include/wayland-server-core.h:32,
from ../types/seat/wlr_seat_pointer.c:6:
In function 'wl_fixed_from_double',
inlined from 'wlr_seat_pointer_send_axis' at ../types/seat/wlr_seat_pointer.c:367:6:
/usr/include/wayland-util.h:641:17: error: 'low_res_value' may be used uninitialized [-Werror=maybe-uninitialized]
641 | u.d = d + (3LL << (51 - 8));
| ~~^~~~~~~~~~~~~~~~~~~
../types/seat/wlr_seat_pointer.c: In function 'wlr_seat_pointer_send_axis':
../types/seat/wlr_seat_pointer.c:329:16: note: 'low_res_value' was declared here
329 | double low_res_value;
| ^~~~~~~~~~~~~
Use a basic linked list to store the currently active mappings.
Note that we don't actually need to implement a full lock-free
atomic linked list here. The signal handler will never write to
the list, it will only read it. Only the main thread will write.
We need to always expose a consistent view of the list to the
signal handler (the main thread might be interrupted at any point
by the signal handler).
This is a re-implementation of wl_shm. The motivations for using
this over the one shipped in libwayland are:
- Properly handle SIGBUS when accessing a wl_buffer's underlying
data after the wl_buffer protocol object has been destroyed.
With the current code, we just crash if the client does that
and then shrinks the backing file.
- No need to fight the wl_shm_buffer API anymore. This was awkward
because we weren't notified when clients created a wl_shm buffer,
and this doesn't play well with our wlr_buffer abstraction.
- Access to the underlying FD. This makes it possible to forward
the wl_shm buffer to a parent compositor with the Wayland/X11
backends.
- Better stride checks. We can use our format table to ensure that
the stride is consistent with the bpp and width.
The concept of a persistent accumulated surface offset is wrong
from a protocol point-of-view. wl_surface.offset is tied to a
commit, its interpretation depends on the surface role.
For example, with the following sequence:
wl_surface@1.offset(1, 1)
wl_surface@1.commit()
wl_pointer@2.set_cursor(wl_surface@1, 42, 42)
The final cursor hotspot is (42, 42): the commit which happened
before the set_cursor request has no impact on the hotspot
computation.
The wlr_output_cursor logic already uses wlr_surface.current.{dx,dy}.
wlr_scene's drag icon doesn't, update it accordingly.
This allows compositors to indicate which features they support,
and is required to eventually make this API stable.
References: https://github.com/swaywm/sway/issues/7260
If a fixed mode matching the user requirements is available, use
that. This avoids generating the mode with GTF or CVT in the DRM
backend, and instead uses mode timings advertised by the output.
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3514
If a new buffer is set for a buffer node, we must update the entire
node unconditionally if the buffer size changes, or the buffer is given
a buffer where it was previously NULL.
While we're here, let's avoid calling scene_node_update on just damage
updates. If the caller hasn't given us a damage region we just assume
the whole buffer.
If the area calculations for output overlap overflow a signed int, we
may not consider it to be a primary output. Turn this into an unsigned
type so this happens less frequently.
Additionally, it is possible the overflow would produce 0, we can handle
this by simply changing the comparison to more than or equal.
While we're here, let's assert that we always assign a primary output
if there are any intersecting outputs.
We were crashing in the error codepath [1] when
wlr_drm_create_lease() fails.
To fix this, delay the creation of the wlr_drm_lease_v1 until the
request is granted. Previously we were allocating that struct early
without populating the drm_lease field. However that means we ended
up with a half-constructed struct in the error codepath which is
annoying to handle.
[1]: https://github.com/swaywm/sway/issues/7204#issuecomment-1269797356
On first commit, require a new buffer if the compositor called a
mode-setting function, even if the mode won't change. This makes it
so the swapchain is created now.
Stop trying to check whether the backend supports buffer-less modesets
because that makes everything more complicated. For instance, the
DRM backend doesn't need a new buffer if the previous DRM master left
the output enabled.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3499
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3502
Some compositors want to have full control over the buffers attached
to the output, and don't want to use the internal swapchain. Such
compositors include KWinFT (allocates its buffers on its own) and
gamescope (uses a headless output without any buffers).
Let's just make output_ensure_buffer() a no-op in that case.
When starting up, the compositor might call wlr_output_set_mode()
with a mode which is already the current one. wlroots will detect
this and make the wlr_output_set_mode() call a no-op. During the
next wlr_output_commit() call, wlroots will perform an atomic
commit without the ALLOW_MODESET flag.
This is an issue, because some drivers need ALLOW_MODESET even if
the mode is the same. For instance, if the FB stride or modifier
changed, some drivers require a modeset.
Add a new flag "allow_artifacts" which is set when the compositor
calls mode-setting functions. Use this flag to figure out whether
we want to perform atomic commits with ALLOW_MODESET.
(The name "allow_artifacts" is picked because ALLOW_MODESET is a
misnomer, see [1].)
[1]: https://patchwork.freedesktop.org/patch/505107/
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3499
Instead of using low-level wl_shm_buffer and wlr_dmabuf_v1_buffer
APIs, use the unified wlr_buffer APIs. That way it doesn't matter
what the exact wlr_buffer implementation is used, any which provides
the necessary capabilities (data_ptr or dmabuf) would work.
Simplifies the logic a bit, and will make the transition to wlr_shm
easier.
There doesn't appear to be any good reason to warp the cursor to
the top-left corner when all outputs are disconnected; it's no more
valid than any other (x,y) point in that case.
The real-world case here is a user with a single external monitor
turning it off (which apparently counts as disconnected depending
on the connection type/hardware). For that user, it's desirable to
have the cursor remain in its original location when the monitor
is turned back on.
It should be considered a bug if a compositor sets a non-finite
cursor position, so fail loudly (in debug builds) if that happens.
The existing check in wlr_cursor_warp_closest() is now redundant,
and would silently hide such bugs, so remove it.
In wlr_output_attach_render(), stop setting
wlr_output.pending.buffer. This removes one footgun: using the
wlr_buffer at that stage is invalid, because rendering operations
haven't been flushed to the GPU yet. We need to wait until
output_clear_back_buffer() for the wlr_buffer to be used safely.
Instead, set wlr_output.pending.buffer in wlr_output_test() and
wlr_output_commit().
Additionally, move the output_clear_back_buffer() from
wlr_output_commit_state() to wlr_output_commit(). This reduces the
number of calls in the failure path.
We can just use pending.buffer instead. It's completely fine to
call wlr_swapchain_set_buffer_submitted() with a buffer which
doesn't come from the swapchain, in which case it's a no-op.
This is documented to reset the gamma LUT, but we don't handle this
properly.
While at it, make sure we leave wlr_output.pending in a good state
on allocation failure.
wlr_buffer.c is difficult to read because it contains a mixed bag
of unrelated things: base buffer type, buffer implementations,
buffer resource factory, and client buffer.
Split each of these into their own file.
valgrind said (on exit from labwc):
Invalid write of size 8
at 0x487DEAF: wl_list_remove (wayland-util.c:56)
by 0x487DF80: wl_signal_emit_mutable (wayland-server.c:2182)
by 0x48CD6B7: backend_destroy.part.0.lto_priv.0 (backend.c:41)
by 0x48DC19D: multi_backend_destroy (backend.c:58)
by 0x4880286: UnknownInlinedFun (wayland-server.c:2315)
by 0x4880286: wl_display_destroy (wayland-server.c:1170)
by 0x112491: UnknownInlinedFun (server.c:485)
by 0x112491: main (main.c:110)
Address 0x1f9d0210 is 112 bytes inside a block of size 136 free'd
at 0x484426F: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x487DF6D: wl_signal_emit_mutable (wayland-server.c:2179)
by 0x48CD6B7: backend_destroy.part.0.lto_priv.0 (backend.c:41)
by 0x48DC19D: multi_backend_destroy (backend.c:58)
by 0x4880286: UnknownInlinedFun (wayland-server.c:2315)
by 0x4880286: wl_display_destroy (wayland-server.c:1170)
by 0x112491: UnknownInlinedFun (server.c:485)
by 0x112491: main (main.c:110)
Block was alloc'd at
at 0x4846A73: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4918D4E: drm_lease_device_v1_create (wlr_drm_lease_v1.c:639)
by 0x48D3B00: wlr_multi_for_each_backend (backend.c:249)
by 0x49191D2: wlr_drm_lease_v1_manager_create (wlr_drm_lease_v1.c:706)
by 0x111EE9: UnknownInlinedFun (server.c:384)
by 0x111EE9: main (main.c:92)
dac040f87f mistakenly renamed
xdg_surface_destroy listener, which was listening to *unmap* events, to
xdg_surface_unmap. The actual fix, however, is to listen to destroy
events. This fixes various crashes.
If the first test in output_ensure_buffer() fails with modifiers we
replace the swapchain with a modifierless swapchain and try again.
However if that fails as well the output is currently stuck without
modifiers until the next modeset.
To fix this, destroy the modifierless swapchain if the test using it
fails. The next output_attach_back_buffer() call will create a swapchain
that allows modifiers when needed.
Originally, I thought that we could safely subtract opaque regions
from the background even if the black rect optimization was kicking in.
This is wrong because a scene node that isn't fully occluded will still
appear in the render list even if its partially under a black rect. We
need to make sure that while culling the background, we only consider
opaque regions that are also visible. This will fix the black rect
optimization with the background.
We don't need to worry about the black rect optimization here (that
always assumes that there will be a black background) because the
background is culled based on the render list. That means if a black rect
is removed, the visibility will reach all the way to the bottom forcing
the renderer to clear the area not breaking the assumption.
If culling is not enabled, there is no longer any guarantee that the
elements behind the rect won't be rendered. We must render the black rect
in all circumstances to cover up anything rendered.
This fixes the WLR_SCENE_DISABLE_VISIBILTY option.
If the client binds to version 3 of zxdg_output_v1 and version 1 of
wl_output no wl_output.done or zxdg_output_v1.done event is
emitted [1].
Also no wl_output.done event is emitted when version 2 or lower of
zxdg_output_v1 is bound to.
Add a version check to output_manager_handle_get_xdg_output so that no
wl_output.done event is emitted when using version 1 of wl_output and
version 2 or lower of zxdg_output_v1.
[1]: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/81
This has a few benefits one of them crucial for proper operation:
- The primary output will be based on the largest area that is actually
visible to the user. Presentation and frame done events are based on
this state. This is important to do since we cull frame done events.
If we happen to be in a situation where a surface sits mostly on output
A and some on output B but is completely obstructed by for instance a
fullscreen surface on output A we will erroneously send frame_done
events based on output A. If we base things as they are in reality
(visibility) the primary output will instead be output B and things will
work properly.
- The primary output will be NULL if the surface is completely hidden.
Due to quirks with wayland, on a surface commit, frame done events are
required to be sent. Therefore, a new frame will be submitted for rendering
on the primary output. We can improve adaptive sync on completely hidden
but enabled surfaces if we null out the primary output in this state.
- The client will be more likely to choose better metadata to use
for rendering to an output's optimal rendering characteristics.
We can also get rid of the intersection checks in the rendering functions
because we are guaranteed to already be in the node do to the prior
intersection checking of the node visibility.
Simplify damage handling by using our cached visibility state.
Damaging can happen in one step because since we can use the old visibility
state which represent what portions of the screen the scene node was. This
way we can damage everything in one step after the fact.
Will query the scene for all nodes that appear in the given wlr_box.
The nodes will be sent to the iterator from closest to farthest from the
eye.
Refactor wlr_scene_node_at to use this new function.
This lets the renderer handle the wlr_buffer directly, just like it
does in texture_from_buffer. This also allows the renderer to batch
the rectangle updates, and update more than the damage region if
desirable (e.g. too many rects), so can be more efficient.
Only the exclusion zone for mapped layer shell surfaces should be respected. In
particular, a layer shell surface that was mapped with an exclusion zone but is
now unmapped should not adjust the usable area.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3471
This allows whatever the user calls from the signal handlers to react to observe
the new state rather than the old, e.g. that a surface is no longer mapped in
the unmap handler.
This results in the following warning, which in release mode causes an
error due to -Werror:
../types/seat/wlr_seat_pointer.c: In function ‘wlr_seat_pointer_send_axis’:
../types/seat/wlr_seat_pointer.c:344:25: error: ‘low_res_value_discrete’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
343 | if (version < WL_POINTER_AXIS_VALUE120_SINCE_VERSION &&
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344 | value_discrete != 0 && low_res_value_discrete == 0) {
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
This commit fixes:
- sending discrete scrolling events to multiple pointer resources
- sending events to clients which don't support wl_pointer.axis_discrete
When the client doesn't support high-resolution scroll, accumulate
deltas until we can notify a discrete event.
Some mice have a free spinning wheel, making possible to lock the wheel
when the accumulator value is not 0. To avoid synchronization issues
between the mouse wheel and the accumulators, store the last delta and
when the scroll direction changes, reset the accumulator.
Upgrade the seat protocol to version 8 and handle clients that support
high-resolution scroll wheel events.
Since the backend already sends discrete values in the 120 range,
forwarding them is enough.
Currently, the "wlr_event_pointer_axis" event stores low-resolution
values in its "delta_discrete" field. Low-resolution values are always
multiples of one, i.e., 1 for one wheel detent, 2 for two wheel
detents, etc.
In order to simplify internal handling of events, always transform in
the backend from the low-resolution value into the high-resolution
value.
The transformation is performed by multiplying by 120. The 120 magic
number is used by the kernel and it is exposed to clients in the
"WLR_POINTER_AXIS_DISCRETE_STEP" constant.
When using direct scanout back_buffer is NULL. We'd emit a commit
event with WLR_OUTPUT_STATE_BUFFER set but with a NULL buffer field,
which is non-sensical.
wl_subsurface description states:
A sub-surface becomes mapped, when a non-NULL wl_buffer is applied and
the parent surface is mapped.
Note that this doesn't require an explicit commit, which means that a
newly created subsurface with a mapped parent and a buffer already
attached must be mapped immediately. This can happen with the following
sequence of events:
- subcompositor.get_subsurface(subsurface, surface, parent)
- surface.attach(buffer)
- surface.commit()
- subsurface.destroy()
- subcompositor.get_subsurface(subsurface, surface, parent)
Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3449
The previous wlr_output_cursor_set_image() allows setting a NULL buffer for the
cursor to hide it. This functionality was used by sway to hide the cursor,
restore the original semantics by allowing NULL buffers again by avoiding the
wlr_buffer allocation in case we have NULL pixels and handing a NULL wlr_buffer
to wlr_output_cursor_set_buffer().
Whether a texture is opaque or not doesn't depend on the renderer
at all, it just depends on the source buffer. Instead of forcing
all renderers to implement wlr_texture_impl.is_opaque, let's move
this in common code and use the wlr_buffer format to know whether
a texture will be opaque.
...in wlr_scene_layer_surface_v1_configure()
Reproduce bug with waybar by setting `"margin": 5,`
in ~/.config/waybar/config. It will result in the right edge of the panel
extending outside the edge of the output.
The bug can also be reproduced with gtk-layer-demo by anchoring
left/right/top/bottom and setting respective margins
Relates-to: https://github.com/labwc/labwc/issues/382
Before calling wlr_output_impl.{test,commit}, perform a cheap
comparison between the current and candidate state. Unset any
fields which didn't change.
This refactors output_ensure_buffer() to not mutate the state passed,
making the previous subtle behavior much more explicit.
Fixes: d483dd2f ("output: add wlr_output_commit_state")
Closes: #3442
Replace them with wlr_signal_emit_safe, which correctly handles
cases where a listener removes another listener.
Reported-by: Isaac Freund <ifreund@ifreund.xyz>
See the discussion at [1]: there's no easy way to fix libwayland-cursor
without a new API. Sending the error for other roles will prevent the
same client bug from appearing elsewhere.
[1]: https://gitlab.freedesktop.org/wayland/wayland/-/issues/194
This commit ensures that outputs that weren't created by the output
layout helper aren't destroyed on the output layout change.
Consider the following piece of logic:
// struct wlr_output *o1, *o2;
// struct wlr_scene *scene;
// struct wlr_output_layout *layout;
wlr_scene_attach_output_layout(scene, layout);
wlr_output_layout_add_auto(layout, o1);
struct wlr_scene_output *so2 = wlr_scene_output_create(scene, o2);
wlr_output_layout_move(layout, o1, 100, 200);
// so2 is invalid now
Since 5e0ef70cc0 ("seat: Create inert objects for missing capabilities")
wlroots can create inert seat objects when the capability is currently missing
for the client but it had the capablity before. The client hoever will happily
handover the wl_pointer resource to the relative_pointer implementation,
creating a NULL pointer dereference when trying to access the seat_client which
is set to NULL for inert objects.
Since the protocol does not contain an error for such requests, we hand out an
relative_pointer handle with the seat set to NULL.
We also need to check whether there is an associated seat in
send_relative_motion and need to tweak the destroy notifier in case no seat is
available.
This way we can hand out a valid relative_pointer resource and don't crash the
compositor when trying to access an inert seat pointer resource in
relative_pointer.
Relevant WAYLAND_DEBUG=1 when testing a client and switching VT every second:
[2619872.442] wl_seat@30.capabilities(3)
[2619872.460] -> wl_seat@30.get_pointer(new id wl_pointer@36)
[2619872.484] wl_data_device@25.selection(nil)
[2619872.504] zwp_primary_selection_device_v1@26.selection(nil)
[2619874.995] wl_seat@12.capabilities(3)
[2619875.035] -> wl_compositor@5.create_surface(new id wl_surface@37)
[2619875.088] -> wl_seat@12.get_pointer(new id wl_pointer@29)
[2619875.105] -> zwp_relative_pointer_manager_v1@8.get_relative_pointer(new id zwp_relative_pointer_v1@27, wl_pointer@29)
[2619875.127] -> wl_compositor@5.create_surface(new id wl_surface@35)
[2619875.139] -> wl_seat@12.get_pointer(new id wl_pointer@43)
[2619981.180] wl_seat@12.capabilities(2)
[2619981.214] -> zwp_relative_pointer_v1@27.destroy()
[2619981.226] -> wl_pointer@29.release()
[2619981.236] -> wl_surface@37.destroy()
[2619981.247] -> wl_pointer@43.release()
[2619981.254] -> wl_surface@35.destroy()
[2619981.262] wl_seat@12.capabilities(0)
[2619981.285] -> wl_keyboard@33.release()
[2619987.316] wl_seat@30.capabilities(2)
[2619987.336] -> wl_pointer@36.release()
[2619987.363] wl_seat@30.capabilities(0)
[2619987.371] -> wl_keyboard@34.release()
[2621932.880] wl_display@1.delete_id(41)
[2621932.903] wl_display@1.delete_id(40)
[2621932.910] wl_display@1.delete_id(27)
[2621932.917] wl_display@1.delete_id(29)
[2621932.924] wl_display@1.delete_id(37)
[2621932.930] wl_display@1.delete_id(43)
[2621932.944] wl_display@1.delete_id(35)
[2621932.950] wl_display@1.delete_id(33)
[2621932.959] wl_seat@12.capabilities(2)
[2621932.976] -> wl_seat@12.get_keyboard(new id wl_keyboard@33)
[2621936.875] wl_seat@12.capabilities(3)
[2621936.893] -> wl_compositor@5.create_surface(new id wl_surface@35)
[2621936.931] -> wl_seat@12.get_pointer(new id wl_pointer@43)
[2621936.945] -> zwp_relative_pointer_manager_v1@8.get_relative_pointer(new id zwp_relative_pointer_v1@37, wl_pointer@43)
[2621936.965] -> wl_compositor@5.create_surface(new id wl_surface@29)
[2621936.987] -> wl_seat@12.get_pointer(new id wl_pointer@27)
[2621942.796] wl_data_device@25.selection(nil)
[2621942.817] zwp_primary_selection_device_v1@26.selection(nil)
[2621942.823] wl_seat@30.capabilities(2)
[1] has changed wlr_drm_format to remove the assumption that
MOD_INVALID is always implicitly enabled. MOD_INVALID is now part
of the modifier list just like any other modifier.
The patch adding support for linux-dmabuf-v1 feedback has been
written a lot of time before [1], and hasn't been updated accordingly
when merged. This results in MOD_INVALID being advertised twice [2] and
other index bugs.
Fix these issues by removing special-casing for MOD_INVALID.
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3231
[2]: https://github.com/swaywm/sway/issues/7028
This allows the make/model/serial to be NULL when unset, and allows
them to be longer than the hardcoded array length.
This is a breaking change: compositors need to handle the new NULL
case, and we stop setting make/model to useless "headless" or
"wayland" strings.
This will display red translucent rectangles on the screen regions that
have been damaged. These rectangles will fade out over the span of 250
msecs. If the area is damaged again while the region is fading out,
the timer is reset.
Let's also disable direct scan out when this option is enabled, or else
we won't be able to render the highlight damage regions.
After cancelation we destroy the touch points associated with this
surface as the Wayland spec says:
No further events are sent to the clients from that particular gesture.
Touch cancellation applies to all touch points currently active on this
client's surface. The client is responsible for finalizing the touch
points, future touch points on this surface may re-use the touch point
ID.
Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2999
This function sidesteps damage tracking and output awareness on
buffers/surfaces. This function isn't a great fit for the API.
Let's also inline the function and simplify it.
There were a couple places this was missing
- on mode change of an output. If the resolution changes for example
nodes may fall out of the view.
- on commits on an output for scale or transform changes
- when the transform of a buffer is changed. If the dest size is not
set, the buffer may have been rotated potentially changing its size
if the buffer width != height
With protocol additions such as [1], compositors currently have no
way to opt out of the version upgrade. The protocol upgrade will
always be backwards-compatible but may require new compositor
features.
The status quo doesn't make it possible to ship a protocol addition
without breaking the wlroots API. This will be an issue for API
stabilization [2].
To address this, let compositors provide a maximum version in the
function creating the global. We need to support all previous versions
of the interface anyways because of older clients.
This mechanism works the same way as Wayland clients passing a version
in wl_global.bind.
[1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3514
[2]: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1008
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3397
There were three places initializing a token:
- wlr_xdg_activation_v1_add_token
- wlr_xdg_activation_token_v1_create
- activation_handle_get_activation_token
The initialization of the token.destroy was missing in the first one. To
prevent these functions from getting out of sync move the token creation
into a common function.
Fixes 4c59f7d4 ("xdg-activation: Allow to submit tokens")
This commit fixes a regression introduced in
511f137f8f where GTK tooltips wouldn't be
unconstrained due to no gravity on x axis being set, in which case the
behavior is ambiguous, by sliding to the right/bottom.
This fixed adaptive sync issues with wlr_scene. Scenes don't check
if the damage region intersects with an output when calling
wlr_output_damage_add.
This is especially important for multi output.
The destroy callback in wlr_touch_impl has been removed. The function
`wlr_touch_finish` has been introduced to clean up the resources owned by a
wlr_touch.
`wlr_input_device_destroy` no longer destroys the wlr_touch, attempting to
destroy a wlr_touch will result in a no-op.
The field `name` has been added to the wlr_touch_impl to be able to identify
a given wlr_touch device.
The destroy callback in wlr_tablet_tool_impl has been removed. The function
`wlr_tablet_tool_finish` has been introduced to clean up the resources owned by
a wlr_tablet_tool.
`wlr_input_device_destroy` no longer destroys the wlr_tablet_tool, attempting to
destroy a wlr_tablet_tool will result in a no-op.
The field `name` has been added to the wlr_tablet_tool_impl to be able to
identify a given wlr_tablet_tool device.
The destroy callback in wlr_tablet_pad_impl has been removed. The function
`wlr_tablet_pad_finish` has been introduced to clean up the resources owned by a
wlr_tablet_pad.
`wlr_input_device_destroy` no longer destroys the wlr_tablet_pad, attempting to
destroy a wlr_tablet_pad will result in a no-op.
The field `name` has been added to the wlr_tablet_pad_impl to be able to identify
a given wlr_tablet_pad device.
The destroy callback in wlr_switch_impl has been removed. The function
`wlr_switch_finish` has been introduced to clean up the resources owned by a
wlr_switch.
`wlr_input_device_destroy` no longer destroys the wlr_switch, attempting to
destroy a wlr_switch will result in a no-op.
The field `name` has been added to the wlr_switch_impl to be able to identify
a given wlr_switch device.
The destroy callback in wlr_pointer_impl has been removed. The function
`wlr_pointer_finish` has been introduced to clean up the resources owned by a
wlr_pointer.
`wlr_input_device_destroy` no longer destroys the wlr_pointer, attempting to
destroy a wlr_pointer will result in a no-op.
The field `name` has been added to the wlr_pointer_impl to be able to identify
a given wlr_pointer device.
The destroy member in wlr_keyboard_impl has been removed. The function
`wlr_keyboard_finish` has been introduce to clean up the resources owned by a
wlr_keyboard.
`wlr_input_device_destroy` no longer destroys the wlr_keyboard, attempting to
destroy a wlr_keyboard will result in a no-op.
The field `name` has been added to the wlr_keyboard_impl to be able to identify
a given wlr_keyboard device.
To be consistent with other wlr_xdg_* structs,
wlr_xdg_positioner_resource is renamed to wlr_xdg_positioner and made
public, and wlr_xdg_positioner is renamed to wlr_xdg_positioner_rules.
Functions which operated on wlr_xdg_positioner were renamed and updated
accordingly.
In case the `wlr_input_device` is not owned by a specialized input device, the
function will finish the wlr_input_device and call it's implementation destroy
function if an implementation has been supplied, or simply free it.
When calling wlr_output_test an empty buffer might be created. This implicitly
changes the pending state of the output. Ensure that such a change is only
temporarily and clear such an empty buffer before returning the test result.
I am running a custom compiled version of chromium with a patch to get
it up and running on sway git at the moment, and in that development
build I compiled there is a bug where the browser will crash if you
try to open a file select dialog. When this crash happens, chromium will
not close, but instead will remain open and impossible to close unless
you send a SIGKILL signal to the process. However, sway will crash to
tty when you send the SIGKILL.
I have a hunch that when chromium is opening the file select dialog
it is creating some sort of a xdg toplevel surface. But it freezes
before it fully initializes the surface. When the SIGKILL signal is
given, sway/wlroots will try to free the xdg_toplevel surface but
because it hasn't fully initialized due to the frozen window, it
segfaults.
Don't be fooled by the assert, the assert is not firing, the surface
pointer is indeed NULL here.
* thread #1, name = 'sway', stop reason = signal SIGSEGV: invalid address (fault address: 0x28)
frame #0: 0x00007ffff78b9041 libwlroots.so.11`wlr_xdg_toplevel_set_parent(surface=0x0000000000000000, parent=0x0000000000000000) at wlr_xdg_toplevel.c:159:37
156
157 void wlr_xdg_toplevel_set_parent(struct wlr_xdg_surface *surface,
158 struct wlr_xdg_surface *parent) {
-> 159 assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
160 assert(!parent || parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
161
162 if (surface->toplevel->parent) {
(lldb) up
error: sway {0x0003442a}: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x67) attribute, but range extraction failed (invalid range list offset 0x67), please file a bug and attach the file at the start of this error message
error: sway {0x0003442a}: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x67) attribute, but range extraction failed (invalid range list offset 0x67), please file a bug and attach the file at the start of this error message
frame #1: 0x00007ffff78e176e libwlroots.so.11`destroy_imported(imported=0x000055555626d570) at wlr_xdg_foreign_v1.c:154:3
151 wl_list_for_each_safe(child, child_tmp, &imported->children, link) {
152 struct wlr_xdg_surface *xdg_child =
153 wlr_xdg_surface_from_wlr_surface(child->surface);
-> 154 wlr_xdg_toplevel_set_parent(xdg_child, NULL);
155 }
156
157 wl_list_remove(&imported->exported_destroyed.link);
(lldb) up
frame #2: 0x00007ffff78e1b9d libwlroots.so.11`xdg_imported_handle_resource_destroy(resource=0x00005555562555a0) at wlr_xdg_foreign_v1.c:280:2
277 struct wl_resource *resource) {
278 struct wlr_xdg_imported_v1 *imported = xdg_imported_from_resource(resource);
279 if (!imported) {
-> 280 return;
281 }
282
283 destroy_imported(imported);
(lldb) up
frame #3: 0x00007ffff794989a libwayland-server.so.0`___lldb_unnamed_symbol211 + 154
libwayland-server.so.0`___lldb_unnamed_symbol211:
-> 0x7ffff794989a <+154>: andl $0x1, %r13d
0x7ffff794989e <+158>: je 0x7ffff79498b0 ; <+176>
0x7ffff79498a0 <+160>: addq $0x8, %rsp
0x7ffff79498a4 <+164>: movl $0x1, %eax
(lldb) up
frame #4: 0x00007ffff794fec0 libwayland-server.so.0`___lldb_unnamed_symbol290 + 64
libwayland-server.so.0`___lldb_unnamed_symbol290:
-> 0x7ffff794fec0 <+64>: cmpl $0x1, %eax
0x7ffff794fec3 <+67>: jne 0x7ffff794fed3 ; <+83>
0x7ffff794fec5 <+69>: addq $0x8, %rbx
0x7ffff794fec9 <+73>: cmpq %rbx, %r13
(lldb) up
frame #5: 0x00007ffff79503e0 libwayland-server.so.0`___lldb_unnamed_symbol300 + 32
libwayland-server.so.0`___lldb_unnamed_symbol300:
-> 0x7ffff79503e0 <+32>: cmpl $0x1, %eax
0x7ffff79503e3 <+35>: je 0x7ffff79503f0 ; <+48>
0x7ffff79503e5 <+37>: popq %rbx
0x7ffff79503e6 <+38>: popq %r12
(lldb) up
frame #6: 0x00007ffff794a30e libwayland-server.so.0`wl_client_destroy + 126
libwayland-server.so.0`wl_client_destroy:
-> 0x7ffff794a30e <+126>: movq %r12, %rdi
0x7ffff794a311 <+129>: callq 0x7ffff7950150 ; ___lldb_unnamed_symbol293
0x7ffff794a317 <+135>: movq 0x8(%rbp), %rdi
0x7ffff794a31b <+139>: callq *0xdc77(%rip)
(lldb) up
frame #7: 0x00007ffff794a3f7 libwayland-server.so.0`___lldb_unnamed_symbol214 + 119
libwayland-server.so.0`___lldb_unnamed_symbol214:
-> 0x7ffff794a3f7 <+119>: movq 0x28(%rsp), %rax
0x7ffff794a3fc <+124>: subq %fs:0x28, %rax
0x7ffff794a405 <+133>: jne 0x7ffff794a727 ; <+935>
0x7ffff794a40b <+139>: addq $0x38, %rsp
(lldb) up
frame #8: 0x00007ffff794d1ca libwayland-server.so.0`wl_event_loop_dispatch + 202
libwayland-server.so.0`wl_event_loop_dispatch:
-> 0x7ffff794d1ca <+202>: addq $0xc, %r15
0x7ffff794d1ce <+206>: cmpq %r15, %rbp
0x7ffff794d1d1 <+209>: jne 0x7ffff794d1b8 ; <+184>
0x7ffff794d1d3 <+211>: movq 0x8(%rsp), %rcx
(lldb) up
frame #9: 0x00007ffff794ad37 libwayland-server.so.0`wl_display_run + 39
libwayland-server.so.0`wl_display_run:
-> 0x7ffff794ad37 <+39>: movl 0x8(%rbx), %eax
0x7ffff794ad3a <+42>: testl %eax, %eax
0x7ffff794ad3c <+44>: jne 0x7ffff794ad20 ; <+16>
0x7ffff794ad3e <+46>: popq %rbx
(lldb) up
frame #10: 0x000055555557689a sway`server_run(server=0x00005555555f26c0) at server.c:307:2
304 wlr_backend_destroy(server->backend);
305 return false;
306 }
-> 307
308 return true;
309 }
310
(lldb) up
frame #11: 0x0000555555575a93 sway`main(argc=3, argv=0x00007fffffffe978) at main.c:431:2
428 swaynag_show(&config->swaynag_config_errors);
429 }
430
-> 431 server_run(&server);
432
433 shutdown:
434 sway_log(SWAY_INFO, "Shutting down sway");
The wlroots APIs currently don't allow importing/uploading a buffer
during rendering operations. Scene-graph buffer nodes need to turn
their wlr_buffer into a wlr_texture at some point. It's not always
possible to do so at wlr_scene_buffer creation time because the
scene-graph may have zero outputs at this point, thus no way to
grab a wlr_renderer.
Instead, add scene-graph buffers to a pending list and try to import
them in wlr_scene_output_commit.
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3354
Commit 498f30aad1 changed the logic of
get_mapping() in types/wlr_cursor.c to use updated version of
wlr_output_layout_get_box(). However, the case where c_device isn't NULL
but doesn't have output or geometry mappings wasn't handled properly,
resulting in leaving the output value uninitialized. This commit fixes
`c_device != NULL` branch by returning from the function only when a
mapping is found.
Fixes https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3369