23 #include "uwac-priv.h"
24 #include "uwac-utils.h"
34 #include <sys/timerfd.h>
35 #include <sys/epoll.h>
38 static void data_offer_offer(
void* data,
struct wl_data_offer* data_offer,
39 const char* offered_mime_type)
41 UwacSeat* seat = (UwacSeat*)data;
44 if (!seat->ignore_announcement)
46 UwacClipboardEvent*
event =
47 (UwacClipboardEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_CLIPBOARD_OFFER);
51 assert(uwacErrorHandler(seat->display, UWAC_ERROR_INTERNAL,
52 "failed to allocate a clipboard event\n"));
57 (void)snprintf(event->mime,
sizeof(event->mime),
"%s", offered_mime_type);
62 static const struct wl_data_offer_listener data_offer_listener = { .offer = data_offer_offer };
64 static void data_device_data_offer(
void* data,
struct wl_data_device* data_device,
65 struct wl_data_offer* data_offer)
67 UwacSeat* seat = (UwacSeat*)data;
70 if (!seat->ignore_announcement)
72 UwacClipboardEvent*
event =
73 (UwacClipboardEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_CLIPBOARD_SELECT);
77 assert(uwacErrorHandler(seat->display, UWAC_ERROR_INTERNAL,
78 "failed to allocate a close event\n"));
83 wl_data_offer_add_listener(data_offer, &data_offer_listener, data);
84 seat->offer = data_offer;
90 static void data_device_selection(
void* data,
struct wl_data_device* data_device,
91 struct wl_data_offer* data_offer)
95 static const struct wl_data_device_listener data_device_listener = {
96 .data_offer = data_device_data_offer, .selection = data_device_selection
100 static void data_source_target_handler(
void* data,
struct wl_data_source* data_source,
101 const char* mime_type)
105 static void data_source_send_handler(
void* data,
struct wl_data_source* data_source,
106 const char* mime_type,
int fd)
108 UwacSeat* seat = (UwacSeat*)data;
109 seat->transfer_data(seat, seat->data_context, mime_type, fd);
112 static void data_source_cancelled_handler(
void* data,
struct wl_data_source* data_source)
114 UwacSeat* seat = (UwacSeat*)data;
115 seat->cancel_data(seat, seat->data_context);
118 static const struct wl_data_source_listener data_source_listener = {
119 .target = data_source_target_handler,
120 .send = data_source_send_handler,
121 .cancelled = data_source_cancelled_handler
124 static void UwacRegisterDeviceListener(UwacSeat* s)
126 wl_data_device_add_listener(s->data_device, &data_device_listener, s);
129 static UwacReturnCode UwacCreateDataSource(UwacSeat* s)
132 return UWAC_ERROR_INTERNAL;
134 s->data_source = wl_data_device_manager_create_data_source(s->display->data_device_manager);
135 wl_data_source_add_listener(s->data_source, &data_source_listener, s);
139 UwacReturnCode UwacSeatRegisterClipboard(UwacSeat* s)
141 UwacClipboardEvent*
event = NULL;
144 return UWAC_ERROR_INTERNAL;
146 if (!s->display->data_device_manager || !s->data_device)
147 return UWAC_NOT_ENOUGH_RESOURCES;
149 UwacRegisterDeviceListener(s);
151 UwacReturnCode rc = UwacCreateDataSource(s);
153 if (rc != UWAC_SUCCESS)
155 event = (UwacClipboardEvent*)UwacDisplayNewEvent(s->display, UWAC_EVENT_CLIPBOARD_AVAILABLE);
159 assert(uwacErrorHandler(s->display, UWAC_ERROR_INTERNAL,
160 "failed to allocate a clipboard event\n"));
161 return UWAC_ERROR_INTERNAL;
168 UwacReturnCode UwacClipboardOfferDestroy(UwacSeat* seat)
171 return UWAC_ERROR_INTERNAL;
173 if (seat->data_source)
174 wl_data_source_destroy(seat->data_source);
176 return UwacCreateDataSource(seat);
179 UwacReturnCode UwacClipboardOfferCreate(UwacSeat* seat,
const char* mime)
182 return UWAC_ERROR_INTERNAL;
184 wl_data_source_offer(seat->data_source, mime);
188 static void callback_done(
void* data,
struct wl_callback* callback, uint32_t serial)
190 *(uint32_t*)data = serial;
193 static const struct wl_callback_listener callback_listener = { .done = callback_done };
195 static uint32_t get_serial(UwacSeat* s)
197 struct wl_callback* callback = NULL;
199 callback = wl_display_sync(s->display->display);
200 wl_callback_add_listener(callback, &callback_listener, &serial);
204 wl_display_dispatch(s->display->display);
210 UwacReturnCode UwacClipboardOfferAnnounce(UwacSeat* seat,
void* context,
211 UwacDataTransferHandler transfer,
212 UwacCancelDataTransferHandler cancel)
215 return UWAC_ERROR_INTERNAL;
217 seat->data_context = context;
218 seat->transfer_data = transfer;
219 seat->cancel_data = cancel;
220 seat->ignore_announcement =
true;
221 wl_data_device_set_selection(seat->data_device, seat->data_source, get_serial(seat));
222 wl_display_roundtrip(seat->display->display);
223 seat->ignore_announcement =
false;
227 void* UwacClipboardDataGet(UwacSeat* seat,
const char* mime,
size_t* size)
233 int pipefd[2] = { 0 };
235 if (!seat || !mime || !size || !seat->offer)
239 if (pipe(pipefd) != 0)
242 wl_data_offer_receive(seat->offer, mime, pipefd[1]);
244 wl_display_roundtrip(seat->display->display);
245 wl_display_flush(seat->display->display);
249 if (alloc >= SIZE_MAX - 1024)
253 void* tmp = xrealloc(data, alloc);
262 r = read(pipefd[0], &data[pos], alloc - pos);