diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 3d85a5e282..b19bfdacd0 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/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); } diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 5bd061a25c..af317811f3 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/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); diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 728d7b9879..efd1be7296 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/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);