static void xf_cliprdr_process_requested_data(xfInfo* xfi, boolean has_data, uint8* data, int size) { uint8* outbuf; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if (cb->incr_starts && has_data) return; if (!has_data || data == NULL) { xf_cliprdr_send_null_data_response(xfi); return; } switch (cb->format_mappings[cb->request_index].format_id) { case CB_FORMAT_RAW: case CB_FORMAT_PNG: case CB_FORMAT_JPEG: case CB_FORMAT_GIF: outbuf = xf_cliprdr_process_requested_raw(data, &size); break; case CB_FORMAT_UNICODETEXT: outbuf = xf_cliprdr_process_requested_unicodetext(data, &size); break; case CB_FORMAT_TEXT: outbuf = xf_cliprdr_process_requested_text(data, &size); break; case CB_FORMAT_DIB: outbuf = xf_cliprdr_process_requested_dib(data, &size); break; case CB_FORMAT_HTML: outbuf = xf_cliprdr_process_requested_html(data, &size); break; default: outbuf = NULL; break; } if (outbuf) { xf_cliprdr_send_data_response(xfi, outbuf, size); } else { xf_cliprdr_send_null_data_response(xfi); } /* Resend the format list, otherwise the server won't request again for the next paste */ xf_cliprdr_send_format_list(xfi); }
static void xf_cliprdr_process_cb_data_request_event(xfInfo* xfi, RDP_CB_DATA_REQUEST_EVENT* event) { int i; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; DEBUG_X11_CLIPRDR("format %d", event->format); if (xf_cliprdr_is_self_owned(xfi)) { /* CB_FORMAT_RAW */ i = 0; XChangeProperty(xfi->display, xfi->drawable, cb->property_atom, XA_INTEGER, 32, PropModeReplace, (BYTE*) &event->format, 1); } else { i = xf_cliprdr_select_format_by_id(cb, event->format); } if (i < 0) { DEBUG_X11_CLIPRDR("unsupported format requested"); xf_cliprdr_send_null_data_response(xfi); } else { cb->request_index = i; DEBUG_X11_CLIPRDR("target=%d", (int) cb->format_mappings[i].target_format); XConvertSelection(xfi->display, cb->clipboard_atom, cb->format_mappings[i].target_format, cb->property_atom, xfi->drawable, CurrentTime); XFlush(xfi->display); /* After this point, we expect a SelectionNotify event from the clipboard owner. */ } }
static BOOL xf_cliprdr_get_requested_data(xfInfo* xfi, Atom target) { Atom type; int format; BYTE* data = NULL; BOOL has_data = FALSE; unsigned long length, bytes_left, dummy; clipboardContext* cb = (clipboardContext*) xfi->clipboard_context; if ((cb->request_index < 0) || (cb->format_mappings[cb->request_index].target_format != target)) { DEBUG_X11_CLIPRDR("invalid target"); xf_cliprdr_send_null_data_response(xfi); return FALSE; } XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, 0, 0, target, &type, &format, &length, &bytes_left, &data); DEBUG_X11_CLIPRDR("type=%d format=%d bytes=%d request_index=%d", (int) type, format, (int) bytes_left, cb->request_index); if (data) { XFree(data); data = NULL; } if (bytes_left <= 0 && !cb->incr_starts) { DEBUG_X11("no data"); } else if (type == cb->incr_atom) { DEBUG_X11("INCR started"); cb->incr_starts = TRUE; if (cb->incr_data) { free(cb->incr_data); cb->incr_data = NULL; } cb->incr_data_length = 0; /* Data will be followed in PropertyNotify event */ has_data = TRUE; } else { if (bytes_left <= 0) { /* INCR finish */ data = cb->incr_data; cb->incr_data = NULL; bytes_left = cb->incr_data_length; cb->incr_data_length = 0; cb->incr_starts = 0; DEBUG_X11("INCR finished"); has_data = TRUE; } else if (XGetWindowProperty(xfi->display, xfi->drawable, cb->property_atom, 0, bytes_left, 0, target, &type, &format, &length, &dummy, &data) == Success) { if (cb->incr_starts) { bytes_left = length * format / 8; DEBUG_X11("%d bytes", (int)bytes_left); cb->incr_data = (BYTE*) realloc(cb->incr_data, cb->incr_data_length + bytes_left); CopyMemory(cb->incr_data + cb->incr_data_length, data, bytes_left); cb->incr_data_length += bytes_left; XFree(data); data = NULL; } has_data = TRUE; } else { DEBUG_X11_CLIPRDR("XGetWindowProperty failed"); } } XDeleteProperty(xfi->display, xfi->drawable, cb->property_atom); xf_cliprdr_process_requested_data(xfi, has_data, data, (int) bytes_left); if (data) XFree(data); return TRUE; }