From 39e2ea8420e78710906308a17a65b55e9d03dda8 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Tue, 21 Nov 2017 18:09:25 -0500 Subject: [PATCH] xwm: get selection targets --- include/wlr/xwayland.h | 1 + rootston/main.c | 6 ++++ xwayland/selection.c | 68 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 9b493d88..54558a7b 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -16,6 +16,7 @@ struct wlr_xwayland_cursor; struct wlr_xwayland { pid_t pid; int display; + struct wlr_seat *seat; int x_fd[2], wl_fd[2], wm_fd[2]; struct wl_client *client; struct wl_display *wl_display; diff --git a/rootston/main.c b/rootston/main.c index 46548094..74f9195c 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -38,6 +38,12 @@ int main(int argc, char **argv) { server.desktop = desktop_create(&server, server.config); server.input = input_create(&server, server.config); + struct roots_seat *default_seat = + roots_seat_create(server.input, ROOTS_CONFIG_DEFAULT_SEAT_NAME); + if (server.desktop->xwayland) { + server.desktop->xwayland->seat = default_seat->seat; + } + const char *socket = wl_display_add_socket_auto(server.wl_display); if (!socket) { wlr_log_errno(L_ERROR, "Unable to open wayland socket"); diff --git a/xwayland/selection.c b/xwayland/selection.c index c458f867..911a3627 100644 --- a/xwayland/selection.c +++ b/xwayland/selection.c @@ -1,3 +1,6 @@ +#define _XOPEN_SOURCE 700 +#include +#include #include #include #include "wlr/util/log.h" @@ -53,11 +56,11 @@ static void data_source_send(struct wlr_data_source *base, if (strcmp(mime_type, "text/plain;charset=utf-8") == 0) { // Get data for the utf8_string target xcb_convert_selection(xwm->xcb_conn, - xwm->selection_window, - xwm->atoms[CLIPBOARD], - xwm->atoms[UTF8_STRING], - xwm->atoms[WL_SELECTION], - XCB_TIME_CURRENT_TIME); + xwm->selection_window, + xwm->atoms[CLIPBOARD], + xwm->atoms[UTF8_STRING], + xwm->atoms[WL_SELECTION], + XCB_TIME_CURRENT_TIME); xcb_flush(xwm->xcb_conn); @@ -71,7 +74,54 @@ static void data_source_cancel(struct wlr_data_source *source) { static void xwm_get_selection_targets(struct wlr_xwm *xwm) { // set the wayland clipboard selection to the copied selection - wlr_log(L_DEBUG, "TODO: GET SELECTION TARGETS"); + + xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, + 1, // delete + xwm->selection_window, + xwm->atoms[WL_SELECTION], + XCB_GET_PROPERTY_TYPE_ANY, + 0, // offset + 4096 //length + ); + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xwm->xcb_conn, cookie, NULL); + if (reply == NULL) + return; + + if (reply->type != XCB_ATOM_ATOM) { + free(reply); + return; + } + + struct x11_data_source *source = calloc(1, sizeof(struct x11_data_source)); + if (source == NULL) { + free(reply); + return; + } + + wl_signal_init(&source->base.events.destroy); + source->base.accept = data_source_accept; + source->base.send = data_source_send; + source->base.cancel = data_source_cancel; + source->xwm = xwm; + + wl_array_init(&source->base.mime_types); + xcb_atom_t *value = xcb_get_property_value(reply); + for (uint32_t i = 0; i < reply->value_len; i++) { + if (value[i] == xwm->atoms[UTF8_STRING]) { + char **p = wl_array_add(&source->base.mime_types, sizeof *p); + if (p) { + *p = strdup("text/plain;charset=utf-8"); + } + } + } + + wlr_seat_set_selection(xwm->xwayland->seat, &source->base, + wl_display_next_serial(xwm->xwayland->wl_display)); + + free(reply); + } static void xwm_handle_selection_notify(struct wlr_xwm *xwm, @@ -133,6 +183,12 @@ static int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm, int xwm_handle_selection_event(struct wlr_xwm *xwm, xcb_generic_event_t *event) { + if (!xwm->xwayland->seat) { + wlr_log(L_DEBUG, "not handling selection events:" + "no seat assigned to xwayland"); + return 0; + } + switch (event->response_type & ~0x80) { case XCB_SELECTION_NOTIFY: xwm_handle_selection_notify(xwm, event);