فهرست منبع

wayland: Always create the backing input store, even if there is no seat

Fixes a crash if no seat was available at initialization, but still allows for one to still be created later if an input device is added.

Removes some unnecessary abstractions in the process.
Frank Praznik 1 سال پیش
والد
کامیت
84e47b4af5
3فایلهای تغییر یافته به همراه58 افزوده شده و 69 حذف شده
  1. 21 58
      src/video/wayland/SDL_waylandevents.c
  2. 4 4
      src/video/wayland/SDL_waylandevents_c.h
  3. 33 7
      src/video/wayland/SDL_waylandvideo.c

+ 21 - 58
src/video/wayland/SDL_waylandevents.c

@@ -64,15 +64,6 @@
 #include "../../events/imKStoUCS.h"
 #include "../../events/SDL_keysym_to_scancode_c.h"
 
-/* Clamp the wl_seat version on older versions of libwayland. */
-#if SDL_WAYLAND_CHECK_VERSION(1, 22, 0)
-#define SDL_WL_SEAT_VERSION 9
-#elif SDL_WAYLAND_CHECK_VERSION(1, 21, 0)
-#define SDL_WL_SEAT_VERSION 8
-#else
-#define SDL_WL_SEAT_VERSION 5
-#endif
-
 /* Weston uses a ratio of 10 units per scroll tick */
 #define WAYLAND_WHEEL_AXIS_UNIT 10
 
@@ -2305,10 +2296,15 @@ static const struct zwp_text_input_v3_listener text_input_listener = {
     text_input_done
 };
 
-static void Wayland_create_data_device(SDL_VideoData *d)
+void Wayland_create_data_device(SDL_VideoData *d)
 {
     SDL_WaylandDataDevice *data_device = NULL;
 
+    if (!d->input->seat) {
+        /* No seat yet, will be initialized later. */
+        return;
+    }
+
     data_device = SDL_calloc(1, sizeof(*data_device));
     if (!data_device) {
         return;
@@ -2328,10 +2324,15 @@ static void Wayland_create_data_device(SDL_VideoData *d)
     }
 }
 
-static void Wayland_create_primary_selection_device(SDL_VideoData *d)
+void Wayland_create_primary_selection_device(SDL_VideoData *d)
 {
     SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
 
+    if (!d->input->seat) {
+        /* No seat yet, will be initialized later. */
+        return;
+    }
+
     primary_selection_device = SDL_calloc(1, sizeof(*primary_selection_device));
     if (!primary_selection_device) {
         return;
@@ -2352,10 +2353,15 @@ static void Wayland_create_primary_selection_device(SDL_VideoData *d)
     }
 }
 
-static void Wayland_create_text_input(SDL_VideoData *d)
+void Wayland_create_text_input(SDL_VideoData *d)
 {
     SDL_WaylandTextInput *text_input = NULL;
 
+    if (!d->input->seat) {
+        /* No seat yet, will be initialized later. */
+        return;
+    }
+
     text_input = SDL_calloc(1, sizeof(*text_input));
     if (!text_input) {
         return;
@@ -2374,33 +2380,6 @@ static void Wayland_create_text_input(SDL_VideoData *d)
     }
 }
 
-void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
-{
-    d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version));
-
-    if (d->input) {
-        Wayland_create_data_device(d);
-    }
-}
-
-void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
-{
-    d->primary_selection_device_manager = wl_registry_bind(d->registry, id, &zwp_primary_selection_device_manager_v1_interface, 1);
-
-    if (d->input) {
-        Wayland_create_primary_selection_device(d);
-    }
-}
-
-void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
-{
-    d->text_input_manager = wl_registry_bind(d->registry, id, &zwp_text_input_manager_v3_interface, 1);
-
-    if (d->input) {
-        Wayland_create_text_input(d);
-    }
-}
-
 static SDL_PenID Wayland_get_penid(void *data, struct zwp_tablet_tool_v2 *tool)
 {
     struct SDL_WaylandTool *sdltool = data;
@@ -2939,7 +2918,7 @@ void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_Wayland
     struct SDL_WaylandTabletInput *tablet_input;
     static Uint32 num_tablets = 0;
 
-    if (!tablet_manager || !input || !input->seat) {
+    if (!tablet_manager || !input->seat) {
         return;
     }
 
@@ -2974,24 +2953,12 @@ void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input)
     input->tablet = NULL;
 }
 
-void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
+void Wayland_input_initialize_seat(SDL_VideoData *d)
 {
-    struct SDL_WaylandInput *input;
-
-    input = SDL_calloc(1, sizeof(*input));
-    if (!input) {
-        return;
-    }
+    struct SDL_WaylandInput *input = d->input;
 
     WAYLAND_wl_list_init(&touch_points);
 
-    input->display = d;
-    input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(SDL_WL_SEAT_VERSION, version));
-    input->sx_w = wl_fixed_from_int(0);
-    input->sy_w = wl_fixed_from_int(0);
-    input->xkb.current_group = XKB_GROUP_INVALID;
-    d->input = input;
-
     if (d->data_device_manager) {
         Wayland_create_data_device(d);
     }
@@ -3016,10 +2983,6 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
 {
     struct SDL_WaylandInput *input = d->input;
 
-    if (!input) {
-        return;
-    }
-
     if (input->keyboard_timestamps) {
         zwp_input_timestamps_v1_destroy(input->keyboard_timestamps);
     }

+ 4 - 4
src/video/wayland/SDL_waylandevents_c.h

@@ -189,11 +189,11 @@ extern void Wayland_PumpEvents(SDL_VideoDevice *_this);
 extern void Wayland_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window);
 extern int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS);
 
-extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
-extern void Wayland_add_primary_selection_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
-extern void Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version);
+extern void Wayland_create_data_device(SDL_VideoData *d);
+extern void Wayland_create_primary_selection_device(SDL_VideoData *d);
+extern void Wayland_create_text_input(SDL_VideoData *d);
 
-extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version);
+extern void Wayland_input_initialize_seat(SDL_VideoData *d);
 extern void Wayland_display_destroy_input(SDL_VideoData *d);
 
 extern int Wayland_input_lock_pointer(struct SDL_WaylandInput *input);

+ 33 - 7
src/video/wayland/SDL_waylandvideo.c

@@ -63,12 +63,21 @@
 
 #define WAYLANDVID_DRIVER_NAME "wayland"
 
+/* Clamp certain core protocol versions on older versions of libwayland. */
 #if SDL_WAYLAND_CHECK_VERSION(1, 22, 0)
 #define SDL_WL_COMPOSITOR_VERSION 6
 #else
 #define SDL_WL_COMPOSITOR_VERSION 4
 #endif
 
+#if SDL_WAYLAND_CHECK_VERSION(1, 22, 0)
+#define SDL_WL_SEAT_VERSION 9
+#elif SDL_WAYLAND_CHECK_VERSION(1, 21, 0)
+#define SDL_WL_SEAT_VERSION 8
+#else
+#define SDL_WL_SEAT_VERSION 5
+#endif
+
 #if SDL_WAYLAND_CHECK_VERSION(1, 20, 0)
 #define SDL_WL_OUTPUT_VERSION 4
 #else
@@ -158,6 +167,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
 {
     SDL_VideoDevice *device;
     SDL_VideoData *data;
+    struct SDL_WaylandInput *input;
     struct wl_display *display = SDL_GetProperty(SDL_GetGlobalProperties(),
                                                  SDL_PROPERTY_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER, NULL);
     SDL_bool display_is_external = !!display;
@@ -189,8 +199,22 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
         return NULL;
     }
 
+    input = SDL_calloc(1, sizeof(*input));
+    if (!input) {
+        SDL_free(data);
+        WAYLAND_wl_display_disconnect(display);
+        SDL_WAYLAND_UnloadSymbols();
+        return NULL;
+    }
+
+    input->display = data;
+    input->sx_w = wl_fixed_from_int(0);
+    input->sy_w = wl_fixed_from_int(0);
+    input->xkb.current_group = XKB_GROUP_INVALID;
+
     data->initializing = SDL_TRUE;
     data->display = display;
+    data->input = input;
     data->display_externally_owned = display_is_external;
     WAYLAND_wl_list_init(&data->output_list);
     WAYLAND_wl_list_init(&external_window_list);
@@ -786,7 +810,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
     } else if (SDL_strcmp(interface, "wl_output") == 0) {
         Wayland_add_display(d, id, SDL_min(version, SDL_WL_OUTPUT_VERSION));
     } else if (SDL_strcmp(interface, "wl_seat") == 0) {
-        Wayland_display_add_input(d, id, version);
+        d->input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(SDL_WL_SEAT_VERSION, version));
+        Wayland_input_initialize_seat(d);
     } else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
         d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 6));
         xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
@@ -803,18 +828,19 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
     } else if (SDL_strcmp(interface, "xdg_activation_v1") == 0) {
         d->activation_manager = wl_registry_bind(d->registry, id, &xdg_activation_v1_interface, 1);
     } else if (SDL_strcmp(interface, "zwp_text_input_manager_v3") == 0) {
-        Wayland_add_text_input_manager(d, id, version);
+        d->text_input_manager = wl_registry_bind(d->registry, id, &zwp_text_input_manager_v3_interface, 1);
+        Wayland_create_text_input(d);
     } else if (SDL_strcmp(interface, "wl_data_device_manager") == 0) {
-        Wayland_add_data_device_manager(d, id, version);
+        d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version));
+        Wayland_create_data_device(d);
     } else if (SDL_strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0) {
-        Wayland_add_primary_selection_device_manager(d, id, version);
+        d->primary_selection_device_manager = wl_registry_bind(d->registry, id, &zwp_primary_selection_device_manager_v1_interface, 1);
+        Wayland_create_primary_selection_device(d);
     } else if (SDL_strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
         d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
     } else if (SDL_strcmp(interface, "zwp_tablet_manager_v2") == 0) {
         d->tablet_manager = wl_registry_bind(d->registry, id, &zwp_tablet_manager_v2_interface, 1);
-        if (d->input) {
-            Wayland_input_add_tablet(d->input, d->tablet_manager);
-        }
+        Wayland_input_add_tablet(d->input, d->tablet_manager);
     } else if (SDL_strcmp(interface, "zxdg_output_manager_v1") == 0) {
         version = SDL_min(version, 3); /* Versions 1 through 3 are supported. */
         d->xdg_output_manager = wl_registry_bind(d->registry, id, &zxdg_output_manager_v1_interface, version);