summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPovilas Kanapickas <povilas@radix.lt>2021-12-03 02:40:59 +0200
committerPovilas Kanapickas <povilas@radix.lt>2021-12-04 15:55:21 +0000
commit0146fd6d360f26210e60f37e390de1e54f40586c (patch)
tree07fffdc0d93ea9668dfa9c9468e1a0fd910735ad
parentff2de0b87ee9ab64fe4f07d019a4386f802492ca (diff)
xwayland: Fix a race condition when setting up input devices
The compositor may send us wl_seat and its capabilities before sending e.g. relative_pointer_manager or pointer_gesture interfaces. This would result in devices being created in capabilities handler, but listeners not, because the interfaces weren't available at the time. So we manually attempt to setup listeners again. Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
-rw-r--r--hw/xwayland/xwayland-input.c76
1 files changed, 59 insertions, 17 deletions
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index db73c3528..672647f71 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -1470,6 +1470,18 @@ release_pointer(struct xwl_seat *xwl_seat)
static void
init_relative_pointer(struct xwl_seat *xwl_seat)
{
+ if (xwl_seat->relative_pointer == NULL) {
+ xwl_seat->relative_pointer =
+ add_device(xwl_seat, "xwayland-relative-pointer",
+ xwl_pointer_proc_relative);
+ ActivateDevice(xwl_seat->relative_pointer, TRUE);
+ }
+ enable_device(xwl_seat, xwl_seat->relative_pointer);
+}
+
+static void
+init_relative_pointer_listener(struct xwl_seat *xwl_seat)
+{
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager =
xwl_seat->xwl_screen->relative_pointer_manager;
@@ -1481,14 +1493,6 @@ init_relative_pointer(struct xwl_seat *xwl_seat)
&relative_pointer_listener,
xwl_seat);
}
-
- if (xwl_seat->relative_pointer == NULL) {
- xwl_seat->relative_pointer =
- add_device(xwl_seat, "xwayland-relative-pointer",
- xwl_pointer_proc_relative);
- ActivateDevice(xwl_seat->relative_pointer, TRUE);
- }
- enable_device(xwl_seat, xwl_seat->relative_pointer);
}
static void
@@ -1506,10 +1510,22 @@ release_relative_pointer(struct xwl_seat *xwl_seat)
static void
init_pointer_gestures_device(struct xwl_seat *xwl_seat)
{
+ if (xwl_seat->pointer_gestures == NULL) {
+ xwl_seat->pointer_gestures =
+ add_device(xwl_seat, "xwayland-pointer-gestures",
+ xwl_pointer_proc_pointer_gestures);
+ ActivateDevice(xwl_seat->pointer_gestures, TRUE);
+ }
+ enable_device(xwl_seat, xwl_seat->pointer_gestures);
+}
+
+static void
+init_pointer_gestures_listener(struct xwl_seat *xwl_seat)
+{
struct zwp_pointer_gestures_v1 *pointer_gestures =
xwl_seat->xwl_screen->pointer_gestures;
- if (pointer_gestures) {
+ if (pointer_gestures && !xwl_seat->wp_pointer_gesture_swipe) {
xwl_seat->wp_pointer_gesture_swipe =
zwp_pointer_gestures_v1_get_swipe_gesture(pointer_gestures,
xwl_seat->wl_pointer);
@@ -1518,7 +1534,9 @@ init_pointer_gestures_device(struct xwl_seat *xwl_seat)
zwp_pointer_gesture_swipe_v1_add_listener(xwl_seat->wp_pointer_gesture_swipe,
&pointer_gesture_swipe_listener,
xwl_seat);
+ }
+ if (pointer_gestures && !xwl_seat->wp_pointer_gesture_pinch) {
xwl_seat->wp_pointer_gesture_pinch =
zwp_pointer_gestures_v1_get_pinch_gesture(pointer_gestures,
xwl_seat->wl_pointer);
@@ -1528,14 +1546,6 @@ init_pointer_gestures_device(struct xwl_seat *xwl_seat)
&pointer_gesture_pinch_listener,
xwl_seat);
}
-
- if (xwl_seat->pointer_gestures == NULL) {
- xwl_seat->pointer_gestures =
- add_device(xwl_seat, "xwayland-pointer-gestures",
- xwl_pointer_proc_pointer_gestures);
- ActivateDevice(xwl_seat->pointer_gestures, TRUE);
- }
- enable_device(xwl_seat, xwl_seat->pointer_gestures);
}
static void
@@ -1627,7 +1637,9 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->wl_pointer == NULL) {
init_pointer(xwl_seat);
init_relative_pointer(xwl_seat);
+ init_relative_pointer_listener(xwl_seat);
init_pointer_gestures_device(xwl_seat);
+ init_pointer_gestures_listener(xwl_seat);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->wl_pointer) {
release_pointer(xwl_seat);
release_relative_pointer(xwl_seat);
@@ -2812,6 +2824,34 @@ init_keyboard_grab(struct xwl_screen *xwl_screen,
}
}
+/* The compositor may send us wl_seat and its capabilities before sending e.g.
+ relative_pointer_manager or pointer_gesture interfaces. This would result in
+ devices being created in capabilities handler, but listeners not, because
+ the interfaces weren't available at the time. So we manually attempt to setup
+ listeners again.
+*/
+static void
+maybe_init_relative_pointer_listeners_after_capabilities(struct xwl_screen* xwl_screen)
+{
+ struct xwl_seat *xwl_seat;
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ if (xwl_seat->wl_pointer) {
+ init_relative_pointer_listener(xwl_seat);
+ }
+ }
+}
+
+static void
+maybe_init_pointer_gesture_listeners_after_capabilities(struct xwl_screen* xwl_screen)
+{
+ struct xwl_seat *xwl_seat;
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ if (xwl_seat->wl_pointer) {
+ init_pointer_gestures_listener(xwl_seat);
+ }
+ }
+}
+
static void
input_handler(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
@@ -2823,10 +2863,12 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
xwl_screen->expecting_event++;
} else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
init_relative_pointer_manager(xwl_screen, id, version);
+ maybe_init_relative_pointer_listeners_after_capabilities(xwl_screen);
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
init_pointer_constraints(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_pointer_gestures_v1") == 0) {
init_pointer_gestures(xwl_screen, id, version);
+ maybe_init_pointer_gesture_listeners_after_capabilities(xwl_screen);
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
init_tablet_manager(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_xwayland_keyboard_grab_manager_v1") == 0) {