diff options
author | Sergio Gómez <sergio.g.delreal@gmail.com> | 2023-03-08 17:39:49 -0500 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2023-05-16 10:54:29 +0300 |
commit | 21e46364c0813f80bf6992d929339cdcbdaf5171 (patch) | |
tree | 8818b2e4b22869fb3d6778b599bc5375beb9e961 | |
parent | 0bd68d9ad6b4e8b860e638ffb82abf2eeb2edd15 (diff) | |
download | weston-21e46364c0813f80bf6992d929339cdcbdaf5171.tar.gz |
libweston: Add view unmap listener to pointer constraints
Since the logic of pointer constraints assumes a valid view throughout, add a
signal to disable constraints when its current view is unmapped by Weston.
The assumption that a previously unmapped view is valid already leads to the
constraints code crashing. This can happen when attaching a NULL buffer to the
surface and commiting, which effectively unmaps the view with the side effect of
clearing the surface's input region, which is then assumed valid inside
maybe_warp_confined_pointer().
Fixes: #721
Signed-off-by: Sergio Gómez <sergio.g.delreal@gmail.com>
(cherry picked from commit e3079393c400e3dc6498234d1d092f3072fa8b44)
-rw-r--r-- | include/libweston/libweston.h | 2 | ||||
-rw-r--r-- | libweston/compositor.c | 31 | ||||
-rw-r--r-- | libweston/input.c | 16 |
3 files changed, 34 insertions, 15 deletions
diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index eb3c487c..4bb9ea75 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -1452,6 +1452,7 @@ struct weston_view { struct weston_surface *surface; struct wl_list surface_link; struct wl_signal destroy_signal; + struct wl_signal unmap_signal; /* struct weston_paint_node::view_link */ struct wl_list paint_node_list; @@ -1605,6 +1606,7 @@ struct weston_pointer_constraint { bool hint_is_pending; struct wl_listener pointer_destroy_listener; + struct wl_listener view_unmap_listener; struct wl_listener surface_commit_listener; struct wl_listener surface_activate_listener; }; diff --git a/libweston/compositor.c b/libweston/compositor.c index 428e4b5e..b6c16d6f 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -396,6 +396,7 @@ weston_view_create(struct weston_surface *surface) wl_list_insert(&surface->views, &view->surface_link); wl_signal_init(&view->destroy_signal); + wl_signal_init(&view->unmap_signal); wl_list_init(&view->link); wl_list_init(&view->layer_link.link); wl_list_init(&view->paint_node_list); @@ -2248,22 +2249,22 @@ weston_view_unmap(struct weston_view *view) view->output_mask = 0; weston_surface_assign_output(view->surface); - if (weston_surface_is_mapped(view->surface)) - return; - - wl_list_for_each(seat, &view->surface->compositor->seat_list, link) { - struct weston_touch *touch = weston_seat_get_touch(seat); - struct weston_pointer *pointer = weston_seat_get_pointer(seat); - struct weston_keyboard *keyboard = - weston_seat_get_keyboard(seat); - - if (keyboard && keyboard->focus == view->surface) - weston_keyboard_set_focus(keyboard, NULL); - if (pointer && pointer->focus == view) - weston_pointer_clear_focus(pointer); - if (touch && touch->focus == view) - weston_touch_set_focus(touch, NULL); + if (!weston_surface_is_mapped(view->surface)) { + wl_list_for_each(seat, &view->surface->compositor->seat_list, link) { + struct weston_touch *touch = weston_seat_get_touch(seat); + struct weston_pointer *pointer = weston_seat_get_pointer(seat); + struct weston_keyboard *keyboard = + weston_seat_get_keyboard(seat); + + if (keyboard && keyboard->focus == view->surface) + weston_keyboard_set_focus(keyboard, NULL); + if (pointer && pointer->focus == view) + weston_pointer_clear_focus(pointer); + if (touch && touch->focus == view) + weston_touch_set_focus(touch, NULL); + } } + weston_signal_emit_mutable(&view->unmap_signal, view); } WL_EXPORT void diff --git a/libweston/input.c b/libweston/input.c index db029580..f2a9a07a 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -3713,6 +3713,8 @@ enable_pointer_constraint(struct weston_pointer_constraint *constraint, constraint->view = view; pointer_constraint_notify_activated(constraint); weston_pointer_start_grab(constraint->pointer, &constraint->grab); + wl_signal_add(&constraint->view->unmap_signal, + &constraint->view_unmap_listener); } static bool @@ -3727,6 +3729,8 @@ weston_pointer_constraint_disable(struct weston_pointer_constraint *constraint) constraint->view = NULL; pointer_constraint_notify_deactivated(constraint); weston_pointer_end_grab(constraint->grab.pointer); + wl_list_remove(&constraint->view_unmap_listener.link); + wl_list_init(&constraint->view_unmap_listener.link); } void @@ -3932,6 +3936,16 @@ pointer_constraint_pointer_destroyed(struct wl_listener *listener, void *data) } static void +pointer_constraint_view_unmapped(struct wl_listener *listener, void *data) +{ + struct weston_pointer_constraint *constraint = + container_of(listener, struct weston_pointer_constraint, + view_unmap_listener); + + disable_pointer_constraint(constraint); +} + +static void pointer_constraint_surface_committed(struct wl_listener *listener, void *data) { struct weston_pointer_constraint *constraint = @@ -3992,6 +4006,8 @@ weston_pointer_constraint_create(struct weston_surface *surface, constraint->surface_activate_listener.notify = pointer_constraint_surface_activate; + constraint->view_unmap_listener.notify = + pointer_constraint_view_unmapped; constraint->surface_commit_listener.notify = pointer_constraint_surface_committed; constraint->pointer_destroy_listener.notify = |