mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
xwayland: fix xdg->xwayland drag-and-drop
As struct wlr_drag is destroyed on drop and in the process resets
the focus, a xwayland dnd listener would also reset xwm->drag_focus.
This prevents the xcb replies from being processed and also prevents
the transfer if a compositor would not additionally request new focus
in its wlr_drag destroy handler (which is something usually only done
when in a focus-follows-mouse setting).
This patch creates a new xwm->drop_focus pointer which is a copy of
xwm->drag_focus at drop time. The xcb reply handler and transfer
logic now use the new xwm->drop_focus for their authorization checks.
(cherry picked from commit 546c5d000d)
This commit is contained in:
parent
35ab453360
commit
0c437f6e98
4 changed files with 31 additions and 4 deletions
|
|
@ -123,6 +123,7 @@ struct wlr_xwm {
|
||||||
|
|
||||||
struct wlr_drag *drag;
|
struct wlr_drag *drag;
|
||||||
struct wlr_xwayland_surface *drag_focus;
|
struct wlr_xwayland_surface *drag_focus;
|
||||||
|
struct wlr_xwayland_surface *drop_focus;
|
||||||
|
|
||||||
const xcb_query_extension_reply_t *xfixes;
|
const xcb_query_extension_reply_t *xfixes;
|
||||||
const xcb_query_extension_reply_t *xres;
|
const xcb_query_extension_reply_t *xres;
|
||||||
|
|
@ -145,6 +146,7 @@ struct wlr_xwm {
|
||||||
struct wl_listener seat_drag_destroy;
|
struct wl_listener seat_drag_destroy;
|
||||||
struct wl_listener seat_drag_source_destroy;
|
struct wl_listener seat_drag_source_destroy;
|
||||||
struct wl_listener drag_focus_destroy;
|
struct wl_listener drag_focus_destroy;
|
||||||
|
struct wl_listener drop_focus_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
|
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
|
||||||
|
|
|
||||||
|
|
@ -212,10 +212,10 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
||||||
bool performed = data->data32[1] & 1;
|
bool performed = data->data32[1] & 1;
|
||||||
xcb_atom_t action_atom = data->data32[2];
|
xcb_atom_t action_atom = data->data32[2];
|
||||||
|
|
||||||
if (xwm->drag_focus == NULL ||
|
if (xwm->drop_focus == NULL ||
|
||||||
target_window != xwm->drag_focus->window_id) {
|
target_window != xwm->drop_focus->window_id) {
|
||||||
wlr_log(WLR_DEBUG, "ignoring XdndFinished client message because "
|
wlr_log(WLR_DEBUG, "ignoring XdndFinished client message because "
|
||||||
"it doesn't match the finished drag focus window ID");
|
"it doesn't match the finished drop focus window ID");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,6 +241,13 @@ static void drag_focus_handle_destroy(struct wl_listener *listener, void *data)
|
||||||
xwm_set_drag_focus(xwm, NULL);
|
xwm_set_drag_focus(xwm, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drop_focus_handle_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct wlr_xwm *xwm = wl_container_of(listener, xwm, drop_focus_destroy);
|
||||||
|
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||||
|
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||||
|
xwm->drop_focus = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) {
|
static void xwm_set_drag_focus(struct wlr_xwm *xwm, struct wlr_xwayland_surface *focus) {
|
||||||
if (focus == xwm->drag_focus) {
|
if (focus == xwm->drag_focus) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -299,6 +306,12 @@ static void seat_handle_drag_drop(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "Wayland drag dropped over an Xwayland window");
|
wlr_log(WLR_DEBUG, "Wayland drag dropped over an Xwayland window");
|
||||||
|
|
||||||
|
xwm->drop_focus = xwm->drag_focus;
|
||||||
|
xwm->drop_focus_destroy.notify = drop_focus_handle_destroy;
|
||||||
|
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||||
|
wl_signal_add(&xwm->drop_focus->events.destroy, &xwm->drop_focus_destroy);
|
||||||
|
|
||||||
xwm_dnd_send_drop(xwm, event->time);
|
xwm_dnd_send_drop(xwm, event->time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,14 +342,21 @@ static void seat_handle_drag_source_destroy(struct wl_listener *listener,
|
||||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||||
xwm->drag_focus = NULL;
|
xwm->drag_focus = NULL;
|
||||||
|
|
||||||
|
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||||
|
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||||
|
xwm->drop_focus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
|
void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
|
||||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||||
|
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||||
|
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||||
|
|
||||||
xwm->drag = drag;
|
xwm->drag = drag;
|
||||||
xwm->drag_focus = NULL;
|
xwm->drag_focus = NULL;
|
||||||
|
xwm->drop_focus = NULL;
|
||||||
|
|
||||||
if (drag != NULL) {
|
if (drag != NULL) {
|
||||||
wl_signal_add(&drag->events.focus, &xwm->seat_drag_focus);
|
wl_signal_add(&drag->events.focus, &xwm->seat_drag_focus);
|
||||||
|
|
@ -357,6 +377,7 @@ void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag) {
|
||||||
void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm) {
|
void xwm_seat_unlink_drag_handlers(struct wlr_xwm *xwm) {
|
||||||
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
||||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||||
|
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||||
|
|
||||||
if (!xwm->drag) {
|
if (!xwm->drag) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -410,8 +410,11 @@ void xwm_handle_selection_request(struct wlr_xwm *xwm,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dnd_allowed = selection == &xwm->dnd_selection
|
||||||
|
&& (xwm->drag_focus != NULL || xwm->drop_focus != NULL);
|
||||||
|
|
||||||
// No xwayland surface focused, deny access to clipboard
|
// No xwayland surface focused, deny access to clipboard
|
||||||
if (xwm->focus_surface == NULL && xwm->drag_focus == NULL) {
|
if (xwm->focus_surface == NULL && !dnd_allowed) {
|
||||||
if (wlr_log_get_verbosity() >= WLR_DEBUG) {
|
if (wlr_log_get_verbosity() >= WLR_DEBUG) {
|
||||||
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
||||||
wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): "
|
wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): "
|
||||||
|
|
|
||||||
|
|
@ -2177,6 +2177,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
||||||
wl_list_init(&xwm->pending_startup_ids);
|
wl_list_init(&xwm->pending_startup_ids);
|
||||||
wl_list_init(&xwm->seat_drag_source_destroy.link);
|
wl_list_init(&xwm->seat_drag_source_destroy.link);
|
||||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||||
|
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||||
|
|
||||||
xwm->ping_timeout = 10000;
|
xwm->ping_timeout = 10000;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue