History

video/out/wayland_common: fix dnd with focus follow mouse

Whenever mpv window gains focus, a new data offer is sent for the selection. However, mpv currently treats it the same as dnd data offers, which results in wrong handling. One bug which results from this is when focus follow mouse is enabled, dropping the dnd file results in the window being focused and selection offer being sent, freeing the existing dnd offer. This results in dnd being broken on at least GTK3. Fix this by separating selection and dnd offer handling. Since there is no way to know whether an offer introduced by data_device_handle_data_offer is a selection or dnd offer, make it pending, and move them once the identity is confirmed.

nanahi committed 2 years ago

Commit 70e02e71 parent eb0c4b92 files · +35 −23Browse files

Unified · Split

2 files
  1. video/out/wayland_common.c +32 −22
  2. video/out/wayland_common.h +3 −1
video/out/wayland_common.c+32−22
@@ -259,6 +259,7 @@ static void set_surface_scaling(struct vo_wayland_state *wl); · 258 unmodified lines
259static void update_output_scaling(struct vo_wayland_state *wl);259static void update_output_scaling(struct vo_wayland_state *wl);
260static void update_output_geometry(struct vo_wayland_state *wl, struct mp_rect old_geometry,260static void update_output_geometry(struct vo_wayland_state *wl, struct mp_rect old_geometry,
261 struct mp_rect old_output_geometry);261 struct mp_rect old_output_geometry);
262static void destroy_offer(struct vo_wayland_data_offer *o);
262 263
263/* Wayland listener boilerplate */264/* Wayland listener boilerplate */
264static void pointer_handle_enter(void *data, struct wl_pointer *pointer,265static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
@@ -696,12 +697,12 @@ static void data_offer_handle_offer(void *data, struct wl_data_offer *offer, · 431 unmodified lines
696{697{
697 struct vo_wayland_seat *s = data;698 struct vo_wayland_seat *s = data;
698 struct vo_wayland_state *wl = s->wl;699 struct vo_wayland_state *wl = s->wl;
699 struct vo_wayland_data_offer *o = wl->dnd_offer;700 struct vo_wayland_data_offer *o = wl->pending_offer;
700 int score = mp_event_get_mime_type_score(wl->vo->input_ctx, mime_type);701 int score = mp_event_get_mime_type_score(wl->vo->input_ctx, mime_type);
701 if (score > o->mime_score && wl->opts->drag_and_drop != -2) {702 if (o->offer && score > o->mime_score && wl->opts->drag_and_drop != -2) {
702 o->mime_score = score;703 o->mime_score = score;
703 talloc_replace(wl, o->mime_type, mime_type);704 talloc_replace(wl, o->mime_type, mime_type);
704 MP_VERBOSE(wl, "Given DND offer with mime type %s\n", o->mime_type);705 MP_VERBOSE(wl, "Given data offer with mime type %s\n", o->mime_type);
705 }706 }
706}707}
707 708
@@ -743,9 +744,8 @@ static void data_device_handle_data_offer(void *data, struct wl_data_device *wl_ · 35 unmodified lines
743{744{
744 struct vo_wayland_seat *s = data;745 struct vo_wayland_seat *s = data;
745 struct vo_wayland_state *wl = s->wl;746 struct vo_wayland_state *wl = s->wl;
746 struct vo_wayland_data_offer *o = wl->dnd_offer;747 struct vo_wayland_data_offer *o = wl->pending_offer;
747 if (o->offer)748 destroy_offer(o);
748 wl_data_offer_destroy(o->offer);
749 749
750 o->offer = id;750 o->offer = id;
751 wl_data_offer_add_listener(id, &data_offer_listener, s);751 wl_data_offer_add_listener(id, &data_offer_listener, s);
@@ -758,12 +758,16 @@ static void data_device_handle_enter(void *data, struct wl_data_device *wl_ddev, · 6 unmodified lines
758{758{
759 struct vo_wayland_seat *s = data;759 struct vo_wayland_seat *s = data;
760 struct vo_wayland_state *wl = s->wl;760 struct vo_wayland_state *wl = s->wl;
761 struct vo_wayland_data_offer *o = wl->dnd_offer;761 struct vo_wayland_data_offer *o = wl->pending_offer;
762 if (o->offer != id) {762 if (o->offer != id) {
763 MP_FATAL(wl, "DND offer ID mismatch!\n");763 MP_FATAL(wl, "DND offer ID mismatch!\n");
764 return;764 return;
765 }765 }
766 766
767 assert(!wl->dnd_offer->offer);
768 *wl->dnd_offer = *wl->pending_offer;
769 *wl->pending_offer = (struct vo_wayland_data_offer){.fd = -1};
770 o = wl->dnd_offer;
767 if (wl->opts->drag_and_drop != -2) {771 if (wl->opts->drag_and_drop != -2) {
768 wl_data_offer_set_actions(id, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |772 wl_data_offer_set_actions(id, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
769 WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,773 WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE,
@@ -831,14 +835,18 @@ static void data_device_handle_selection(void *data, struct wl_data_device *wl_d · 61 unmodified lines
831{835{
832 struct vo_wayland_seat *s = data;836 struct vo_wayland_seat *s = data;
833 struct vo_wayland_state *wl = s->wl;837 struct vo_wayland_state *wl = s->wl;
834 struct vo_wayland_data_offer *o = wl->dnd_offer;838 struct vo_wayland_data_offer *o = wl->pending_offer;
835 839 if (o->offer != id) {
836 if (o->offer) {840 MP_FATAL(wl, "Selection offer ID mismatch!\n");
837 wl_data_offer_destroy(o->offer);841 return;
838 o->offer = NULL;
839 MP_VERBOSE(wl, "Received a new DND offer. Releasing the previous offer.\n");
840 }842 }
841 843
844 if (wl->selection_offer->offer) {
845 destroy_offer(wl->selection_offer);
846 MP_VERBOSE(wl, "Received a new selection offer. Releasing the previous offer.\n");
847 }
848 *wl->selection_offer = *wl->pending_offer;
849 *wl->pending_offer = (struct vo_wayland_data_offer){.fd = -1};
842}850}
843 851
844static const struct wl_data_device_listener data_device_listener = {852static const struct wl_data_device_listener data_device_listener = {
@@ -1690,7 +1698,7 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id · 845 unmodified lines
1690 1698
1691 if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {1699 if (!strcmp(interface, wl_data_device_manager_interface.name) && (ver >= 3) && found++) {
1692 ver = 3;1700 ver = 3;
1693 wl->dnd_devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, ver);1701 wl->devman = wl_registry_bind(reg, id, &wl_data_device_manager_interface, ver);
1694 }1702 }
1695 1703
1696 if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {1704 if (!strcmp(interface, wl_output_interface.name) && (ver >= 2) && found++) {
@@ -1898,15 +1906,13 @@ static void check_dnd_fd(struct vo_wayland_state *wl) · 201 unmodified lines
1898 }1906 }
1899 1907
1900 talloc_free(file_list.start);1908 talloc_free(file_list.start);
1901 free_offer_data(wl->dnd_offer);1909 destroy_offer(o);
1902 }1910 }
1903 1911
1904 if (fdp.revents & (POLLIN | POLLERR | POLLHUP)) {1912 if (fdp.revents & (POLLIN | POLLERR | POLLHUP)) {
1905 if (o->action >= 0)1913 if (o->action >= 0)
1906 MP_VERBOSE(wl, "DND aborted (hang up or error)\n");1914 MP_VERBOSE(wl, "DND aborted (hang up or error)\n");
1907 free_offer_data(wl->dnd_offer);1915 destroy_offer(o);
1908 close(o->fd);
1909 o->fd = -1;
1910 }1916 }
1911}1917}
1912 1918
@@ -3058,7 +3064,9 @@ bool vo_wayland_init(struct vo *vo) · 1145 unmodified lines
3058 .scaling = WAYLAND_SCALE_FACTOR,3064 .scaling = WAYLAND_SCALE_FACTOR,
3059 .wakeup_pipe = {-1, -1},3065 .wakeup_pipe = {-1, -1},
3060 .display_fd = -1,3066 .display_fd = -1,
3067 .pending_offer = talloc_zero(wl, struct vo_wayland_data_offer),
3061 .dnd_offer = talloc_zero(wl, struct vo_wayland_data_offer),3068 .dnd_offer = talloc_zero(wl, struct vo_wayland_data_offer),
3069 .selection_offer = talloc_zero(wl, struct vo_wayland_data_offer),
3062 .cursor_visible = true,3070 .cursor_visible = true,
3063 .opts_cache = m_config_cache_alloc(wl, vo->global, &vo_sub_opts),3071 .opts_cache = m_config_cache_alloc(wl, vo->global, &vo_sub_opts),
3064 };3072 };
@@ -3148,10 +3156,10 @@ bool vo_wayland_init(struct vo *vo) · 83 unmodified lines
3148 }3156 }
3149#endif3157#endif
3150 3158
3151 if (wl->dnd_devman) {3159 if (wl->devman) {
3152 struct vo_wayland_seat *seat;3160 struct vo_wayland_seat *seat;
3153 wl_list_for_each(seat, &wl->seat_list, link) {3161 wl_list_for_each(seat, &wl->seat_list, link) {
3154 seat->dnd_ddev = wl_data_device_manager_get_data_device(wl->dnd_devman, seat->seat);3162 seat->dnd_ddev = wl_data_device_manager_get_data_device(wl->devman, seat->seat);
3155 wl_data_device_add_listener(seat->dnd_ddev, &data_device_listener, seat);3163 wl_data_device_add_listener(seat->dnd_ddev, &data_device_listener, seat);
3156 }3164 }
3157 } else {3165 } else {
@@ -3287,7 +3295,9 @@ void vo_wayland_uninit(struct vo *vo) · 129 unmodified lines
3287 if (!wl)3295 if (!wl)
3288 return;3296 return;
3289 3297
3298 destroy_offer(wl->pending_offer);
3290 destroy_offer(wl->dnd_offer);3299 destroy_offer(wl->dnd_offer);
3300 destroy_offer(wl->selection_offer);
3291 3301
3292 mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);3302 mp_input_put_key(wl->vo->input_ctx, MP_INPUT_RELEASE_ALL);
3293 3303
@@ -3326,8 +3336,8 @@ void vo_wayland_uninit(struct vo *vo) · 32 unmodified lines
3326 if (wl->content_type_manager)3336 if (wl->content_type_manager)
3327 wp_content_type_manager_v1_destroy(wl->content_type_manager);3337 wp_content_type_manager_v1_destroy(wl->content_type_manager);
3328 3338
3329 if (wl->dnd_devman)3339 if (wl->devman)
3330 wl_data_device_manager_destroy(wl->dnd_devman);3340 wl_data_device_manager_destroy(wl->devman);
3331 3341
3332 if (wl->fback_pool)3342 if (wl->fback_pool)
3333 clean_feedback_pool(wl->fback_pool);3343 clean_feedback_pool(wl->fback_pool);
video/out/wayland_common.h+3−1
@@ -162,8 +162,10 @@ struct vo_wayland_state { · 161 unmodified lines
162 struct xkb_context *xkb_context;162 struct xkb_context *xkb_context;
163 163
164 /* Data offer */164 /* Data offer */
165 struct wl_data_device_manager *dnd_devman;165 struct wl_data_device_manager *devman;
166 struct vo_wayland_data_offer *pending_offer;
166 struct vo_wayland_data_offer *dnd_offer;167 struct vo_wayland_data_offer *dnd_offer;
168 struct vo_wayland_data_offer *selection_offer;
167 169
168 /* Cursor */170 /* Cursor */
169 struct wl_cursor_theme *cursor_theme;171 struct wl_cursor_theme *cursor_theme;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t