aboutsummaryrefslogtreecommitdiff
path: root/xwayland
diff options
context:
space:
mode:
authoremersion <contact@emersion.fr>2018-03-29 12:11:30 -0400
committeremersion <contact@emersion.fr>2018-03-29 12:11:30 -0400
commit79dd4a0ff98f6467c414903fc14112ab73345389 (patch)
treee8c6b63950d1f9944ecb4fa58e03a0853c70a17a /xwayland
parentca2a73b90d98a70d1a175cedf00c40bf7fcdf204 (diff)
xwayland: receive DND_FINISHED
Diffstat (limited to 'xwayland')
-rw-r--r--xwayland/selection.c38
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);
}