diff --git a/xwayland/selection.c b/xwayland/selection.c index 81b5ab81..976b9200 100644 --- a/xwayland/selection.c +++ b/xwayland/selection.c @@ -269,11 +269,31 @@ static xcb_atom_t xwm_get_mime_type_atom(struct wlr_xwm *xwm, char *mime_type) { return atom; } +static void xwm_dnd_send_event(struct wlr_xwm *xwm, xcb_atom_t type, + xcb_client_message_data_t *data) { + struct wlr_xwayland_surface *dest = xwm->drag_focus; + assert(dest != NULL); + + xcb_client_message_event_t event = { + .response_type = XCB_CLIENT_MESSAGE, + .format = 32, + .sequence = 0, + .window = dest->window_id, + .type = type, + .data = *data, + }; + + xcb_send_event(xwm->xcb_conn, + 0, // propagate + dest->window_id, + XCB_EVENT_MASK_NO_EVENT, + (const char *)&event); + xcb_flush(xwm->xcb_conn); +} + static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { struct wlr_drag *drag = xwm->drag; assert(drag != NULL); - struct wlr_xwayland_surface *dest = xwm->drag_focus; - assert(dest != NULL); struct wl_array *mime_types = &drag->source->mime_types; xcb_client_message_data_t data = { 0 }; @@ -312,29 +332,13 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { n, targets); } - xcb_client_message_event_t event = { - .response_type = XCB_CLIENT_MESSAGE, - .format = 32, - .sequence = 0, - .window = dest->window_id, - .type = xwm->atoms[DND_ENTER], - .data = data, - }; - - xcb_send_event(xwm->xcb_conn, - 0, // propagate - dest->window_id, - XCB_EVENT_MASK_NO_EVENT, - (const char *)&event); - xcb_flush(xwm->xcb_conn); + xwm_dnd_send_event(xwm, xwm->atoms[DND_ENTER], &data); } static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x, int16_t y) { struct wlr_drag *drag = xwm->drag; assert(drag != NULL); - struct wlr_xwayland_surface *dest = xwm->drag_focus; - assert(dest != NULL); xcb_client_message_data_t data = { 0 }; data.data32[0] = xwm->dnd_selection.window; @@ -343,21 +347,7 @@ static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x, data.data32[4] = data_device_manager_dnd_action_to_atom(xwm, drag->source->actions); - xcb_client_message_event_t event = { - .response_type = XCB_CLIENT_MESSAGE, - .format = 32, - .sequence = 0, - .window = dest->window_id, - .type = xwm->atoms[DND_POSITION], - .data = data, - }; - - xcb_send_event(xwm->xcb_conn, - 0, // propagate - dest->window_id, - XCB_EVENT_MASK_NO_EVENT, - (const char *)&event); - xcb_flush(xwm->xcb_conn); + xwm_dnd_send_event(xwm, xwm->atoms[DND_POSITION], &data); } static void xwm_dnd_send_drop(struct wlr_xwm *xwm, uint32_t time) { @@ -370,21 +360,19 @@ static void xwm_dnd_send_drop(struct wlr_xwm *xwm, uint32_t time) { data.data32[0] = xwm->dnd_selection.window; data.data32[2] = time; - xcb_client_message_event_t event = { - .response_type = XCB_CLIENT_MESSAGE, - .format = 32, - .sequence = 0, - .window = dest->window_id, - .type = xwm->atoms[DND_DROP], - .data = data, - }; + xwm_dnd_send_event(xwm, xwm->atoms[DND_DROP], &data); +} - xcb_send_event(xwm->xcb_conn, - 0, // propagate - dest->window_id, - XCB_EVENT_MASK_NO_EVENT, - (const char *)&event); - xcb_flush(xwm->xcb_conn); +static void xwm_dnd_send_leave(struct wlr_xwm *xwm) { + struct wlr_drag *drag = xwm->drag; + assert(drag != NULL); + struct wlr_xwayland_surface *dest = xwm->drag_focus; + assert(dest != NULL); + + xcb_client_message_data_t data = { 0 }; + data.data32[0] = xwm->dnd_selection.window; + + xwm_dnd_send_event(xwm, xwm->atoms[DND_LEAVE], &data); } /*static void xwm_dnd_send_finished(struct wlr_xwm *xwm) { @@ -402,21 +390,7 @@ static void xwm_dnd_send_drop(struct wlr_xwm *xwm, uint32_t time) { drag->source->current_dnd_action); } - xcb_client_message_event_t event = { - .response_type = XCB_CLIENT_MESSAGE, - .format = 32, - .sequence = 0, - .window = dest->window_id, - .type = xwm->atoms[DND_FINISHED], - .data = data, - }; - - xcb_send_event(xwm->xcb_conn, - 0, // propagate - dest->window_id, - XCB_EVENT_MASK_NO_EVENT, - (const char *)&event); - xcb_flush(xwm->xcb_conn); + xwm_dnd_send_event(xwm, xwm->atoms[DND_FINISHED], &data); }*/ static struct wl_array *xwm_selection_source_get_mime_types( @@ -1128,21 +1102,31 @@ static void seat_handle_drag_focus(struct wl_listener *listener, void *data) { struct wlr_drag *drag = data; struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_focus); - // TODO: check for subsurfaces? - bool found = false; - struct wlr_xwayland_surface *surface; - wl_list_for_each(surface, &xwm->surfaces, link) { - if (surface->surface == drag->focus) { - found = true; - break; + struct wlr_xwayland_surface *focus = NULL; + if (drag->focus != NULL) { + // TODO: check for subsurfaces? + struct wlr_xwayland_surface *surface; + wl_list_for_each(surface, &xwm->surfaces, link) { + if (surface->surface == drag->focus) { + focus = surface; + break; + } } } - if (!found) { + + if (focus == xwm->drag_focus) { return; } - xwm->drag_focus = surface; - xwm_dnd_send_enter(xwm); + if (xwm->drag_focus != NULL) { + xwm_dnd_send_leave(xwm); + } + + xwm->drag_focus = focus; + + if (xwm->drag_focus != NULL) { + xwm_dnd_send_enter(xwm); + } } static void seat_handle_drag_motion(struct wl_listener *listener, void *data) { @@ -1161,9 +1145,8 @@ static void seat_handle_drag_motion(struct wl_listener *listener, void *data) { static void seat_handle_drag_drop(struct wl_listener *listener, void *data) { struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_drop); struct wlr_drag_drop_event *event = data; - struct wlr_xwayland_surface *surface = xwm->drag_focus; - if (surface == NULL) { + if (xwm->drag_focus == NULL) { return; // No xwayland surface focused } @@ -1173,6 +1156,10 @@ static void seat_handle_drag_drop(struct wl_listener *listener, void *data) { static void seat_handle_drag_destroy(struct wl_listener *listener, void *data) { struct wlr_xwm *xwm = wl_container_of(listener, xwm, seat_drag_destroy); + if (xwm->drag_focus != NULL) { + xwm_dnd_send_leave(xwm); + } + wl_list_remove(&xwm->seat_drag_focus.link); wl_list_remove(&xwm->seat_drag_destroy.link); xwm->drag = NULL;