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
wl_subsurface::set_desync description states: "If cached state exists when
wl_surface.commit is called in desynchronized mode, the pending state is
added to the cached state, and applied as a whole."
This commit reintroduces an implementation of said behavior, previously
removed in 7daf6da9ac05be2cb74c0983e3caee0b21db75d4.
Strictly speaking, this logic isn't fully correct, as the cached state
and the pending state are applied individually instead, if the cached
state isn't locked by anything else. However, the end result is still
the same.
This commit fixes the issue with Firefox permission popups.
wp_viewporter protocol doesn't seem to say anything about damage, but
Firefox assumes that wp_viewport::set_source alone is enough to damage
the whole surface, and that assumption kinda makes sense, so let's do
that.
Currently the output enter event is never sent if the client has not
yet bound the output, which happens every time the compositor creates a
new output.
To fix this, listen for the output bind event and inform clients as
if needed.
This commit renames map/unmap listeners to clarify that they handle
subsurface events, and ensures the node is always destroyed before
the subsurface.
Without this patch, wl_list_remove() would operate on listener links in
already freed memory. glibc is usually lenient to bugs like this, but
musl isn't.
Allows the compositor to submit tokens to the pool of
currently active tokens. This can be useful when the
launcher doesn't use or support xdg-activation-v1 by
itself - e.g. when it is X11 based or use gtk_shell1.
This doesn't work if scene outputs are not used as the primary output of
scene surfaces will always be NULL.
Therefore, take a wlr_scene_output instead of separate wlr_scene and
wlr_output arguments and rename the function to
wlr_scene_output_send_frame_done().
The actual behavior of the function is unchanged.
This allows compositors to avoid sending multiple frame done events
to a surface that is rendered on multiple outputs at once. This may
also be used in the same way for presentation feedback.
wlroots picks names for all outputs, but it might be desirable for
compositor to override it.
For instance, Sway will use a headless output as a fallback in
case no outputs are connected. Sway wants to clearly label the
fallback output as such and label "real" headless outputs starting
from HEADLESS-1.
Implement a basic version of linux-dmabuf-unstable-v1 version 4.
Only default hints are implemented.
The new wlr_linux_dmabuf_feedback_v1 data structure will allow
compositors to define their own custom hints in the future. This
data structure makes it easy to describe feedback metadata.
It's converted to a "compiled" form suitable for marshalling over
the Wayland socket via feedback_compile.
This allows output commit listeners to access the newly committed
buffer. Currently wlr_output.front_buffer is used but it'll get
removed in the next commit.
DRM formats with an empty modifier list are invalid. Instead of
emptying the list, reduce it to { INVALID }.
Add a check to make sure the renderer and backend support implicit
modifiers, so that we don't fallback on e.g. Vulkan.
Closes: https://github.com/swaywm/sway/issues/6692
This allows getting a wlr_scene_output from a wlr_output. Since an
output can only be added once to a scene-graph there's no ambiguity.
This is useful for compositors using wlr_scene_attach_output_layout:
the output layout integration automatically creates a scene-graph
output for each wlr_output added to the layout.
This allows compositors to get primary formats without manually
calling wlr_output_impl.get_primary_formats.
For example, the Sway patch for linux-dmabuf feedback [1] needs
this.
[1]: https://github.com/swaywm/sway/pull/6313
Sometimes we were calling wlr_output_impl.set_cursor with a NULL
buffer, but we weren't clearing wlr_output.cursor_front_buffer.
Avoid leaving a dangling buffer behind.
Introduce a helper function output_set_hardware_cursor which calls
wlr_output_impl.set_cursor and keeps cursor_front_buffer in sync.
The implicit check to filter out LINEAR for dmabuf checked for INVALID
twice instead of checking for INVALID & LINEAR. Fix this.
Fixes: d37eb5c2ea ("linux-dmabuf-v1: filter out LINEAR if implicit")
Reported-by: Dawid Czeluśniak <czelusniakdawid@gmail.com>
If only INVALID and LINEAR are valid modifiers, we need to filter out
LINEAR since Xwayland won't be able to allocate a BO with the explicit
linear modifier on hardware that does not support explicit modifiers.
The addition of LINEAR is an internal implementation detail which
simplifies the wlroots architecture for now.
Evntually Xwayland should be fixed to filter out modifiers that are not
supported by the GBM implementation, see [1]. This could be done by
querying EGL for the supported modifiers.
[1]: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1166
This allows compositors to easily add an xdg_surface to the
scene-graph while retaining the ability to unconstraint popups
and decide their final position.
Compositors can handle new popups with the wlr_xdg_shell.new_surface
event, get the parent scene-graph node via wlr_xdg_popup.parent.data,
create a new scene-graph node via wlr_scene_xdg_surface_tree_create,
and unconstraint the popup if they want to.
The parameters are used when the client is in the process of
building a buffer. There's no reason why this internal
implementation detail should be exposed in our public header.
All graphics drivers supporting cursor planes support ARGB8888,
the default cursor format, so this fallback is almost certainly
unused.
Essentially all cursor themes use alpha transparency to make it
clearer where relative to the screen content the cursor hotspot is.
It is better to fall back to a slightly slower software cursor than
it is to fall back to the opaque square that is a hardware cursor
without an alpha channel.
This change introduces new double buffered state to the wlr_output,
corresponding to the buffer format to render to.
The format being rendered to does not control the bit depth of colors
being sent to the display; it does generally determine the format with
which screenshot data is provided. The DRM backend _may_ sent higher
bit depths if the render format depth is increased, but hardware and
other limitations may apply.
Most (and possibly all) compositors using wlroots only ever render
fully opaque content. To provide better performance, this change
switches the default format used by wlr_output buffers from
ARGB8888 to the opaque XRGB8888.
Compositors like mutter, kwin, and weston already default to
XRGB8888, so this change is unlikely to expose any new bugs in
underlying drivers and hardware.
This does not affect the hardware cursor's buffer format, which is
still ARGB8888 by default.
As part of this change, the X11 backend (which does not support
changing format at runtime) now picks a true color, 24 bit depth
visual (i.e. XRGB8888) instead of a 32 bit depth (ARGB8888) one.
This makes it possible for the two functions using output_pick_format
(output_pick_cursor_format and output_create_swapchain) to select
different buffer formats.
The backend and renderer don't directly interact together, so there's
no point in checking that their buffer caps intersect. What we want to
check is that:
- The backend and allocator buffer caps are compatible, because the
backend consumes buffers to display them.
- The renderer and allocator buffer caps are compatible, because the
renderer imports buffers to sample them or render to them.
For instance, when running with the DRM backend and the Pixman renderer,
the (backend & renderer) check will fail because backend = DMABUF and
renderer = DATA_PTR.
They are never used in practice, which makes all of our flag
handling effectively dead code. Also, APIs such as KMS don't
provide a good way to deal with the flags. Let's just fail the
DMA-BUF import when clients provide flags.
We were send a protocol error if INTERLACED or BOTTOM_FIRST was
set. This is incorrect for the zwp_linux_dmabuf_params.create
code-path because this kills the client without allowing it to
gracefully handle the error.
We should only send a protocol error if the client provides a bit
not listed in the protocol definition.
The protocol uses a signed integer here, which is also what the
wlr_input_method_v2_preedit_string struct provides to compositors from
the input method protocol. Sway currently just passes those int32_t
values directly to this function leading to an implicit conversion.
The data field is useful to track metadata about a token. The destroy
events are useful for compositors that track application startup to
let them know they can stop doing that.
These new functions allow a compositor to request new managed tokens
without participating in the xdg-activation procedure as a wayland
client.
This enables the compositor itself to behave as a launcher
application.
Variables on the stack are released when the parent block is closed.
Here, `now` is used outside of the `if` block, causing the following
crash when starting Sway with the headless backend:
==49606==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fff94645f90 at pc 0x5558aeae9e29 bp 0x7fff94645df0 sp 0x7fff94645de0
READ of size 16 at 0x7fff94645f90 thread T0
#0 0x5558aeae9e28 in handle_present ../sway/desktop/output.c:834
#1 0x7fdc8d6792fb in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#2 0x7fdc8d54f77f in wlr_output_send_present ../subprojects/wlroots/types/output/output.c:766
#3 0x7fdc8d524a28 in output_commit ../subprojects/wlroots/backend/headless/output.c:71
#4 0x7fdc8d54d2db in wlr_output_commit ../subprojects/wlroots/types/output/output.c:629
#5 0x5558aeb013cb in output_render ../sway/desktop/render.c:1157
#6 0x5558aeae549e in output_repaint_timer_handler ../sway/desktop/output.c:544
#7 0x5558aeae5f8a in damage_handle_frame ../sway/desktop/output.c:606
#8 0x7fdc8d6792fb in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#9 0x7fdc8d6007d5 in output_handle_frame ../subprojects/wlroots/types/wlr_output_damage.c:44
#10 0x7fdc8d6792fb in wlr_signal_emit_safe ../subprojects/wlroots/util/signal.c:29
#11 0x7fdc8d54ee84 in wlr_output_send_frame ../subprojects/wlroots/types/output/output.c:720
#12 0x7fdc8d54efc3 in schedule_frame_handle_idle_timer ../subprojects/wlroots/types/output/output.c:728
#13 0x7fdc8c9dcf5a in wl_event_loop_dispatch_idle (/usr/lib/libwayland-server.so.0+0xaf5a)
#14 0x7fdc8c9dcfb4 in wl_event_loop_dispatch (/usr/lib/libwayland-server.so.0+0xafb4)
#15 0x7fdc8c9dabc6 in wl_display_run (/usr/lib/libwayland-server.so.0+0x8bc6)
#16 0x5558aeac8e30 in server_run ../sway/server.c:285
#17 0x5558aeac3c7d in main ../sway/main.c:396
#18 0x7fdc8be35b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
#19 0x5558aea8686d in _start (/home/simon/src/sway/build/sway/sway+0x33f86d)
If the output is destroyed after capture_output but before
frame_handle_copy, it'll have a dangling output pointer. Add the
output destroy listener in capture_output.
Closes: https://github.com/swaywm/wlroots/issues/3284
This is only called from one function.
To destroy the wlr_scene_subsurface_tree from elsewhere, callers
can destroy the scene-graph node returned by
wlr_scene_subsurface_tree_create instead (just like a compositor
would do). subsurface_tree_handle_surface_destroy does exactly this.
Inlining avoids calling subsurface_tree_destroy by mistake.
This organizes the wlr_output implementation into separate files.
This avoids having a single mega-file with lots of unrelated parts
and makes it more obvious what the interactions between all the
parts are.
No functional changes, just moving code around.
Currently these functions remove the node from the scene if the sibling
argument is the same node as the node. To prevent confusion when
misusing this API, assert that the nodes are distinct and document this.
These functions are used mostly for rendering, where including unmapped
surfaces is undesired.
This is a breaking change. However, few to no usages will have to be
updated.
struct wlr_xdg_surface_state is introduced to hold the geometry
and configure serial to be applied on next wl_surface.commit.
This commit fixes our handling for ack_configure: instead of making
the request mutate our current state, it mutates the pending state
only.
Co-authored-by: Simon Ser <contact@emersion.fr>
As touchpad touches are generally fully abstracted, a client cannot
currently know when a user is interacting with the touchpad without
moving. This is solved by hold gestures.
Hold gestures are notifications about one or more fingers being held
down on the touchpad without significant movement.
Hold gestures are primarily designed for two interactions:
- Hold to interact: where a hold gesture is active for some time a
menu could pop up, some object could be selected, etc.
- Hold to cancel: where e.g. kinetic scrolling is currently active,
the start of a hold gesture can be used to stop the scroll.
Unlike swipe and pinch, hold gestures, by definition, do not have
movement, so there is no need for an "update" stage in the gesture.
Create two structs, wlr_event_pointer_hold_begin and
wlr_event_pointer_hold_end, to represent hold gesture events and the
signals to emit them: wlr_pointer->pointer.hold_begin/hold_end.
This allows the compiler to error out if we haven't enumerated all
of the cases. This is useful to avoid a missing implementation when
adding a new node type.
This commit removes any checks whether a configure will change anything
and makes configures be sent unconditionally. Additionally, configures
are scheduled on xdg_toplevel.{un,}set_{maximized,fullscreen} events.
Previously, `wlr_xdg_toplevel` didn't follow the usual "current state +
pending state" pattern and instead had confusingly named
`client_pending` and `server_pending`. This commit removes them, and
instead introduces `wlr_xdg_toplevel.scheduled` to store the properties
that are yet to be sent to a client, and `wlr_xdg_toplevel.requested`
to store the properties that a client has requested. They have different
types to emphasize that they aren't actual states.
This allows callers to specify the operations they'll perform on
the returned data pointer. The motivations for this are:
- The upcoming Linux MAP_NOSIGBUS flag may only be usable on
read-only mappings.
- gbm_bo_map with GBM_BO_TRANSFER_READ hurts performance.
This will allow more scene-graph extensions to be added without
cluttering wlr_scene.c, for instance for sub-surface handling and
wlr_output_layout integration.