Merge branch 'dnd' into 'master'

xwayland/dnd: add support for XdndProxy

See merge request wlroots/wlroots!5024
This commit is contained in:
Xu Rui 2026-01-20 08:21:44 +00:00
commit 6833511dc8
2 changed files with 41 additions and 1 deletions

View file

@ -174,6 +174,9 @@ struct wlr_xwayland_surface {
*/
xcb_ewmh_wm_strut_partial_t *strut_partial;
/* XdndProxy window */
xcb_window_t proxy_window;
bool pinging;
struct wl_event_source *ping_timer;

View file

@ -51,7 +51,7 @@ static void xwm_dnd_send_event(struct wlr_xwm *xwm, xcb_atom_t type,
xwm_send_event_with_size(xwm->xcb_conn,
0, // propagate
dest->window_id,
dest->proxy_window ? dest->proxy_window : dest->window_id,
XCB_EVENT_MASK_NO_EVENT,
&event,
sizeof(event));
@ -245,6 +245,39 @@ static void drop_focus_handle_destroy(struct wl_listener *listener, void *data)
xwm->drop_focus = NULL;
}
static bool property_reply_is_valid(xcb_get_property_reply_t *reply) {
return reply && reply->type == XCB_ATOM_WINDOW && reply->format == 32 &&
xcb_get_property_value_length(reply) == sizeof(xcb_window_t);
}
static xcb_window_t get_proxy_window(struct wlr_xwm *xwm, xcb_window_t window) {
xcb_window_t target_window = window;
xcb_get_property_cookie_t proxy_cookie =
xcb_get_property(xwm->xcb_conn, 0, window, xwm->atoms[DND_PROXY], XCB_ATOM_WINDOW, 0, 1);
xcb_get_property_reply_t *proxy_reply =
xcb_get_property_reply(xwm->xcb_conn, proxy_cookie, NULL);
if (property_reply_is_valid(proxy_reply)) {
xcb_window_t proxy_window = *(xcb_window_t *)xcb_get_property_value(proxy_reply);
xcb_get_property_cookie_t proxy_verify_cookie = xcb_get_property(
xwm->xcb_conn, 0, proxy_window, xwm->atoms[DND_PROXY], XCB_ATOM_WINDOW, 0, 1);
xcb_get_property_reply_t *proxy_verify_reply =
xcb_get_property_reply(xwm->xcb_conn, proxy_verify_cookie, NULL);
if (property_reply_is_valid(proxy_verify_reply)) {
xcb_window_t verifyWindow = *(xcb_window_t *)xcb_get_property_value(proxy_verify_reply);
if (verifyWindow == proxy_window) {
target_window = proxy_window;
}
}
free(proxy_verify_reply);
}
free(proxy_reply);
return target_window;
}
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) {
if (focus == xwm->drag_focus) {
return;
@ -265,6 +298,10 @@ static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface
xwm->drag_focus_destroy.notify = drag_focus_handle_destroy;
wl_signal_add(&xwm->drag_focus->events.destroy, &xwm->drag_focus_destroy);
if (!xwm->drag_focus->proxy_window) {
xwm->drag_focus->proxy_window = get_proxy_window(xwm, focus->window_id);
}
xwm_dnd_send_enter(xwm);
}
}