Handle large clipboard transfers X->Windows.
Can't handle INCR yet, but at least we handle larger transfers than 1592 bytes. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@390 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
a80b1267a4
commit
1052468cf7
194
cliprdr.c
194
cliprdr.c
@ -29,11 +29,12 @@ extern Time last_gesturetime;
|
|||||||
|
|
||||||
// static Time selection_timestamp;
|
// static Time selection_timestamp;
|
||||||
static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
|
static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
|
||||||
static Atom rdesktop_clipboard_target_atom;
|
static Atom rdesktop_clipboard_target_atom, incr_atom;
|
||||||
static cliprdr_dataformat *server_formats = NULL;
|
static cliprdr_dataformat *server_formats = NULL;
|
||||||
static uint16 num_server_formats = 0;
|
static uint16 num_server_formats = 0;
|
||||||
static XSelectionEvent selection_event;
|
static XSelectionEvent selection_event;
|
||||||
static uint16 clipboard_channelno;
|
static uint16 clipboard_channelno;
|
||||||
|
static Atom targets[NUM_TARGETS];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cliprdr_print_server_formats(void)
|
cliprdr_print_server_formats(void)
|
||||||
@ -125,13 +126,16 @@ void
|
|||||||
cliprdr_handle_SelectionNotify(XSelectionEvent *event)
|
cliprdr_handle_SelectionNotify(XSelectionEvent *event)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned char *data;
|
unsigned char *data, *datap;
|
||||||
unsigned long nitems, bytes_left;
|
unsigned long nitems, bytes_left;
|
||||||
int res;
|
|
||||||
|
unsigned long bytes_left_to_transfer;
|
||||||
|
int res, i;
|
||||||
|
|
||||||
int format;
|
int format;
|
||||||
Atom type_return;
|
Atom type_return;
|
||||||
Atom best_target;
|
Atom best_target;
|
||||||
|
Atom *supported_targets;
|
||||||
|
|
||||||
STREAM out;
|
STREAM out;
|
||||||
|
|
||||||
@ -171,6 +175,13 @@ cliprdr_handle_SelectionNotify(XSelectionEvent *event)
|
|||||||
{
|
{
|
||||||
/* FIXME: We should choose format here based
|
/* FIXME: We should choose format here based
|
||||||
on what the server wanted */
|
on what the server wanted */
|
||||||
|
supported_targets = (Atom *)data;
|
||||||
|
for (i=0;i<nitems;i++)
|
||||||
|
{
|
||||||
|
DEBUG_CLIPBOARD(("Target %d: %s\n",
|
||||||
|
i, XGetAtomName(display,
|
||||||
|
supported_targets[i])));
|
||||||
|
}
|
||||||
best_target = XInternAtom(display, "TEXT", False);
|
best_target = XInternAtom(display, "TEXT", False);
|
||||||
|
|
||||||
|
|
||||||
@ -187,10 +198,22 @@ cliprdr_handle_SelectionNotify(XSelectionEvent *event)
|
|||||||
|
|
||||||
res = XGetWindowProperty(display, wnd,
|
res = XGetWindowProperty(display, wnd,
|
||||||
rdesktop_clipboard_target_atom,
|
rdesktop_clipboard_target_atom,
|
||||||
0L, 4096L, False, AnyPropertyType,
|
0L, 0x1FFFFFF,
|
||||||
|
True, AnyPropertyType,
|
||||||
&type_return,
|
&type_return,
|
||||||
&format, &nitems, &bytes_left, &data);
|
&format, &nitems, &bytes_left, &data);
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: We need to handle INCR as well,
|
||||||
|
this is a temporary solution. */
|
||||||
|
|
||||||
|
if (incr_atom == type_return)
|
||||||
|
{
|
||||||
|
warning("We don't support INCR transfers at this time. Try cutting less data\n");
|
||||||
|
cliprdr_send_empty_datapacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (Success != res)
|
if (Success != res)
|
||||||
{
|
{
|
||||||
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
|
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
|
||||||
@ -198,23 +221,88 @@ cliprdr_handle_SelectionNotify(XSelectionEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to handle INCR as well */
|
DEBUG_CLIPBOARD(("Received %d bytes of clipboard data from X, there is %d remaining\n",
|
||||||
|
nitems, bytes_left));
|
||||||
|
DEBUG_CLIPBOARD(("type_return is %s\n",
|
||||||
|
XGetAtomName(display, type_return)));
|
||||||
|
|
||||||
out = sec_init(encryption ? SEC_ENCRYPT : 0,
|
datap = data;
|
||||||
20+nitems+1);
|
|
||||||
out_uint32_le(out, 12+nitems+1);
|
if (nitems+1 <= MAX_CLIPRDR_STANDALONE_DATASIZE)
|
||||||
out_uint32_le(out, 0x13);
|
{
|
||||||
out_uint16_le(out, 5);
|
out = sec_init(encryption ? SEC_ENCRYPT : 0,
|
||||||
out_uint16_le(out, 1);
|
20+nitems+1);
|
||||||
out_uint32_le(out, nitems+1);
|
out_uint32_le(out, 12+nitems+1);
|
||||||
out_uint8p(out, data, nitems+1);
|
out_uint32_le(out, 0x13);
|
||||||
/* Insert null string here? */
|
out_uint16_le(out, 5);
|
||||||
out_uint32_le(out, 0);
|
out_uint16_le(out, 1);
|
||||||
s_mark_end(out);
|
out_uint32_le(out, nitems+1);
|
||||||
|
out_uint8p(out, datap, nitems+1);
|
||||||
|
out_uint32_le(out, 0);
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
|
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
|
||||||
clipboard_channelno);
|
clipboard_channelno);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
|
||||||
|
16+MAX_CLIPRDR_STANDALONE_DATASIZE));
|
||||||
|
out = sec_init(encryption ? SEC_ENCRYPT : 0,
|
||||||
|
16+MAX_CLIPRDR_STANDALONE_DATASIZE);
|
||||||
|
out_uint32_le(out, nitems+12);
|
||||||
|
out_uint32_le(out, 0x11);
|
||||||
|
out_uint16_le(out, 5);
|
||||||
|
out_uint16_le(out, 1);
|
||||||
|
out_uint32_le(out, nitems);
|
||||||
|
out_uint8p(out, datap,
|
||||||
|
MAX_CLIPRDR_STANDALONE_DATASIZE);
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
|
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
|
||||||
|
clipboard_channelno);
|
||||||
|
|
||||||
|
bytes_left_to_transfer = nitems - MAX_CLIPRDR_STANDALONE_DATASIZE;
|
||||||
|
datap+=MAX_CLIPRDR_STANDALONE_DATASIZE;
|
||||||
|
|
||||||
|
while (bytes_left_to_transfer > MAX_CLIPRDR_STANDALONE_DATASIZE)
|
||||||
|
{
|
||||||
|
DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
|
||||||
|
16+MAX_CLIPRDR_CONTINUATION_DATASIZE));
|
||||||
|
out = sec_init(encryption ? SEC_ENCRYPT : 0,
|
||||||
|
8+MAX_CLIPRDR_CONTINUATION_DATASIZE);
|
||||||
|
out_uint32_le(out, nitems);
|
||||||
|
out_uint32_le(out, 0x10);
|
||||||
|
out_uint8p(out, datap,
|
||||||
|
MAX_CLIPRDR_CONTINUATION_DATASIZE);
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
|
sec_send_to_channel(out,
|
||||||
|
encryption ? SEC_ENCRYPT : 0,
|
||||||
|
clipboard_channelno);
|
||||||
|
bytes_left_to_transfer-= MAX_CLIPRDR_CONTINUATION_DATASIZE;
|
||||||
|
datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE;
|
||||||
|
|
||||||
|
}
|
||||||
|
DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
|
||||||
|
12+bytes_left_to_transfer));
|
||||||
|
out = sec_init(encryption ? SEC_ENCRYPT : 0,
|
||||||
|
12+bytes_left_to_transfer);
|
||||||
|
out_uint32_le(out, nitems);
|
||||||
|
out_uint32_le(out, 0x12);
|
||||||
|
out_uint8p(out, datap,
|
||||||
|
bytes_left_to_transfer);
|
||||||
|
out_uint32_le(out, 0x0);
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
|
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
|
||||||
|
clipboard_channelno);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XFree(data);
|
||||||
cliprdr_send_format_announce();
|
cliprdr_send_format_announce();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -254,9 +342,6 @@ void
|
|||||||
cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
|
cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
|
||||||
{
|
{
|
||||||
|
|
||||||
Atom *targets;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
XSelectionEvent xev;
|
XSelectionEvent xev;
|
||||||
DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
|
DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
|
||||||
DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
|
DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
|
||||||
@ -285,43 +370,36 @@ cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
|
|||||||
if (targets_atom == xevent->target)
|
if (targets_atom == xevent->target)
|
||||||
{
|
{
|
||||||
DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
|
DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
|
||||||
targets = xmalloc(4*sizeof(Atom));
|
XChangeProperty(display,
|
||||||
targets[0] = xevent->target;
|
xevent->requestor,
|
||||||
targets[1] = XInternAtom(display, "TEXT", True);
|
xevent->property,
|
||||||
targets[2] = XInternAtom(display, "UTF8_STRING", True);
|
XA_ATOM,
|
||||||
targets[3] = XInternAtom(display, "TIMESTAMP", True);
|
32,
|
||||||
res = XChangeProperty(display,
|
PropModeAppend,
|
||||||
xevent->requestor,
|
(unsigned char *)&targets,
|
||||||
xevent->property,
|
NUM_TARGETS);
|
||||||
XA_ATOM,
|
|
||||||
32,
|
|
||||||
PropModeAppend,
|
|
||||||
(unsigned char *)targets,
|
|
||||||
3);
|
|
||||||
|
|
||||||
res = XSendEvent(display,
|
XSendEvent(display,
|
||||||
xevent->requestor,
|
xevent->requestor,
|
||||||
False,
|
False,
|
||||||
NoEventMask,
|
NoEventMask,
|
||||||
(XEvent *)&xev);
|
(XEvent *)&xev);
|
||||||
return;
|
return;
|
||||||
} else if (timestamp_atom == xevent->target)
|
} else if (timestamp_atom == xevent->target)
|
||||||
{
|
{
|
||||||
DEBUG_CLIPBOARD(("TIMESTAMP requested... sending 0x%x\n",
|
XChangeProperty(display,
|
||||||
(unsigned)last_gesturetime));
|
xevent->requestor,
|
||||||
res = XChangeProperty(display,
|
xevent->property,
|
||||||
xevent->requestor,
|
XA_INTEGER,
|
||||||
xevent->property,
|
32,
|
||||||
XA_INTEGER,
|
PropModeAppend,
|
||||||
32,
|
(unsigned char *)&last_gesturetime,
|
||||||
PropModeAppend,
|
1);
|
||||||
(unsigned char *)&last_gesturetime,
|
XSendEvent(display,
|
||||||
1);
|
xevent->requestor,
|
||||||
res = XSendEvent(display,
|
False,
|
||||||
xevent->requestor,
|
NoEventMask,
|
||||||
False,
|
(XEvent *)&xev);
|
||||||
NoEventMask,
|
|
||||||
(XEvent *)&xev);
|
|
||||||
} else /* Some other target */
|
} else /* Some other target */
|
||||||
{
|
{
|
||||||
cliprdr_request_clipboard_data(CF_TEXT);
|
cliprdr_request_clipboard_data(CF_TEXT);
|
||||||
@ -571,4 +649,12 @@ void cliprdr_init(void)
|
|||||||
targets_atom = XInternAtom(display, "TARGETS", False);
|
targets_atom = XInternAtom(display, "TARGETS", False);
|
||||||
timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
|
timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
|
||||||
rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
|
rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
|
||||||
|
incr_atom = XInternAtom(display, "INCR", False);
|
||||||
|
targets[0] = targets_atom;
|
||||||
|
targets[1] = XInternAtom(display, "TEXT", False);
|
||||||
|
targets[2] = XInternAtom(display, "UTF8_STRING", False);
|
||||||
|
targets[3] = XInternAtom(display, "text/unicode", False);
|
||||||
|
targets[4] = XInternAtom(display, "TIMESTAMP", False);
|
||||||
|
targets[5] = XInternAtom(display, "STRING", False);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user