summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2022-02-03 10:48:56 -0600
committerDudemanguy <random342@airmail.cc>2022-02-07 17:54:03 +0000
commit34e0a212cd2e0a073a3580952549a62ede38c2d6 (patch)
tree5369477b586f4d3cb861a1b33ef3fd01f44129f8 /video/out
parent09343bc86e8bd7935fcc40f3645427a38e4b017a (diff)
downloadmpv-34e0a212cd2e0a073a3580952549a62ede38c2d6.tar.bz2
mpv-34e0a212cd2e0a073a3580952549a62ede38c2d6.tar.xz
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 700f4ef5fad353800fa866b059663bc1dd58d3b7) 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.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/wayland_common.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c
index 5824804df0..ee6b3e885d 100644
--- a/video/out/wayland_common.c
+++ b/video/out/wayland_common.c
@@ -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;
}