diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h index f467e107..d12eb681 100644 --- a/include/xwayland/xwm.h +++ b/include/xwayland/xwm.h @@ -103,13 +103,8 @@ struct wlr_xwm { xcb_render_pictformat_t render_format_id; xcb_cursor_t cursor; - // FIXME: need one per selection to simultaneously request both mimetypes, - // I think. - xcb_window_t selection_window; struct wlr_xwm_selection clipboard_selection; struct wlr_xwm_selection primary_selection; - - xcb_window_t dnd_window; struct wlr_xwm_selection dnd_selection; struct wlr_xwayland_surface *focus_surface; diff --git a/xwayland/selection/dnd.c b/xwayland/selection/dnd.c index 16941558..ee9a23a6 100644 --- a/xwayland/selection/dnd.c +++ b/xwayland/selection/dnd.c @@ -64,7 +64,7 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { struct wl_array *mime_types = &drag->source->mime_types; xcb_client_message_data_t data = { 0 }; - data.data32[0] = xwm->dnd_window; + data.data32[0] = xwm->dnd_selection.window; data.data32[1] = XDND_VERSION << 24; // If we have 3 MIME types or less, we can send them directly in the @@ -94,7 +94,7 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { xcb_change_property(xwm->xcb_conn, XCB_PROP_MODE_REPLACE, - xwm->dnd_window, + xwm->dnd_selection.window, xwm->atoms[DND_TYPE_LIST], XCB_ATOM_ATOM, 32, // format @@ -110,7 +110,7 @@ static void xwm_dnd_send_position(struct wlr_xwm *xwm, uint32_t time, int16_t x, assert(drag != NULL); xcb_client_message_data_t data = { 0 }; - data.data32[0] = xwm->dnd_window; + data.data32[0] = xwm->dnd_selection.window; data.data32[2] = (x << 16) | y; data.data32[3] = time; data.data32[4] = @@ -126,7 +126,7 @@ static void xwm_dnd_send_drop(struct wlr_xwm *xwm, uint32_t time) { assert(dest != NULL); xcb_client_message_data_t data = { 0 }; - data.data32[0] = xwm->dnd_window; + data.data32[0] = xwm->dnd_selection.window; data.data32[2] = time; xwm_dnd_send_event(xwm, xwm->atoms[DND_DROP], &data); @@ -139,7 +139,7 @@ static void xwm_dnd_send_leave(struct wlr_xwm *xwm) { assert(dest != NULL); xcb_client_message_data_t data = { 0 }; - data.data32[0] = xwm->dnd_window; + data.data32[0] = xwm->dnd_selection.window; xwm_dnd_send_event(xwm, xwm->atoms[DND_LEAVE], &data); } @@ -151,7 +151,7 @@ static void xwm_dnd_send_leave(struct wlr_xwm *xwm) { assert(dest != NULL); xcb_client_message_data_t data = { 0 }; - data.data32[0] = xwm->dnd_window; + data.data32[0] = xwm->dnd_selection.window; data.data32[1] = drag->source->accepted; if (drag->source->accepted) { diff --git a/xwayland/selection/selection.c b/xwayland/selection/selection.c index 0996f94d..9cb8c455 100644 --- a/xwayland/selection/selection.c +++ b/xwayland/selection/selection.c @@ -174,12 +174,65 @@ int xwm_handle_selection_event(struct wlr_xwm *xwm, void xwm_selection_init(struct wlr_xwm_selection *selection, struct wlr_xwm *xwm, xcb_atom_t atom) { - selection->xwm = xwm; - selection->atom = atom; - selection->window = xwm->selection_window; wl_list_init(&selection->incoming); wl_list_init(&selection->outgoing); + selection->xwm = xwm; + selection->atom = atom; + selection->window = xcb_generate_id(xwm->xcb_conn); + + if (atom == xwm->atoms[DND_SELECTION]) { + xcb_create_window( + xwm->xcb_conn, + XCB_COPY_FROM_PARENT, + selection->window, + xwm->screen->root, + 0, 0, + 8192, 8192, + 0, + XCB_WINDOW_CLASS_INPUT_ONLY, + xwm->screen->root_visual, + XCB_CW_EVENT_MASK, + (uint32_t[]){ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE + } + ); + + xcb_change_property( + xwm->xcb_conn, + XCB_PROP_MODE_REPLACE, + selection->window, + xwm->atoms[DND_AWARE], + XCB_ATOM_ATOM, + 32, // format + 1, + &(uint32_t){XDND_VERSION} + ); + } else { + xcb_create_window( + xwm->xcb_conn, + XCB_COPY_FROM_PARENT, + selection->window, + xwm->screen->root, + 0, 0, + 10, 10, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + xwm->screen->root_visual, + XCB_CW_EVENT_MASK, + (uint32_t[]){ + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE + } + ); + + if (atom == xwm->atoms[CLIPBOARD]) { + xcb_set_selection_owner(xwm->xcb_conn, selection->window, + xwm->atoms[CLIPBOARD_MANAGER], XCB_TIME_CURRENT_TIME); + } else { + assert(atom == xwm->atoms[PRIMARY]); + } + } + uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | @@ -203,6 +256,8 @@ void xwm_selection_finish(struct wlr_xwm_selection *selection) { wl_list_for_each_safe(incoming, tmp, &selection->incoming, link) { xwm_selection_transfer_destroy(incoming); } + + xcb_destroy_window(selection->xwm->xcb_conn, selection->window); } static void xwm_selection_set_owner(struct wlr_xwm_selection *selection, diff --git a/xwayland/xwm.c b/xwayland/xwm.c index be1436a5..cfc192f5 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -864,8 +864,9 @@ static void xsurface_unmap(struct wlr_xwayland_surface *surface) { static void xwm_handle_create_notify(struct wlr_xwm *xwm, xcb_create_notify_event_t *ev) { if (ev->window == xwm->window || - ev->window == xwm->selection_window || - ev->window == xwm->dnd_window) { + ev->window == xwm->primary_selection.window || + ev->window == xwm->clipboard_selection.window || + ev->window == xwm->dnd_selection.window) { return; } @@ -1588,14 +1589,6 @@ void xwm_destroy(struct wlr_xwm *xwm) { xwm_selection_finish(&xwm->primary_selection); xwm_selection_finish(&xwm->dnd_selection); - if (xwm->selection_window) { - xcb_destroy_window(xwm->xcb_conn, xwm->selection_window); - } - - if (xwm->dnd_window) { - xcb_destroy_window(xwm->xcb_conn, xwm->dnd_window); - } - if (xwm->seat) { if (xwm->seat->selection_source && data_source_is_xwayland(xwm->seat->selection_source)) { @@ -1927,56 +1920,8 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) { xwm_set_net_active_window(xwm, XCB_WINDOW_NONE); - // Clipboard and primary selection - xwm->selection_window = xcb_generate_id(xwm->xcb_conn); - xcb_create_window( - xwm->xcb_conn, - XCB_COPY_FROM_PARENT, - xwm->selection_window, - xwm->screen->root, - 0, 0, - 10, 10, - 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, - xwm->screen->root_visual, - XCB_CW_EVENT_MASK, (uint32_t[]){ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE - } - ); - - xcb_set_selection_owner(xwm->xcb_conn, xwm->selection_window, - xwm->atoms[CLIPBOARD_MANAGER], XCB_TIME_CURRENT_TIME); - xwm_selection_init(&xwm->clipboard_selection, xwm, xwm->atoms[CLIPBOARD]); xwm_selection_init(&xwm->primary_selection, xwm, xwm->atoms[PRIMARY]); - - // Drag'n'drop - xwm->dnd_window = xcb_generate_id(xwm->xcb_conn); - xcb_create_window( - xwm->xcb_conn, - XCB_COPY_FROM_PARENT, - xwm->dnd_window, - xwm->screen->root, - 0, 0, - 8192, 8192, - 0, - XCB_WINDOW_CLASS_INPUT_ONLY, - xwm->screen->root_visual, - XCB_CW_EVENT_MASK, (uint32_t[]){ - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE - } - ); - - xcb_change_property( - xwm->xcb_conn, - XCB_PROP_MODE_REPLACE, - xwm->dnd_window, - xwm->atoms[DND_AWARE], - XCB_ATOM_ATOM, - 32, // format - 1, &(uint32_t){XDND_VERSION} - ); - xwm_selection_init(&xwm->dnd_selection, xwm, xwm->atoms[DND_SELECTION]); xwm->compositor_new_surface.notify = handle_compositor_new_surface;