xwm: get selection data

This commit is contained in:
Tony Crisci 2017-11-21 18:25:21 -05:00
parent 39e2ea8420
commit ea6f77b484
3 changed files with 94 additions and 1 deletions

View file

@ -1,5 +1,6 @@
#define _XOPEN_SOURCE 700 #define _XOPEN_SOURCE 700
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <xcb/xfixes.h> #include <xcb/xfixes.h>
#include <fcntl.h> #include <fcntl.h>
@ -35,8 +36,95 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm,
return; return;
} }
static int writable_callback(int fd, uint32_t mask, void *data) {
struct wlr_xwm *xwm = data;
unsigned char *property = xcb_get_property_value(xwm->property_reply);
int remainder = xcb_get_property_value_length(xwm->property_reply) -
xwm->property_start;
int len = write(fd, property + xwm->property_start, remainder);
if (len == -1) {
free(xwm->property_reply);
xwm->property_reply = NULL;
if (xwm->property_source) {
wl_event_source_remove(xwm->property_source);
}
xwm->property_source = NULL;
close(fd);
wlr_log(L_ERROR, "write error to target fd: %m\n");
return 1;
}
wlr_log(L_DEBUG, "wrote %d (chunk size %d) of %d bytes\n",
xwm->property_start + len,
len, xcb_get_property_value_length(xwm->property_reply));
xwm->property_start += len;
if (len == remainder) {
free(xwm->property_reply);
xwm->property_reply = NULL;
if (xwm->property_source) {
wl_event_source_remove(xwm->property_source);
}
xwm->property_source = NULL;
if (xwm->incr) {
xcb_delete_property(xwm->xcb_conn,
xwm->selection_window,
xwm->atoms[WL_SELECTION]);
} else {
wlr_log(L_DEBUG, "transfer complete\n");
close(fd);
}
}
return 1;
}
static void xwm_write_property(struct wlr_xwm *xwm,
xcb_get_property_reply_t *reply) {
xwm->property_start = 0;
xwm->property_reply = reply;
writable_callback(xwm->data_source_fd, WL_EVENT_WRITABLE, xwm);
if (xwm->property_reply) {
struct wl_event_loop *loop =
wl_display_get_event_loop(xwm->xwayland->wl_display);
xwm->property_source =
wl_event_loop_add_fd(loop,
xwm->data_source_fd,
WL_EVENT_WRITABLE,
writable_callback, xwm);
}
}
static void xwm_get_selection_data(struct wlr_xwm *xwm) { static void xwm_get_selection_data(struct wlr_xwm *xwm) {
wlr_log(L_DEBUG, "TODO: GET SELECTION DATA"); 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
0x1fffffff // length
);
xcb_get_property_reply_t *reply =
xcb_get_property_reply(xwm->xcb_conn, cookie, NULL);
if (reply == NULL) {
return;
} else if (reply->type == xwm->atoms[INCR]) {
xwm->incr = 1;
free(reply);
} else {
xwm->incr = 0;
// reply's ownership is transferred to wm, which is responsible
// for freeing it
xwm_write_property(xwm, reply);
}
} }
struct x11_data_source { struct x11_data_source {

View file

@ -47,6 +47,7 @@ const char *atom_map[ATOM_LAST] = {
"_WL_SELECTION", "_WL_SELECTION",
"TARGETS", "TARGETS",
"CLIPBOARD_MANAGER", "CLIPBOARD_MANAGER",
"INCR",
}; };
/* General helpers */ /* General helpers */

View file

@ -35,6 +35,7 @@ enum atom_name {
WL_SELECTION, WL_SELECTION,
TARGETS, TARGETS,
CLIPBOARD_MANAGER, CLIPBOARD_MANAGER,
INCR,
ATOM_LAST, ATOM_LAST,
}; };
@ -66,6 +67,9 @@ struct wlr_xwm {
xcb_timestamp_t selection_timestamp; xcb_timestamp_t selection_timestamp;
int incr; int incr;
int data_source_fd; int data_source_fd;
int property_start;
xcb_get_property_reply_t *property_reply;
struct wl_event_source *property_source;
struct wlr_xwayland_surface *focus_surface; struct wlr_xwayland_surface *focus_surface;