libweston: Make weston_seat release safe
Ensure the server can safely handle client requests for wl_seat resource
that have become inert due to weston_seat object release and subsequent
destruction.
The clean-up involves, among other things, unsetting the destroyed
weston_seat object from the user data of wl_seat resources, and handling
this NULL user data case where required.
The list of sites extracting and using weston_seat object from wl_seat
resources which were audited for this patch are:
Legend:
N/A = Not Applicable (not implemented by weston)
FIXED = Fixed in the commit
OK = Already works correctly
== keyboard_shortcuts_inhibit_unstable_v1 ==
[N/A] zwp_keyboard_shortcuts_inhibit_manager_v1.inhibit_shortcuts
== tablet_input_unstable_v{1,2} ==
[N/A] zwp_tablet_manager_v{1,2}.get_tablet_seat
== text_input_unstable_v1 ==
[FIXED] zwp_text_input_v1.activate
[FIXED] zwp_text_input_v1.deactivate
== wl_data_device ==
[FIXED] wl_data_device_manager.get_data_device
[OK] wl_data_device.start_drag
[FIXED] wl_data_device.set_selection
[OK] wl_data_device.release
== wl_shell ==
[FIXED] wl_shell_surface.move
[FIXED] wl_shell_surface.resize
[FIXED] wl_shell_surface.set_popup
== xdg_shell and xdg_shell_unstable_v6 ==
[FIXED] xdg_toplevel.show_window_menu
[FIXED] xdg_toplevel.move
[FIXED] xdg_toplevel.resize
[FIXED] xdg_popup.grab
== xdg_shell_unstable_v5 ==
[FIXED] xdg_shell.get_xdg_popup
[FIXED] xdg_surface.show_window_menu
[FIXED] xdg_surface.move
[FIXED] xdg_surface.resize
Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
committed by
Pekka Paalanen
parent
1c3a40edcd
commit
8480d13f6d
@@ -242,6 +242,9 @@ weston_desktop_seat_from_seat(struct weston_seat *wseat)
|
||||
struct wl_listener *listener;
|
||||
struct weston_desktop_seat *seat;
|
||||
|
||||
if (wseat == NULL)
|
||||
return NULL;
|
||||
|
||||
listener = wl_signal_get(&wseat->destroy_signal,
|
||||
weston_desktop_seat_destroy);
|
||||
if (listener != NULL)
|
||||
@@ -270,7 +273,7 @@ weston_desktop_seat_from_seat(struct weston_seat *wseat)
|
||||
struct weston_desktop_surface *
|
||||
weston_desktop_seat_popup_grab_get_topmost_surface(struct weston_desktop_seat *seat)
|
||||
{
|
||||
if (wl_list_empty(&seat->popup_grab.surfaces))
|
||||
if (seat == NULL || wl_list_empty(&seat->popup_grab.surfaces))
|
||||
return NULL;
|
||||
|
||||
struct wl_list *grab_link = seat->popup_grab.surfaces.next;
|
||||
@@ -282,11 +285,14 @@ bool
|
||||
weston_desktop_seat_popup_grab_start(struct weston_desktop_seat *seat,
|
||||
struct wl_client *client, uint32_t serial)
|
||||
{
|
||||
assert(seat->popup_grab.client == NULL || seat->popup_grab.client == client);
|
||||
assert(seat == NULL || seat->popup_grab.client == NULL ||
|
||||
seat->popup_grab.client == client);
|
||||
|
||||
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat->seat);
|
||||
struct weston_pointer *pointer = weston_seat_get_pointer(seat->seat);
|
||||
struct weston_touch *touch = weston_seat_get_touch(seat->seat);
|
||||
struct weston_seat *wseat = seat != NULL ? seat->seat : NULL;
|
||||
/* weston_seat_get_* functions can properly handle a NULL wseat */
|
||||
struct weston_keyboard *keyboard = weston_seat_get_keyboard(wseat);
|
||||
struct weston_pointer *pointer = weston_seat_get_pointer(wseat);
|
||||
struct weston_touch *touch = weston_seat_get_touch(wseat);
|
||||
|
||||
if ((keyboard == NULL || keyboard->grab_serial != serial) &&
|
||||
(pointer == NULL || pointer->grab_serial != serial) &&
|
||||
|
||||
@@ -220,6 +220,9 @@ weston_desktop_wl_shell_surface_protocol_move(struct wl_client *wl_client,
|
||||
struct weston_desktop_wl_shell_surface *surface =
|
||||
weston_desktop_surface_get_implementation_data(dsurface);
|
||||
|
||||
if (seat == NULL)
|
||||
return;
|
||||
|
||||
weston_desktop_api_move(surface->desktop, dsurface, seat, serial);
|
||||
}
|
||||
|
||||
@@ -238,6 +241,9 @@ weston_desktop_wl_shell_surface_protocol_resize(struct wl_client *wl_client,
|
||||
enum weston_desktop_surface_edge surf_edges =
|
||||
(enum weston_desktop_surface_edge) edges;
|
||||
|
||||
if (seat == NULL)
|
||||
return;
|
||||
|
||||
weston_desktop_api_resize(surface->desktop, dsurface, seat, serial, surf_edges);
|
||||
}
|
||||
|
||||
@@ -328,7 +334,8 @@ weston_desktop_wl_shell_surface_protocol_set_popup(struct wl_client *wl_client,
|
||||
struct weston_desktop_wl_shell_surface *surface =
|
||||
weston_desktop_surface_get_implementation_data(dsurface);
|
||||
|
||||
if (seat == NULL) {
|
||||
/* Check that if we have a valid wseat we also got a valid desktop seat */
|
||||
if (wseat != NULL && seat == NULL) {
|
||||
wl_client_post_no_memory(wl_client);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -378,6 +378,9 @@ weston_desktop_xdg_toplevel_protocol_show_window_menu(struct wl_client *wl_clien
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat == NULL)
|
||||
return;
|
||||
|
||||
weston_desktop_api_show_window_menu(toplevel->base.desktop,
|
||||
dsurface, seat, x, y);
|
||||
}
|
||||
@@ -402,6 +405,9 @@ weston_desktop_xdg_toplevel_protocol_move(struct wl_client *wl_client,
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat == NULL)
|
||||
return;
|
||||
|
||||
weston_desktop_api_move(toplevel->base.desktop, dsurface, seat, serial);
|
||||
}
|
||||
|
||||
@@ -428,6 +434,9 @@ weston_desktop_xdg_toplevel_protocol_resize(struct wl_client *wl_client,
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat == NULL)
|
||||
return;
|
||||
|
||||
weston_desktop_api_resize(toplevel->base.desktop,
|
||||
dsurface, seat, serial, surf_edges);
|
||||
}
|
||||
@@ -762,6 +771,12 @@ weston_desktop_xdg_popup_protocol_grab(struct wl_client *wl_client,
|
||||
bool parent_is_toplevel =
|
||||
popup->parent->role == WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL;
|
||||
|
||||
/* Check that if we have a valid wseat we also got a valid desktop seat */
|
||||
if (wseat != NULL && seat == NULL) {
|
||||
wl_client_post_no_memory(wl_client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (popup->committed) {
|
||||
wl_resource_post_error(popup->resource,
|
||||
ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
|
||||
@@ -769,6 +784,15 @@ weston_desktop_xdg_popup_protocol_grab(struct wl_client *wl_client,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If seat is NULL then get_topmost_surface will return NULL. In
|
||||
* combination with setting parent_is_toplevel to TRUE here we will
|
||||
* avoid posting an error, and we will instead gracefully fail the
|
||||
* grab and dismiss the surface.
|
||||
* FIXME: this is a hack because currently we cannot check the topmost
|
||||
* parent with a destroyed weston_seat */
|
||||
if (seat == NULL)
|
||||
parent_is_toplevel = true;
|
||||
|
||||
topmost = weston_desktop_seat_popup_grab_get_topmost_surface(seat);
|
||||
if ((topmost == NULL && !parent_is_toplevel) ||
|
||||
(topmost != NULL && topmost != popup->parent->desktop_surface)) {
|
||||
|
||||
Reference in New Issue
Block a user