Skip to content

Commit

Permalink
wayland: Create the data_device only after both device_manager and in…
Browse files Browse the repository at this point in the history
…put exist.

There is no guarantee on what order the Wayland interfaces will come in, but the
callbacks were assuming that wl_data_device_manager would could before wl_seat.
This would cause certain desktops to not have any data_device to work with,
meaning certain features like the clipboard would silently no-op.
  • Loading branch information
flibitijibibo authored and slouken committed Apr 10, 2021
1 parent 732cc8e commit 7510245
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 20 deletions.
55 changes: 36 additions & 19 deletions src/video/wayland/SDL_waylandevents.c
Expand Up @@ -1087,11 +1087,45 @@ static const struct wl_data_device_listener data_device_listener = {
data_device_handle_selection
};

static void
Wayland_create_data_device(SDL_VideoData *d)
{
SDL_WaylandDataDevice *data_device = NULL;

data_device = SDL_calloc(1, sizeof *data_device);
if (data_device == NULL) {
return;
}

data_device->data_device = wl_data_device_manager_get_data_device(
d->data_device_manager, d->input->seat
);
data_device->video_data = d;

if (data_device->data_device == NULL) {
SDL_free(data_device);
} else {
wl_data_device_set_user_data(data_device->data_device, data_device);
wl_data_device_add_listener(data_device->data_device,
&data_device_listener, data_device);
d->input->data_device = data_device;
}
}

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 != NULL) {
Wayland_create_data_device(d);
}
}

void
Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
{
struct SDL_WaylandInput *input;
SDL_WaylandDataDevice *data_device = NULL;

input = SDL_calloc(1, sizeof *input);
if (input == NULL)
Expand All @@ -1104,24 +1138,7 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
d->input = input;

if (d->data_device_manager != NULL) {
data_device = SDL_calloc(1, sizeof *data_device);
if (data_device == NULL) {
return;
}

data_device->data_device = wl_data_device_manager_get_data_device(
d->data_device_manager, input->seat
);
data_device->video_data = d;

if (data_device->data_device == NULL) {
SDL_free(data_device);
} else {
wl_data_device_set_user_data(data_device->data_device, data_device);
wl_data_device_add_listener(data_device->data_device,
&data_device_listener, data_device);
input->data_device = data_device;
}
Wayland_create_data_device(d);
}

wl_seat_add_listener(input->seat, &seat_listener, input);
Expand Down
2 changes: 2 additions & 0 deletions src/video/wayland/SDL_waylandevents_c.h
Expand Up @@ -80,6 +80,8 @@ struct SDL_WaylandInput {

extern void Wayland_PumpEvents(_THIS);

extern void Wayland_add_data_device_manager(SDL_VideoData *d, uint32_t id, uint32_t version);

extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version);
extern void Wayland_display_destroy_input(SDL_VideoData *d);

Expand Down
2 changes: 1 addition & 1 deletion src/video/wayland/SDL_waylandvideo.c
Expand Up @@ -423,7 +423,7 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
d->idle_inhibit_manager = wl_registry_bind(d->registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version));
Wayland_add_data_device_manager(d, id, version);
} else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);

Expand Down

0 comments on commit 7510245

Please sign in to comment.