mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-28 05:40:11 -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.
This commit is contained in:
parent
71943b3b1e
commit
546c5d000d
4 changed files with 31 additions and 4 deletions
|
|
@ -128,6 +128,7 @@ struct wlr_xwm {
|
|||
|
||||
struct wlr_drag *drag;
|
||||
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 *xres;
|
||||
|
|
@ -150,6 +151,7 @@ struct wlr_xwm {
|
|||
struct wl_listener seat_drag_destroy;
|
||||
struct wl_listener seat_drag_source_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);
|
||||
|
|
|
|||
|
|
@ -212,10 +212,10 @@ int xwm_handle_selection_client_message(struct wlr_xwm *xwm,
|
|||
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) {
|
||||
if (xwm->drop_focus == NULL ||
|
||||
target_window != xwm->drop_focus->window_id) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -241,6 +241,13 @@ static void drag_focus_handle_destroy(struct wl_listener *listener, void *data)
|
|||
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) {
|
||||
if (focus == xwm->drag_focus) {
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -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_init(&xwm->drag_focus_destroy.link);
|
||||
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) {
|
||||
wl_list_remove(&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_focus = NULL;
|
||||
xwm->drop_focus = NULL;
|
||||
|
||||
if (drag != NULL) {
|
||||
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) {
|
||||
wl_list_remove(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_remove(&xwm->drag_focus_destroy.link);
|
||||
wl_list_remove(&xwm->drop_focus_destroy.link);
|
||||
|
||||
if (!xwm->drag) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -410,8 +410,11 @@ void xwm_handle_selection_request(struct wlr_xwm *xwm,
|
|||
return;
|
||||
}
|
||||
|
||||
bool dnd_allowed = selection == &xwm->dnd_selection
|
||||
&& (xwm->drag_focus != NULL || xwm->drop_focus != NULL);
|
||||
|
||||
// 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) {
|
||||
char *selection_name = xwm_get_atom_name(xwm, selection->atom);
|
||||
wlr_log(WLR_DEBUG, "denying read access to selection %u (%s): "
|
||||
|
|
|
|||
|
|
@ -2266,6 +2266,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
|||
wl_list_init(&xwm->pending_startup_ids);
|
||||
wl_list_init(&xwm->seat_drag_source_destroy.link);
|
||||
wl_list_init(&xwm->drag_focus_destroy.link);
|
||||
wl_list_init(&xwm->drop_focus_destroy.link);
|
||||
|
||||
xwm->ping_timeout = 10000;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue