24#include "uwac-utils.h" 
   34#include <sys/timerfd.h> 
   38static 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);
 
   62static const struct wl_data_offer_listener data_offer_listener = { .offer = data_offer_offer };
 
   64static 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;
 
   90static void data_device_selection(
void* data, 
struct wl_data_device* data_device,
 
   91                                  struct wl_data_offer* data_offer)
 
   95static const struct wl_data_device_listener data_device_listener = {
 
   96  .data_offer = data_device_data_offer, .selection = data_device_selection
 
  100static void data_source_target_handler(
void* data, 
struct wl_data_source* data_source,
 
  101                                       const char* mime_type)
 
  105static 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);
 
  112static 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);
 
  118static 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
 
  124static void UwacRegisterDeviceListener(UwacSeat* s)
 
  126  wl_data_device_add_listener(s->data_device, &data_device_listener, s);
 
  129static 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);
 
  139UwacReturnCode 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;
 
  168UwacReturnCode 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);
 
  179UwacReturnCode UwacClipboardOfferCreate(UwacSeat* seat, 
const char* mime)
 
  182    return UWAC_ERROR_INTERNAL;
 
  184  wl_data_source_offer(seat->data_source, mime);
 
  188static void callback_done(
void* data, 
struct wl_callback* callback, uint32_t serial)
 
  190  *(uint32_t*)data = serial;
 
  193static const struct wl_callback_listener callback_listener = { .done = callback_done };
 
  195static 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);
 
  210UwacReturnCode 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;
 
  227void* 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);