xwayland: improve xwm_selection_send_notify

This commit is contained in:
emersion 2018-04-02 21:55:09 -04:00
parent 92b74071d0
commit 103e59703f
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48

View file

@ -39,7 +39,7 @@ static enum wl_data_device_manager_dnd_action
} }
static void xwm_selection_send_notify(struct wlr_xwm *xwm, static void xwm_selection_send_notify(struct wlr_xwm *xwm,
xcb_selection_request_event_t *req, xcb_atom_t property) { xcb_selection_request_event_t *req, bool success) {
xcb_selection_notify_event_t selection_notify = { xcb_selection_notify_event_t selection_notify = {
.response_type = XCB_SELECTION_NOTIFY, .response_type = XCB_SELECTION_NOTIFY,
.sequence = 0, .sequence = 0,
@ -47,12 +47,13 @@ static void xwm_selection_send_notify(struct wlr_xwm *xwm,
.requestor = req->requestor, .requestor = req->requestor,
.selection = req->selection, .selection = req->selection,
.target = req->target, .target = req->target,
.property = property, .property = success ? req->property : XCB_ATOM_NONE,
}; };
wlr_log(L_DEBUG, "SendEvent destination=%d SelectionNotify(31) time=%d " wlr_log(L_DEBUG, "SendEvent destination=%d SelectionNotify(31) time=%d "
"requestor=%d selection=%d target=%d property=%d", req->requestor, "requestor=%d selection=%d target=%d property=%d", req->requestor,
req->time, req->requestor, req->selection, req->target, property); req->time, req->requestor, req->selection, req->target,
selection_notify.property);
xcb_send_event(xwm->xcb_conn, xcb_send_event(xwm->xcb_conn,
0, // propagate 0, // propagate
req->requestor, req->requestor,
@ -71,6 +72,7 @@ static int xwm_selection_flush_source_data(
8, // format 8, // format
transfer->source_data.size, transfer->source_data.size,
transfer->source_data.data); transfer->source_data.data);
xcb_flush(transfer->selection->xwm->xcb_conn);
transfer->property_set = true; transfer->property_set = true;
size_t length = transfer->source_data.size; size_t length = transfer->source_data.size;
transfer->source_data.size = 0; transfer->source_data.size = 0;
@ -136,8 +138,7 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
transfer->property_set = true; transfer->property_set = true;
transfer->flush_property_on_delete = true; transfer->flush_property_on_delete = true;
xwm_data_source_remove_source(transfer); xwm_data_source_remove_source(transfer);
xwm_selection_send_notify(xwm, &transfer->request, xwm_selection_send_notify(xwm, &transfer->request, true);
transfer->request.property);
} else if (transfer->property_set) { } else if (transfer->property_set) {
wlr_log(L_DEBUG, "got %zu bytes, waiting for property delete", wlr_log(L_DEBUG, "got %zu bytes, waiting for property delete",
transfer->source_data.size); transfer->source_data.size);
@ -151,10 +152,8 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
} }
} else if (len == 0 && !transfer->incr) { } else if (len == 0 && !transfer->incr) {
wlr_log(L_DEBUG, "non-incr transfer complete"); wlr_log(L_DEBUG, "non-incr transfer complete");
/* Non-incr transfer all done. */
xwm_selection_flush_source_data(transfer); xwm_selection_flush_source_data(transfer);
xwm_selection_send_notify(xwm, &transfer->request, xwm_selection_send_notify(xwm, &transfer->request, true);
transfer->request.property);
xcb_flush(xwm->xcb_conn); xcb_flush(xwm->xcb_conn);
xwm_data_source_remove_source(transfer); xwm_data_source_remove_source(transfer);
xwm_data_source_close_source_fd(transfer); xwm_data_source_close_source_fd(transfer);
@ -182,7 +181,7 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
return 1; return 1;
error_out: error_out:
xwm_selection_send_notify(xwm, &transfer->request, XCB_ATOM_NONE); xwm_selection_send_notify(xwm, &transfer->request, false);
xwm_data_source_remove_source(transfer); xwm_data_source_remove_source(transfer);
xwm_data_source_close_source_fd(transfer); xwm_data_source_close_source_fd(transfer);
wl_array_release(&transfer->source_data); wl_array_release(&transfer->source_data);
@ -251,7 +250,7 @@ static void xwm_selection_send_data(struct wlr_xwm_selection *selection,
xwm_selection_source_get_mime_types(selection); xwm_selection_source_get_mime_types(selection);
if (mime_types == NULL) { if (mime_types == NULL) {
wlr_log(L_ERROR, "not sending selection: no MIME type list available"); wlr_log(L_ERROR, "not sending selection: no MIME type list available");
xwm_selection_send_notify(selection->xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(selection->xwm, req, false);
return; return;
} }
@ -267,7 +266,7 @@ static void xwm_selection_send_data(struct wlr_xwm_selection *selection,
if (!found) { if (!found) {
wlr_log(L_ERROR, "not sending selection: " wlr_log(L_ERROR, "not sending selection: "
"requested an unsupported MIME type %s", mime_type); "requested an unsupported MIME type %s", mime_type);
xwm_selection_send_notify(selection->xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(selection->xwm, req, false);
return; return;
} }
@ -284,7 +283,7 @@ static void xwm_selection_send_data(struct wlr_xwm_selection *selection,
int p[2]; int p[2];
if (pipe(p) == -1) { if (pipe(p) == -1) {
wlr_log(L_ERROR, "pipe() failed: %m"); wlr_log(L_ERROR, "pipe() failed: %m");
xwm_selection_send_notify(selection->xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(selection->xwm, req, false);
return; return;
} }
fcntl(p[0], F_SETFD, FD_CLOEXEC); fcntl(p[0], F_SETFD, FD_CLOEXEC);
@ -459,7 +458,7 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection,
if (mime_types == NULL) { if (mime_types == NULL) {
wlr_log(L_ERROR, "not sending selection targets: " wlr_log(L_ERROR, "not sending selection targets: "
"no selection source available"); "no selection source available");
xwm_selection_send_notify(selection->xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(selection->xwm, req, false);
return; return;
} }
@ -484,7 +483,7 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection,
32, // format 32, // format
n, targets); n, targets);
xwm_selection_send_notify(selection->xwm, req, req->property); xwm_selection_send_notify(selection->xwm, req, true);
} }
static void xwm_selection_send_timestamp(struct wlr_xwm_selection *selection, static void xwm_selection_send_timestamp(struct wlr_xwm_selection *selection,
@ -497,7 +496,7 @@ static void xwm_selection_send_timestamp(struct wlr_xwm_selection *selection,
32, // format 32, // format
1, &selection->timestamp); 1, &selection->timestamp);
xwm_selection_send_notify(selection->xwm, req, req->property); xwm_selection_send_notify(selection->xwm, req, true);
} }
static struct wlr_xwm_selection *xwm_get_selection(struct wlr_xwm *xwm, static struct wlr_xwm_selection *xwm_get_selection(struct wlr_xwm *xwm,
@ -537,7 +536,7 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm,
// The wlroots clipboard should already have grabbed the first target, // The wlroots clipboard should already have grabbed the first target,
// so just send selection notify now. This isn't synchronized with the // so just send selection notify now. This isn't synchronized with the
// clipboard finishing getting the data, so there's a race here. // clipboard finishing getting the data, so there's a race here.
xwm_selection_send_notify(xwm, req, req->property); xwm_selection_send_notify(xwm, req, true);
return; return;
} }
@ -559,7 +558,7 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm,
wlr_log(L_DEBUG, "denying read access to selection %u (%s): " wlr_log(L_DEBUG, "denying read access to selection %u (%s): "
"no xwayland surface focused", selection->atom, selection_name); "no xwayland surface focused", selection->atom, selection_name);
free(selection_name); free(selection_name);
xwm_selection_send_notify(xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(xwm, req, false);
return; return;
} }
@ -568,14 +567,14 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm,
} else if (req->target == xwm->atoms[TIMESTAMP]) { } else if (req->target == xwm->atoms[TIMESTAMP]) {
xwm_selection_send_timestamp(selection, req); xwm_selection_send_timestamp(selection, req);
} else if (req->target == xwm->atoms[DELETE]) { } else if (req->target == xwm->atoms[DELETE]) {
xwm_selection_send_notify(selection->xwm, req, req->property); xwm_selection_send_notify(selection->xwm, req, true);
} else { } else {
// Send data // Send data
char *mime_type = xwm_mime_type_from_atom(xwm, req->target); char *mime_type = xwm_mime_type_from_atom(xwm, req->target);
if (mime_type == NULL) { if (mime_type == NULL) {
wlr_log(L_ERROR, "ignoring selection request: unknown atom %u", wlr_log(L_ERROR, "ignoring selection request: unknown atom %u",
req->target); req->target);
xwm_selection_send_notify(xwm, req, XCB_ATOM_NONE); xwm_selection_send_notify(xwm, req, false);
return; return;
} }
xwm_selection_send_data(selection, req, mime_type); xwm_selection_send_data(selection, req, mime_type);