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)
Some globals are static and it doesn't make sense to destroy them before
the wl_display. For instance, wl_compositor should be created before the
display is started and shouldn't be destroyed.
For these globals, we can simplify the code by removing the destructor
and stop keeping track of wl_resources (these will be destroyed with the
wl_display by libwayland).
The documentation for wayland-server.h says:
> Use of this header file is discouraged. Prefer including
> wayland-server-core.h instead, which does not include the server protocol
> header and as such only defines the library PI, excluding the deprecated API
> below.
Replacing wayland-server.h with wayland-server-core.h allows us to drop the
WL_HIDE_DEPRECATED declaration.
Frame events group logically connected pointer events. It makes sense to make
the backend responsible for sending frame events, since once the events are
split (ie. once the frame events are stripped) it's not easy to figure out
which events belongs to which frame again.
This is also how Weston handles frame events.
Fixes https://github.com/swaywm/wlroots/issues/1468
Fixes a crash in SDL2 applications when using locked pointer.
SDL2 expects a wl_pointer v1 interface and doesn't provide a handler for
the wl_pointer::frame event. This results in a "listener function for
opcode 5 of wl_pointer is NULL" abort in wayland-client.
Tested on Xonotic v0.8.2 with libSDL2 v2.0.9. Xonotic needs to be ran
with "SDL_VIDEODRIVER=wayland xonotic-sdl" for SDL2 to use the wayland
backend.
Occurs on subsequent calls to
relative_pointer_manager_v1_handle_get_relative_pointer()
Steps to reproduce:
- run rootston
- run examples/relative-pointer
- switch to relative pointer more than once
Note: if done fast enough it may take more than two switches to crash.
In particular, modified public creator and destructor function names,
added a display destroy listener, safely extract user data from
resources, send correct time (in usecs) in rootston, etc.