aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xwayland/selection.c82
1 files changed, 65 insertions, 17 deletions
diff --git a/xwayland/selection.c b/xwayland/selection.c
index 220736d4..f7f8d440 100644
--- a/xwayland/selection.c
+++ b/xwayland/selection.c
@@ -328,6 +328,7 @@ static void xwm_get_selection_data(struct wlr_xwm *xwm) {
struct x11_data_source {
struct wlr_data_source base;
struct wlr_xwm *xwm;
+ struct wl_array mime_types_atoms;
};
static void data_source_accept(struct wlr_data_source *source, uint32_t time,
@@ -335,24 +336,40 @@ static void data_source_accept(struct wlr_data_source *source, uint32_t time,
}
static void data_source_send(struct wlr_data_source *base,
- const char *mime_type, int32_t fd) {
+ const char *requested_mime_type, int32_t fd) {
struct x11_data_source *source = (struct x11_data_source *)base;
struct wlr_xwm *xwm = source->xwm;
- 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);
+ bool found = false;
+ xcb_atom_t mime_type_atom;
+ char **mime_type_ptr;
+ size_t i = 0;
+ wl_array_for_each(mime_type_ptr, &source->base.mime_types) {
+ char *mime_type = *mime_type_ptr;
+ if (strcmp(mime_type, requested_mime_type) == 0) {
+ found = true;
+ xcb_atom_t *atoms = source->mime_types_atoms.data;
+ mime_type_atom = atoms[i];
+ break;
+ }
+ ++i;
+ }
+ if (!found) {
+ return;
+ }
- xcb_flush(xwm->xcb_conn);
+ // Get data for the utf8_string target
+ xcb_convert_selection(xwm->xcb_conn,
+ xwm->selection_window,
+ xwm->atoms[CLIPBOARD],
+ mime_type_atom,
+ xwm->atoms[WL_SELECTION],
+ XCB_TIME_CURRENT_TIME);
- fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK);
- xwm->data_source_fd = fd;
- }
+ xcb_flush(xwm->xcb_conn);
+
+ fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK);
+ xwm->data_source_fd = fd;
}
static void data_source_cancel(struct wlr_data_source *source) {
@@ -393,13 +410,45 @@ static void xwm_get_selection_targets(struct wlr_xwm *xwm) {
source->xwm = xwm;
wl_array_init(&source->base.mime_types);
+ wl_array_init(&source->mime_types_atoms);
xcb_atom_t *value = xcb_get_property_value(reply);
for (uint32_t i = 0; i < reply->value_len; i++) {
+ char *mime_type = NULL;
+
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");
+ mime_type = strdup("text/plain;charset=utf-8");
+ } else if (value[i] == xwm->atoms[TEXT]) {
+ mime_type = strdup("text/plain");
+ } else if (value[i] != xwm->atoms[TARGETS] &&
+ value[i] != xwm->atoms[TIMESTAMP]) {
+ xcb_get_atom_name_cookie_t name_cookie =
+ xcb_get_atom_name(xwm->xcb_conn, value[i]);
+ xcb_get_atom_name_reply_t *name_reply =
+ xcb_get_atom_name_reply(xwm->xcb_conn, name_cookie, NULL);
+ if (name_reply == NULL) {
+ continue;
+ }
+ char *name = xcb_get_atom_name_name(name_reply);
+ if (strchr(name, '/') != NULL) {
+ mime_type = strdup(name);
}
+ free(name_reply);
+ }
+
+ if (mime_type != NULL) {
+ char **mime_type_ptr =
+ wl_array_add(&source->base.mime_types, sizeof(*mime_type_ptr));
+ if (mime_type_ptr == NULL) {
+ break;
+ }
+ *mime_type_ptr = mime_type;
+
+ xcb_atom_t *atom_ptr =
+ wl_array_add(&source->mime_types_atoms, sizeof(*atom_ptr));
+ if (atom_ptr == NULL) {
+ break;
+ }
+ *atom_ptr = value[i];
}
}
@@ -407,7 +456,6 @@ static void xwm_get_selection_targets(struct wlr_xwm *xwm) {
wl_display_next_serial(xwm->xwayland->wl_display));
free(reply);
-
}
static void xwm_handle_selection_notify(struct wlr_xwm *xwm,