summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergio Gómez <sergio.g.delreal@gmail.com>2023-03-08 17:39:49 -0500
committerMarius Vlad <marius.vlad@collabora.com>2023-05-16 10:54:29 +0300
commit21e46364c0813f80bf6992d929339cdcbdaf5171 (patch)
tree8818b2e4b22869fb3d6778b599bc5375beb9e961
parent0bd68d9ad6b4e8b860e638ffb82abf2eeb2edd15 (diff)
downloadweston-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.h2
-rw-r--r--libweston/compositor.c31
-rw-r--r--libweston/input.c16
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 =