diff options
Diffstat (limited to 'xwayland/selection.c')
-rw-r--r-- | xwayland/selection.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/xwayland/selection.c b/xwayland/selection.c index f56b39b5..d4a8b597 100644 --- a/xwayland/selection.c +++ b/xwayland/selection.c @@ -1015,6 +1015,41 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm, wlr_log(L_DEBUG, "DND_STATUS window=%d accepted=%d action=%d", target_window, accepted, action); return 1; + } else if (ev->type == xwm->atoms[DND_FINISHED]) { + // This should only happen after the drag has ended, but before the drag + // source is destroyed + if (xwm->seat == NULL || xwm->seat->drag_source == NULL || + xwm->drag != NULL) { + wlr_log(L_DEBUG, "ignoring XdndFinished client message because " + "there's no finished drag"); + return 1; + } + + xcb_client_message_data_t *data = &ev->data; + xcb_window_t target_window = data->data32[0]; + bool performed = data->data32[1] & 1; + xcb_atom_t action_atom = data->data32[2]; + + if (xwm->drag_focus == NULL || + target_window != xwm->drag_focus->window_id) { + wlr_log(L_DEBUG, "ignoring XdndFinished client message because " + "it doesn't match the finished drag focus window ID"); + return 1; + } + + enum wl_data_device_manager_dnd_action action = + data_device_manager_dnd_action_from_atom(xwm, action_atom); + + if (performed) { + struct wlr_data_source *source = xwm->seat->drag_source; + if (source->dnd_finish) { + source->dnd_finish(source); + } + } + + wlr_log(L_DEBUG, "DND_FINISH window=%d performed=%d action=%d", + target_window, performed, action); + return 1; } else { return 0; } @@ -1204,7 +1239,8 @@ static void seat_handle_drag_destroy(struct wl_listener *listener, void *data) { // Don't reset drag focus yet because the target will read the drag source // right after - if (xwm->drag_focus != NULL) { + if (xwm->drag_focus != NULL && !xwm->drag->source->accepted) { + wlr_log(L_DEBUG, "Wayland drag cancelled over an Xwayland window"); xwm_dnd_send_leave(xwm); } |