mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	xwayland: only send one target at a time
This commit is contained in:
		
							parent
							
								
									103e59703f
								
							
						
					
					
						commit
						8f84c5b05f
					
				
					 2 changed files with 117 additions and 56 deletions
				
			
		| 
						 | 
					@ -85,6 +85,7 @@ struct wlr_xwm_selection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_xwm_selection_transfer {
 | 
					struct wlr_xwm_selection_transfer {
 | 
				
			||||||
	struct wlr_xwm_selection *selection;
 | 
						struct wlr_xwm_selection *selection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool incr;
 | 
						bool incr;
 | 
				
			||||||
	bool flush_property_on_delete;
 | 
						bool flush_property_on_delete;
 | 
				
			||||||
	bool property_set;
 | 
						bool property_set;
 | 
				
			||||||
| 
						 | 
					@ -94,6 +95,7 @@ struct wlr_xwm_selection_transfer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// when sending to x11
 | 
						// when sending to x11
 | 
				
			||||||
	xcb_selection_request_event_t request;
 | 
						xcb_selection_request_event_t request;
 | 
				
			||||||
 | 
						struct wl_list outgoing_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// when receiving from x11
 | 
						// when receiving from x11
 | 
				
			||||||
	int property_start;
 | 
						int property_start;
 | 
				
			||||||
| 
						 | 
					@ -108,6 +110,7 @@ struct wlr_xwm_selection {
 | 
				
			||||||
	xcb_timestamp_t timestamp;
 | 
						xcb_timestamp_t timestamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_xwm_selection_transfer incoming;
 | 
						struct wlr_xwm_selection_transfer incoming;
 | 
				
			||||||
 | 
						struct wl_list outgoing;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_xwm {
 | 
					struct wlr_xwm {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ static int xwm_selection_flush_source_data(
 | 
				
			||||||
	return length;
 | 
						return length;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xwm_data_source_remove_source(
 | 
					static void xwm_selection_transfer_remove_source(
 | 
				
			||||||
		struct wlr_xwm_selection_transfer *transfer) {
 | 
							struct wlr_xwm_selection_transfer *transfer) {
 | 
				
			||||||
	if (transfer->source != NULL) {
 | 
						if (transfer->source != NULL) {
 | 
				
			||||||
		wl_event_source_remove(transfer->source);
 | 
							wl_event_source_remove(transfer->source);
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ static void xwm_data_source_remove_source(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xwm_data_source_close_source_fd(
 | 
					static void xwm_selection_transfer_close_source_fd(
 | 
				
			||||||
		struct wlr_xwm_selection_transfer *transfer) {
 | 
							struct wlr_xwm_selection_transfer *transfer) {
 | 
				
			||||||
	if (transfer->source_fd >= 0) {
 | 
						if (transfer->source_fd >= 0) {
 | 
				
			||||||
		close(transfer->source_fd);
 | 
							close(transfer->source_fd);
 | 
				
			||||||
| 
						 | 
					@ -95,6 +95,27 @@ static void xwm_data_source_close_source_fd(
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void xwm_selection_transfer_start_outgoing(
 | 
				
			||||||
 | 
							struct wlr_xwm_selection_transfer *transfer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void xwm_selection_transfer_destroy_outgoing(
 | 
				
			||||||
 | 
							struct wlr_xwm_selection_transfer *transfer) {
 | 
				
			||||||
 | 
						wl_list_remove(&transfer->outgoing_link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Start next queued transfer
 | 
				
			||||||
 | 
						struct wlr_xwm_selection_transfer *first = NULL;
 | 
				
			||||||
 | 
						if (!wl_list_empty(&transfer->selection->outgoing)) {
 | 
				
			||||||
 | 
							first = wl_container_of(transfer->selection->outgoing.prev, first,
 | 
				
			||||||
 | 
								outgoing_link);
 | 
				
			||||||
 | 
							xwm_selection_transfer_start_outgoing(first);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xwm_selection_transfer_remove_source(transfer);
 | 
				
			||||||
 | 
						xwm_selection_transfer_close_source_fd(transfer);
 | 
				
			||||||
 | 
						wl_array_release(&transfer->source_data);
 | 
				
			||||||
 | 
						free(transfer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
					static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
	struct wlr_xwm_selection_transfer *transfer = data;
 | 
						struct wlr_xwm_selection_transfer *transfer = data;
 | 
				
			||||||
	struct wlr_xwm *xwm = transfer->selection->xwm;
 | 
						struct wlr_xwm *xwm = transfer->selection->xwm;
 | 
				
			||||||
| 
						 | 
					@ -137,14 +158,14 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
			transfer->incr = true;
 | 
								transfer->incr = true;
 | 
				
			||||||
			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_selection_transfer_remove_source(transfer);
 | 
				
			||||||
			xwm_selection_send_notify(xwm, &transfer->request, true);
 | 
								xwm_selection_send_notify(xwm, &transfer->request, true);
 | 
				
			||||||
		} 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			transfer->flush_property_on_delete = true;
 | 
								transfer->flush_property_on_delete = true;
 | 
				
			||||||
			xwm_data_source_remove_source(transfer);
 | 
								xwm_selection_transfer_remove_source(transfer);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			wlr_log(L_DEBUG, "got %zu bytes, property deleted, setting new "
 | 
								wlr_log(L_DEBUG, "got %zu bytes, property deleted, setting new "
 | 
				
			||||||
				"property", transfer->source_data.size);
 | 
									"property", transfer->source_data.size);
 | 
				
			||||||
| 
						 | 
					@ -154,11 +175,7 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
		wlr_log(L_DEBUG, "non-incr transfer complete");
 | 
							wlr_log(L_DEBUG, "non-incr transfer complete");
 | 
				
			||||||
		xwm_selection_flush_source_data(transfer);
 | 
							xwm_selection_flush_source_data(transfer);
 | 
				
			||||||
		xwm_selection_send_notify(xwm, &transfer->request, true);
 | 
							xwm_selection_send_notify(xwm, &transfer->request, true);
 | 
				
			||||||
		xcb_flush(xwm->xcb_conn);
 | 
							xwm_selection_transfer_destroy_outgoing(transfer);
 | 
				
			||||||
		xwm_data_source_remove_source(transfer);
 | 
					 | 
				
			||||||
		xwm_data_source_close_source_fd(transfer);
 | 
					 | 
				
			||||||
		wl_array_release(&transfer->source_data);
 | 
					 | 
				
			||||||
		transfer->request.requestor = XCB_NONE;
 | 
					 | 
				
			||||||
	} else if (len == 0 && transfer->incr) {
 | 
						} else if (len == 0 && transfer->incr) {
 | 
				
			||||||
		wlr_log(L_DEBUG, "incr transfer complete");
 | 
							wlr_log(L_DEBUG, "incr transfer complete");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,9 +188,7 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
				"property", transfer->source_data.size);
 | 
									"property", transfer->source_data.size);
 | 
				
			||||||
			xwm_selection_flush_source_data(transfer);
 | 
								xwm_selection_flush_source_data(transfer);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		xcb_flush(xwm->xcb_conn);
 | 
							xwm_selection_transfer_destroy_outgoing(transfer);
 | 
				
			||||||
		xwm_data_source_remove_source(transfer);
 | 
					 | 
				
			||||||
		xwm_data_source_close_source_fd(transfer);
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		wlr_log(L_DEBUG, "nothing happened, buffered the bytes");
 | 
							wlr_log(L_DEBUG, "nothing happened, buffered the bytes");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -182,9 +197,7 @@ static int xwm_data_source_read(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_out:
 | 
					error_out:
 | 
				
			||||||
	xwm_selection_send_notify(xwm, &transfer->request, false);
 | 
						xwm_selection_send_notify(xwm, &transfer->request, false);
 | 
				
			||||||
	xwm_data_source_remove_source(transfer);
 | 
						xwm_selection_transfer_destroy_outgoing(transfer);
 | 
				
			||||||
	xwm_data_source_close_source_fd(transfer);
 | 
					 | 
				
			||||||
	wl_array_release(&transfer->source_data);
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -240,6 +253,15 @@ static struct wl_array *xwm_selection_source_get_mime_types(
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void xwm_selection_transfer_start_outgoing(
 | 
				
			||||||
 | 
							struct wlr_xwm_selection_transfer *transfer) {
 | 
				
			||||||
 | 
						struct wlr_xwm *xwm = transfer->selection->xwm;
 | 
				
			||||||
 | 
						struct wl_event_loop *loop =
 | 
				
			||||||
 | 
							wl_display_get_event_loop(xwm->xwayland->wl_display);
 | 
				
			||||||
 | 
						transfer->source = wl_event_loop_add_fd(loop, transfer->source_fd,
 | 
				
			||||||
 | 
							WL_EVENT_READABLE, xwm_data_source_read, transfer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Read the Wayland selection and send it to an Xwayland client.
 | 
					 * Read the Wayland selection and send it to an Xwayland client.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -293,15 +315,16 @@ static void xwm_selection_send_data(struct wlr_xwm_selection *selection,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	transfer->source_fd = p[0];
 | 
						transfer->source_fd = p[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_event_loop *loop =
 | 
					 | 
				
			||||||
		wl_display_get_event_loop(selection->xwm->xwayland->wl_display);
 | 
					 | 
				
			||||||
	transfer->source = wl_event_loop_add_fd(loop, transfer->source_fd,
 | 
					 | 
				
			||||||
		WL_EVENT_READABLE, xwm_data_source_read, transfer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_log(L_DEBUG, "Sending Wayland selection %u to Xwayland window with "
 | 
						wlr_log(L_DEBUG, "Sending Wayland selection %u to Xwayland window with "
 | 
				
			||||||
		"MIME type %s", req->target, mime_type);
 | 
							"MIME type %s, target %u", req->target, mime_type, req->target);
 | 
				
			||||||
	xwm_selection_source_send(selection, mime_type, p[1]);
 | 
						xwm_selection_source_send(selection, mime_type, p[1]);
 | 
				
			||||||
	// TODO close(p[1]);
 | 
					
 | 
				
			||||||
 | 
						wl_list_insert(&selection->outgoing, &transfer->outgoing_link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We can only handle one transfer at a time
 | 
				
			||||||
 | 
						if (wl_list_length(&selection->outgoing) == 1) {
 | 
				
			||||||
 | 
							xwm_selection_transfer_start_outgoing(transfer);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static xcb_atom_t xwm_mime_type_to_atom(struct wlr_xwm *xwm, char *mime_type) {
 | 
					static xcb_atom_t xwm_mime_type_to_atom(struct wlr_xwm *xwm, char *mime_type) {
 | 
				
			||||||
| 
						 | 
					@ -523,10 +546,7 @@ static char *xwm_mime_type_from_atom(struct wlr_xwm *xwm, xcb_atom_t atom) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xwm_handle_selection_request(struct wlr_xwm *xwm,
 | 
					static void xwm_handle_selection_request(struct wlr_xwm *xwm,
 | 
				
			||||||
		xcb_generic_event_t *event) {
 | 
							xcb_selection_request_event_t *req) {
 | 
				
			||||||
	xcb_selection_request_event_t *req =
 | 
					 | 
				
			||||||
		(xcb_selection_request_event_t *) event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_log(L_DEBUG, "XCB_SELECTION_REQUEST (time=%u owner=%u, requestor=%u "
 | 
						wlr_log(L_DEBUG, "XCB_SELECTION_REQUEST (time=%u owner=%u, requestor=%u "
 | 
				
			||||||
		"selection=%u, target=%u, property=%u)",
 | 
							"selection=%u, target=%u, property=%u)",
 | 
				
			||||||
		req->time, req->owner, req->requestor, req->selection, req->target,
 | 
							req->time, req->owner, req->requestor, req->selection, req->target,
 | 
				
			||||||
| 
						 | 
					@ -582,7 +602,45 @@ static void xwm_handle_selection_request(struct wlr_xwm *xwm,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xwm_data_source_destroy_property_reply(
 | 
					static int xwm_handle_selection_property_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
 | 
							xcb_property_notify_event_t *event) {
 | 
				
			||||||
 | 
						struct wlr_xwm_selection *selections[] = {
 | 
				
			||||||
 | 
							&xwm->clipboard_selection,
 | 
				
			||||||
 | 
							&xwm->primary_selection,
 | 
				
			||||||
 | 
							&xwm->dnd_selection,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (size_t i = 0; i < sizeof(selections)/sizeof(selections[0]); ++i) {
 | 
				
			||||||
 | 
							struct wlr_xwm_selection *selection = selections[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (event->window == xwm->selection_window) {
 | 
				
			||||||
 | 
								if (event->state == XCB_PROPERTY_NEW_VALUE &&
 | 
				
			||||||
 | 
										event->atom == xwm->atoms[WL_SELECTION] &&
 | 
				
			||||||
 | 
										selection->incoming.incr) {
 | 
				
			||||||
 | 
									wlr_log(L_DEBUG, "get incr chunk");
 | 
				
			||||||
 | 
									// TODO
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct wlr_xwm_selection_transfer *outgoing;
 | 
				
			||||||
 | 
							wl_list_for_each(outgoing, &selection->outgoing, outgoing_link) {
 | 
				
			||||||
 | 
								if (event->window == outgoing->request.requestor) {
 | 
				
			||||||
 | 
									if (event->state == XCB_PROPERTY_DELETE &&
 | 
				
			||||||
 | 
											event->atom == outgoing->request.property &&
 | 
				
			||||||
 | 
											outgoing->incr) {
 | 
				
			||||||
 | 
										wlr_log(L_DEBUG, "send incr chunk");
 | 
				
			||||||
 | 
										// TODO
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void xwm_selection_transfer_destroy_property_reply(
 | 
				
			||||||
		struct wlr_xwm_selection_transfer *transfer) {
 | 
							struct wlr_xwm_selection_transfer *transfer) {
 | 
				
			||||||
	free(transfer->property_reply);
 | 
						free(transfer->property_reply);
 | 
				
			||||||
	transfer->property_reply = NULL;
 | 
						transfer->property_reply = NULL;
 | 
				
			||||||
| 
						 | 
					@ -601,9 +659,9 @@ static int xwm_data_source_write(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ssize_t len = write(fd, property + transfer->property_start, remainder);
 | 
						ssize_t len = write(fd, property + transfer->property_start, remainder);
 | 
				
			||||||
	if (len == -1) {
 | 
						if (len == -1) {
 | 
				
			||||||
		xwm_data_source_destroy_property_reply(transfer);
 | 
							xwm_selection_transfer_destroy_property_reply(transfer);
 | 
				
			||||||
		xwm_data_source_remove_source(transfer);
 | 
							xwm_selection_transfer_remove_source(transfer);
 | 
				
			||||||
		xwm_data_source_close_source_fd(transfer);
 | 
							xwm_selection_transfer_close_source_fd(transfer);
 | 
				
			||||||
		wlr_log(L_ERROR, "write error to target fd: %m");
 | 
							wlr_log(L_ERROR, "write error to target fd: %m");
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -614,15 +672,15 @@ static int xwm_data_source_write(int fd, uint32_t mask, void *data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	transfer->property_start += len;
 | 
						transfer->property_start += len;
 | 
				
			||||||
	if (len == remainder) {
 | 
						if (len == remainder) {
 | 
				
			||||||
		xwm_data_source_destroy_property_reply(transfer);
 | 
							xwm_selection_transfer_destroy_property_reply(transfer);
 | 
				
			||||||
		xwm_data_source_remove_source(transfer);
 | 
							xwm_selection_transfer_remove_source(transfer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (transfer->incr) {
 | 
							if (transfer->incr) {
 | 
				
			||||||
			xcb_delete_property(xwm->xcb_conn, transfer->selection->window,
 | 
								xcb_delete_property(xwm->xcb_conn, transfer->selection->window,
 | 
				
			||||||
				xwm->atoms[WL_SELECTION]);
 | 
									xwm->atoms[WL_SELECTION]);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			wlr_log(L_DEBUG, "transfer complete");
 | 
								wlr_log(L_DEBUG, "transfer complete");
 | 
				
			||||||
			xwm_data_source_close_source_fd(transfer);
 | 
								xwm_selection_transfer_close_source_fd(transfer);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -906,23 +964,20 @@ static void xwm_selection_get_targets(struct wlr_xwm_selection *selection) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xwm_handle_selection_notify(struct wlr_xwm *xwm,
 | 
					static void xwm_handle_selection_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
		xcb_generic_event_t *event) {
 | 
							xcb_selection_notify_event_t *event) {
 | 
				
			||||||
	xcb_selection_notify_event_t *selection_notify =
 | 
					 | 
				
			||||||
		(xcb_selection_notify_event_t *) event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_log(L_DEBUG, "XCB_SELECTION_NOTIFY (selection=%u, property=%u, target=%u)",
 | 
						wlr_log(L_DEBUG, "XCB_SELECTION_NOTIFY (selection=%u, property=%u, target=%u)",
 | 
				
			||||||
		selection_notify->selection, selection_notify->property,
 | 
							event->selection, event->property,
 | 
				
			||||||
		selection_notify->target);
 | 
							event->target);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_xwm_selection *selection =
 | 
						struct wlr_xwm_selection *selection =
 | 
				
			||||||
		xwm_get_selection(xwm, selection_notify->selection);
 | 
							xwm_get_selection(xwm, event->selection);
 | 
				
			||||||
	if (selection == NULL) {
 | 
						if (selection == NULL) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (selection_notify->property == XCB_ATOM_NONE) {
 | 
						if (event->property == XCB_ATOM_NONE) {
 | 
				
			||||||
		wlr_log(L_ERROR, "convert selection failed");
 | 
							wlr_log(L_ERROR, "convert selection failed");
 | 
				
			||||||
	} else if (selection_notify->target == xwm->atoms[TARGETS]) {
 | 
						} else if (event->target == xwm->atoms[TARGETS]) {
 | 
				
			||||||
		// No xwayland surface focused, deny access to clipboard
 | 
							// No xwayland surface focused, deny access to clipboard
 | 
				
			||||||
		if (xwm->focus_surface == NULL) {
 | 
							if (xwm->focus_surface == NULL) {
 | 
				
			||||||
			wlr_log(L_DEBUG, "denying write access to clipboard: "
 | 
								wlr_log(L_DEBUG, "denying write access to clipboard: "
 | 
				
			||||||
| 
						 | 
					@ -938,20 +993,17 @@ static void xwm_handle_selection_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
 | 
					static int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
		xcb_generic_event_t *event) {
 | 
							xcb_xfixes_selection_notify_event_t *event) {
 | 
				
			||||||
	xcb_xfixes_selection_notify_event_t *xfixes_selection_notify =
 | 
					 | 
				
			||||||
		(xcb_xfixes_selection_notify_event_t *)event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_log(L_DEBUG, "XCB_XFIXES_SELECTION_NOTIFY (selection=%u, owner=%u)",
 | 
						wlr_log(L_DEBUG, "XCB_XFIXES_SELECTION_NOTIFY (selection=%u, owner=%u)",
 | 
				
			||||||
		xfixes_selection_notify->selection, xfixes_selection_notify->owner);
 | 
							event->selection, event->owner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_xwm_selection *selection =
 | 
						struct wlr_xwm_selection *selection =
 | 
				
			||||||
		xwm_get_selection(xwm, xfixes_selection_notify->selection);
 | 
							xwm_get_selection(xwm, event->selection);
 | 
				
			||||||
	if (selection == NULL) {
 | 
						if (selection == NULL) {
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (xfixes_selection_notify->owner == XCB_WINDOW_NONE) {
 | 
						if (event->owner == XCB_WINDOW_NONE) {
 | 
				
			||||||
		if (selection->owner != selection->window) {
 | 
							if (selection->owner != selection->window) {
 | 
				
			||||||
			// A real X client selection went away, not our
 | 
								// A real X client selection went away, not our
 | 
				
			||||||
			// proxy selection
 | 
								// proxy selection
 | 
				
			||||||
| 
						 | 
					@ -973,13 +1025,13 @@ static int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	selection->owner = xfixes_selection_notify->owner;
 | 
						selection->owner = event->owner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// We have to use XCB_TIME_CURRENT_TIME when we claim the
 | 
						// We have to use XCB_TIME_CURRENT_TIME when we claim the
 | 
				
			||||||
	// selection, so grab the actual timestamp here so we can
 | 
						// selection, so grab the actual timestamp here so we can
 | 
				
			||||||
	// answer TIMESTAMP conversion requests correctly.
 | 
						// answer TIMESTAMP conversion requests correctly.
 | 
				
			||||||
	if (xfixes_selection_notify->owner == selection->window) {
 | 
						if (event->owner == selection->window) {
 | 
				
			||||||
		selection->timestamp = xfixes_selection_notify->timestamp;
 | 
							selection->timestamp = event->timestamp;
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -990,7 +1042,7 @@ static int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm,
 | 
				
			||||||
		selection->atom,
 | 
							selection->atom,
 | 
				
			||||||
		xwm->atoms[TARGETS],
 | 
							xwm->atoms[TARGETS],
 | 
				
			||||||
		xwm->atoms[WL_SELECTION],
 | 
							xwm->atoms[WL_SELECTION],
 | 
				
			||||||
		xfixes_selection_notify->timestamp);
 | 
							event->timestamp);
 | 
				
			||||||
	xcb_flush(xwm->xcb_conn);
 | 
						xcb_flush(xwm->xcb_conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
| 
						 | 
					@ -1006,17 +1058,22 @@ int xwm_handle_selection_event(struct wlr_xwm *xwm,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (event->response_type & ~0x80) {
 | 
						switch (event->response_type & ~0x80) {
 | 
				
			||||||
	case XCB_SELECTION_NOTIFY:
 | 
						case XCB_SELECTION_NOTIFY:
 | 
				
			||||||
		xwm_handle_selection_notify(xwm, event);
 | 
							xwm_handle_selection_notify(xwm, (xcb_selection_notify_event_t *)event);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
 | 
						case XCB_PROPERTY_NOTIFY:
 | 
				
			||||||
 | 
							return xwm_handle_selection_property_notify(xwm,
 | 
				
			||||||
 | 
								(xcb_property_notify_event_t *)event);
 | 
				
			||||||
	case XCB_SELECTION_REQUEST:
 | 
						case XCB_SELECTION_REQUEST:
 | 
				
			||||||
		xwm_handle_selection_request(xwm, event);
 | 
							xwm_handle_selection_request(xwm,
 | 
				
			||||||
 | 
								(xcb_selection_request_event_t *)event);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (event->response_type - xwm->xfixes->first_event) {
 | 
						switch (event->response_type - xwm->xfixes->first_event) {
 | 
				
			||||||
	case XCB_XFIXES_SELECTION_NOTIFY:
 | 
						case XCB_XFIXES_SELECTION_NOTIFY:
 | 
				
			||||||
		// an X11 window has copied something to the clipboard
 | 
							// an X11 window has copied something to the clipboard
 | 
				
			||||||
		return xwm_handle_xfixes_selection_notify(xwm, event);
 | 
							return xwm_handle_xfixes_selection_notify(xwm,
 | 
				
			||||||
 | 
								(xcb_xfixes_selection_notify_event_t *)event);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1100,6 +1157,7 @@ static void selection_init(struct wlr_xwm *xwm,
 | 
				
			||||||
	selection->atom = atom;
 | 
						selection->atom = atom;
 | 
				
			||||||
	selection->window = xwm->selection_window;
 | 
						selection->window = xwm->selection_window;
 | 
				
			||||||
	selection->incoming.selection = selection;
 | 
						selection->incoming.selection = selection;
 | 
				
			||||||
 | 
						wl_list_init(&selection->outgoing);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t mask =
 | 
						uint32_t mask =
 | 
				
			||||||
		XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
 | 
							XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue