Rudimentary client->server clipboard transfer.

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@385 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Erik Forsberg 2003-06-06 09:24:15 +00:00
parent 8c019fe34a
commit 9d4c22ae10

170
cliprdr.c
View File

@ -28,6 +28,7 @@ extern Window wnd;
extern Time last_keyrelease; extern Time last_keyrelease;
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 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;
@ -50,10 +51,121 @@ cliprdr_print_server_formats(void)
#endif #endif
} }
void static void
cliprdr_handle_SelectionNotify(void) cliprdr_send_empty_datapacket(void)
{ {
STREAM out;
out = sec_init(encryption ? SEC_ENCRYPT : 0,
20);
out_uint32_le(out, 12);
out_uint32_le(out, 0x13);
out_uint16_le(out, 5);
out_uint16_le(out, 1);
out_uint32_le(out, 0);
/* Insert null string here? */
out_uint32_le(out, 0);
s_mark_end(out);
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
}
void
cliprdr_handle_SelectionNotify(XSelectionEvent *event)
{
unsigned char *data;
unsigned long nitems, bytes_left;
int res;
int format;
Atom type_return;
Atom best_target;
STREAM out;
DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n")); DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
if (None == event->property) {
cliprdr_send_empty_datapacket();
return; /* Selection failed */
}
DEBUG_CLIPBOARD(("selection: %s, target: %s, property: %s\n",
XGetAtomName(display, event->selection),
XGetAtomName(display, event->target),
XGetAtomName(display, event->property)));
if (targets_atom == event->target) {
/* Response to TARGETS request. Let's find the target
we want and request that */
res = XGetWindowProperty(display, wnd,
rdesktop_clipboard_target_atom,
0L, 4096L, False, AnyPropertyType,
&type_return,
&format, &nitems, &bytes_left, &data);
if (Success != res)
{
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
cliprdr_send_empty_datapacket();
return;
}
if (None == type_return)
/* The owner might no support TARGETS. Just try
STRING */
best_target = XA_STRING;
else
{
/* FIXME: We should choose format here based
on what the server wanted */
best_target = XInternAtom(display, "TEXT", False);
}
XConvertSelection(display, primary_atom,
best_target,
rdesktop_clipboard_target_atom,
wnd, event->time);
}
else /* Other clipboard data */
{
res = XGetWindowProperty(display, wnd,
rdesktop_clipboard_target_atom,
0L, 4096L, False, AnyPropertyType,
&type_return,
&format, &nitems, &bytes_left, &data);
if (Success != res)
{
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
cliprdr_send_empty_datapacket();
return;
}
/* We need to handle INCR as well */
out = sec_init(encryption ? SEC_ENCRYPT : 0,
20+nitems);
out_uint32_le(out, 12+nitems);
out_uint32_le(out, 0x13);
out_uint16_le(out, 5);
out_uint16_le(out, 1);
out_uint32_le(out, nitems);
out_uint8p(out, data, nitems);
/* Insert null string here? */
out_uint32_le(out, 0);
s_mark_end(out);
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
}
} }
void void
@ -352,10 +464,9 @@ void cliprdr_handle_server_data(uint32 length, STREAM s)
void cliprdr_handle_server_data_request(STREAM s) void cliprdr_handle_server_data_request(STREAM s)
{ {
Window selectionowner;
uint32 remaining_length; uint32 remaining_length;
uint32 wanted_formatcode, pad; uint32 wanted_formatcode, pad;
int ret;
STREAM out;
in_uint32_le(s, remaining_length); in_uint32_le(s, remaining_length);
in_uint32_le(s, wanted_formatcode); in_uint32_le(s, wanted_formatcode);
@ -366,35 +477,29 @@ void cliprdr_handle_server_data_request(STREAM s)
DEBUG_CLIPBOARD(("Request from server for format %d\n", DEBUG_CLIPBOARD(("Request from server for format %d\n",
wanted_formatcode)); wanted_formatcode));
out = sec_init(encryption ? SEC_ENCRYPT : 0, selectionowner = XGetSelectionOwner(display, primary_atom);
26);
out_uint32_le(out, 18);
out_uint32_le(out, 0x13);
out_uint16_le(out, 5);
out_uint16_le(out, 1);
out_uint32_le(out, 6);
out_uint8p(out, "fnorp", 6);
out_uint32_le(out, 0);
s_mark_end(out); if (None != selectionowner)
sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
/*
if (1 != wanted_formatcode)
{ {
out = sec_init(encryption ? SEC_ENCRYPT : 0,
20); /* FIXME: Perhaps we should check if we are the owner? */
out_uint32_le(s, 12);
out_uint32_le(s, 0x13); XConvertSelection(display, primary_atom,
out_uint16_le(s, 5); targets_atom,
out_uint16_le(s, 2); rdesktop_clipboard_target_atom,
out_uint32_le(s, 0); wnd, CurrentTime);
out_uint32_le(s, 0);
s_mark_end(s); /* The rest of the transfer is handled in
sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel! cliprdr_handle_SelectionNotify */
} else
{
DEBUG_CLIPBOARD(("There were no owner for PRIMARY, sending empty string\n")); // FIXME: Should we always send an empty string?
cliprdr_send_empty_datapacket();
} }
*/
} }
@ -450,6 +555,7 @@ void cliprdr_init(void)
{ {
primary_atom = XInternAtom(display, "PRIMARY", False); primary_atom = XInternAtom(display, "PRIMARY", False);
clipboard_atom = XInternAtom(display, "CLIPBOARD", False); clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
targets_atom = XInternAtom(display, "TARGETS", True); targets_atom = XInternAtom(display, "TARGETS", False);
timestamp_atom = XInternAtom(display, "TIMESTAMP", True); timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
} }