SDL: wayland: Handle the relative pointer manager appearing after the seat has been initialized

From 7c8171da92f400109447724c4fe0bad4fed4544f Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Thu, 19 Dec 2024 14:26:51 -0500
Subject: [PATCH] wayland: Handle the relative pointer manager appearing after
 the seat has been initialized

---
 src/video/wayland/SDL_waylandevents.c   | 23 +++++++++++++++++------
 src/video/wayland/SDL_waylandevents_c.h |  1 +
 src/video/wayland/SDL_waylandvideo.c    |  1 +
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 518c85bb0bbc2..a87913d59141c 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -1944,6 +1944,22 @@ static const struct wl_keyboard_listener keyboard_listener = {
     keyboard_handle_repeat_info, // Version 4
 };
 
+void Wayland_input_init_relative_pointer(SDL_VideoData *d)
+{
+    struct SDL_WaylandInput *input = d->input;
+
+    if (!d->relative_pointer_manager) {
+        return;
+    }
+
+    if (input->pointer && !input->relative_pointer) {
+        input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(input->display->relative_pointer_manager, input->pointer);
+        zwp_relative_pointer_v1_add_listener(input->relative_pointer,
+                                             &relative_pointer_listener,
+                                             input);
+    }
+}
+
 static void seat_handle_capabilities(void *data, struct wl_seat *seat,
                                      enum wl_seat_capability caps)
 {
@@ -1959,12 +1975,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat,
         wl_pointer_set_user_data(input->pointer, input);
         wl_pointer_add_listener(input->pointer, &pointer_listener, input);
 
-        if (input->display->relative_pointer_manager) {
-            input->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(input->display->relative_pointer_manager, input->pointer);
-            zwp_relative_pointer_v1_add_listener(input->relative_pointer,
-                                                 &relative_pointer_listener,
-                                                 input);
-        }
+        Wayland_input_init_relative_pointer(input->display);
 
         input->pointer_id = SDL_GetNextObjectID();
         SDL_AddMouse(input->pointer_id, WAYLAND_DEFAULT_POINTER_NAME, true);
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index b67e7e3918a6d..f101baa0cb632 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -162,6 +162,7 @@ extern void Wayland_create_text_input(SDL_VideoData *d);
 extern void Wayland_input_initialize_seat(SDL_VideoData *d);
 extern void Wayland_display_destroy_input(SDL_VideoData *d);
 
+extern void Wayland_input_init_relative_pointer(SDL_VideoData *d);
 extern bool Wayland_input_enable_relative_pointer(struct SDL_WaylandInput *input);
 extern bool Wayland_input_disable_relative_pointer(struct SDL_WaylandInput *input);
 
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index b778f9b29d0e2..14f16a7e08000 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -1224,6 +1224,7 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
         d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
     } else if (SDL_strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
         d->relative_pointer_manager = wl_registry_bind(d->registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
+        Wayland_input_init_relative_pointer(d);
     } else if (SDL_strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
         d->pointer_constraints = wl_registry_bind(d->registry, id, &zwp_pointer_constraints_v1_interface, 1);
     } else if (SDL_strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) {