wayland: partially fix drag and drop handling

Drag and drop in wayland is weird and it seems everyone does this
slightly differently (fun). In the past, there was a crash that
occured (fixed by 700f4ef5fa) which
involved using the wl_data_offer_finish in an incorrect way that
triggered a protocol error (always fatal). The fix involved moving the
function call to data_device_handle_drop which seemingly works, but it
has an unfortunate side effect. It appears like GTK applications (or at
least firefox) close the pipe after this function is called which makes
it impossible for mpv to read data from the fd (well you could force it
open again in theory but let's not do that). Who knows if that was the
case when that commit was made (probably not because I'd think I would
have noticed; could just be a dummy though), but obviously having broken
dnd for a major application isn't so fun (this works with QT and
chromium anyway).

Ideally one would just simply check the pipe in data_device_handle_drop,
but this doesn't work because it doesn't seem the compositor actually
sends mpv the data by then. There's not actually a defined event when
you're supposed to be able to read data from this pipe, so we wait for
the usual event checking loop later for this. In that case,
wl_data_offer_finish needs to go back into check_dnd_fd, but we have to
be careful when calling it otherwise we'd just commit protocol errors
like before. We check to make sure we even have a valid wl->dnd_offer
before trying to indicate that it is finished and additionally make sure
there is a valid dnd_action (after checking the fd, it's always set back
to -1).

This doesn't fix everything though. Specifically, sway with
focus_follows_mouse (the default) and GTK as the data source still
doesn't work. The reason is that when you do a drag and drop in sway
with that option on, a new wl_data_device.data_offer event is sent out
instantly after the drop event. This happens before any data is sent
across the fd and before mpv even has a chance to check it. What GTK
does, when getting this new data_offer event, is close the pipe
(POLLHUP). This means mpv can't read it when we reach the event loop and
thus no data is ever read and broken drag and drop. From the client
side, this isn't really fixable since the wayland protocol doesn't have
a clear indication of when clients are supposed to read from the fd and
both the compositor and data source are doing things totally out of our
control. So we'll consider this weird case, "not our bug" at least. The
rest should work.
This commit is contained in:
Dudemanguy 2022-02-03 10:48:56 -06:00
parent 09343bc86e
commit 34e0a212cd
1 changed files with 15 additions and 2 deletions

View File

@ -583,12 +583,19 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_ddev)
close(pipefd[1]);
wl->dnd_fd = pipefd[0];
wl_data_offer_finish(wl->dnd_offer);
}
static void data_device_handle_selection(void *data, struct wl_data_device *wl_ddev,
struct wl_data_offer *id)
{
struct vo_wayland_state *wl = data;
if (wl->dnd_offer) {
wl_data_offer_destroy(wl->dnd_offer);
wl->dnd_offer = NULL;
MP_VERBOSE(wl, "Received a new DND offer. Releasing the previous offer.");
}
}
static const struct wl_data_device_listener data_device_listener = {
@ -1120,7 +1127,13 @@ static void check_dnd_fd(struct vo_wayland_state *wl)
file_list, wl->dnd_action);
talloc_free(buffer);
end:
talloc_free(wl->dnd_mime_type);
if (wl->dnd_mime_type)
talloc_free(wl->dnd_mime_type);
if (wl->dnd_action >= 0 && wl->dnd_offer)
wl_data_offer_finish(wl->dnd_offer);
wl->dnd_action = -1;
wl->dnd_mime_type = NULL;
wl->dnd_mime_score = 0;
}