chansrv: work on clipboard

This commit is contained in:
Jay Sorg 2012-10-14 18:08:06 -07:00
parent 37d4f5725c
commit faec53b7f3
2 changed files with 134 additions and 35 deletions

View File

@ -147,6 +147,11 @@ static int g_cliprdr_flags = CB_USE_LONG_FORMAT_NAMES |
static int g_formatIds[16];
static int g_num_formatIds = 0;
/* this is used because client will ask for the same thing more than
once in successiotn */
int g_last_client_request_xrdp_clip_type = 0;
unsigned int g_last_client_request_xrdp_clip_time = 0;
/*****************************************************************************/
/* this is one way to get the current time from the x server */
static Time APP_CC
@ -559,7 +564,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
out_uint32_le(s, 0);
s_mark_end(s);
size = (int)(s->end - s->data);
g_hexdump(s->data, size);
//g_hexdump(s->data, size);
LOGM((LOG_LEVEL_DEBUG, "clipboard_send_format_announce: data out, sending "
"CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)"));
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
@ -694,19 +699,42 @@ clipboard_provide_selection(XSelectionRequestEvent *req, Atom type, int format,
char *data, int length)
{
XEvent xev;
long val1;
XChangeProperty(g_display, req->requestor, req->property,
type, format, PropModeReplace, (tui8 *)data, length);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
xev.xselection.send_event = True;
xev.xselection.display = req->display;
xev.xselection.requestor = req->requestor;
xev.xselection.selection = req->selection;
xev.xselection.target = req->target;
xev.xselection.property = req->property;
xev.xselection.time = req->time;
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
LLOGLN(0, ("clipboard_provide_selection: length %d", length));
if (length <= 16 * 1024 * 1024)
{
XChangeProperty(g_display, req->requestor, req->property,
type, format, PropModeReplace, (tui8 *)data, length);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
xev.xselection.send_event = True;
xev.xselection.display = req->display;
xev.xselection.requestor = req->requestor;
xev.xselection.selection = req->selection;
xev.xselection.target = req->target;
xev.xselection.property = req->property;
xev.xselection.time = req->time;
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
}
else
{
/* start the INCR process */
LLOGLN(0, ("clipboard_provide_selection: start INCR"));
val1 = 0;
XChangeProperty(g_display, req->requestor, req->property,
g_incr_atom, 32, PropModeReplace, (tui8 *)&val1, 1);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
xev.xselection.send_event = True;
xev.xselection.display = req->display;
xev.xselection.requestor = req->requestor;
xev.xselection.selection = req->selection;
xev.xselection.target = req->target;
xev.xselection.property = req->property;
xev.xselection.time = req->time;
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
}
return 0;
}
@ -746,7 +774,7 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
LOGM((LOG_LEVEL_DEBUG, "clipboard_process_format_announce: "
"CLIPRDR_FORMAT_ANNOUNCE"));
LLOGLN(10, ("clipboard_process_format_announce %d", clip_msg_len));
g_hexdump(s->p, s->end - s->p);
//g_hexdump(s->p, s->end - s->p);
clipboard_send_format_ack();
g_got_format_announce = 1;
g_data_in_up_to_date = 0;
@ -806,7 +834,7 @@ clipboard_prcoess_format_ack(struct stream *s, int clip_msg_status,
{
LOGM((LOG_LEVEL_DEBUG, "clipboard_prcoess_format_ack: CLIPRDR_FORMAT_ACK"));
LLOGLN(10, ("clipboard_prcoess_format_ack:"));
g_hexdump(s->p, s->end - s->p);
//g_hexdump(s->p, s->end - s->p);
return 0;
}
@ -839,28 +867,73 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
int clip_msg_len)
{
int requestedFormatId;
tui32 now;
tui32 tdiff;
LOGM((LOG_LEVEL_DEBUG, "clipboard_process_data_request: "
"CLIPRDR_DATA_REQUEST"));
LLOGLN(10, ("clipboard_process_data_request:"));
g_hexdump(s->p, s->end - s->p);
//g_hexdump(s->p, s->end - s->p);
now = xcommon_get_local_time();
tdiff = now - g_last_client_request_xrdp_clip_time;
in_uint32_le(s, requestedFormatId);
switch (requestedFormatId)
{
case CB_FORMAT_FILE: /* 0xC0BC */
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_FILE %d", g_last_clip_type));
XConvertSelection(g_display, g_clipboard_atom, g_last_clip_type,
g_clip_property_atom, g_wnd, CurrentTime);
if ((tdiff < 500) &&
(g_last_client_request_xrdp_clip_type == XRDP_CB_FILE))
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_FILE, "
"sending last data tdiff %d", tdiff));
clipboard_send_data_response_for_file(g_last_clip_data,
g_last_clip_size);
}
else
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_FILE, "
"calling XConvertSelection to g_utf8_atom "
"tdiff %d", tdiff));
g_last_client_request_xrdp_clip_type = XRDP_CB_FILE;
g_last_client_request_xrdp_clip_time = now;
XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
g_clip_property_atom, g_wnd, CurrentTime);
}
break;
case CB_FORMAT_DIB: /* 0x0008 */
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_DIB"));
XConvertSelection(g_display, g_clipboard_atom, g_last_clip_type,
g_clip_property_atom, g_wnd, CurrentTime);
if ((tdiff < 500) &&
(g_last_client_request_xrdp_clip_type == XRDP_CB_BITMAP))
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_DIB, "
"sending last data tdiff %d", tdiff));
clipboard_send_data_response_for_image(g_last_clip_data,
g_last_clip_size);
}
else
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_DIB, "
"calling XConvertSelection to g_image_bmp_atom "
"tdiff %d", tdiff));
XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
g_clip_property_atom, g_wnd, CurrentTime);
}
break;
case CB_FORMAT_UNICODETEXT: /* 0x000D */
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_UNICODETEXT"));
XConvertSelection(g_display, g_clipboard_atom, g_last_clip_type,
g_clip_property_atom, g_wnd, CurrentTime);
if ((tdiff < 500) &&
(g_last_client_request_xrdp_clip_type == XRDP_CB_TEXT))
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
"sending last data tdiff %d", tdiff));
clipboard_send_data_response_for_image(g_last_clip_data,
g_last_clip_size);
}
else
{
LLOGLN(10, ("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
"calling XConvertSelection to g_utf8_atom "
"tdiff %d", tdiff));
XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
g_clip_property_atom, g_wnd, CurrentTime);
}
break;
default:
LLOGLN(10, ("clipboard_process_data_request: unknown type %d",
@ -880,8 +953,8 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
clipboard data. */
static int APP_CC
clipboard_process_data_response_for_image(struct stream *s,
int clip_msg_status,
int clip_msg_len)
int clip_msg_status,
int clip_msg_len)
{
XSelectionRequestEvent *lxev = &g_saved_selection_req_event;
char *cptr;
@ -931,7 +1004,8 @@ clipboard_process_data_response_for_image(struct stream *s,
g_data_in_time = clipboard_get_local_time();
g_data_in_up_to_date = 1;
}
LLOGLN(10, ("clipboard_process_data_response_for_image: calling "
"clipboard_provide_selection with %d bytes", len));
clipboard_provide_selection(lxev, lxev->target, 8, cptr, len);
return 0;
}
@ -1260,13 +1334,19 @@ clipboard_get_window_property(Window wnd, Atom prop, Atom *type, int *fmt,
if (ltype == g_incr_atom)
{
LOGM((LOG_LEVEL_DEBUG, "clipboard_get_window_property: INCR start"));
LLOGLN(10, ("clipboard_get_window_property: INCR start"));
LLOGLN(10, ("clipboard_get_window_property: INCR start lfmt %d "
"ln_items %d llen_after %d", lfmt, ln_items, llen_after));
g_incr_in_progress = 1;
g_incr_atom_type = prop;
g_incr_data_size = 0;
g_free(g_incr_data);
g_incr_data = 0;
/* this will start the incr process */
XDeleteProperty(g_display, g_wnd, prop);
if (type != 0)
{
*type = ltype;
}
return 0;
}
@ -1426,6 +1506,15 @@ clipboard_event_selection_notify(XEvent *xevent)
}
XDeleteProperty(g_display, lxevent->requestor, lxevent->property);
if (type == g_incr_atom)
{
/* nothing more to do here, the data is comming in through
PropertyNotify */
LLOGLN(0, ("clipboard_event_selection_notify: type is INCR"));
return 0;
}
}
if (rv == 0)
@ -1783,10 +1872,19 @@ clipboard_event_property_notify(XEvent *xevent)
".state %d .atom %d", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom));
if (g_incr_in_progress &&
(xevent->xproperty.atom == g_incr_atom_type) &&
(xevent->xproperty.state == PropertyDelete))
{
/* this is used for when copying a large clipboard to the other app,
it will delete the property so we know to send the next one */
LLOGLN(10, ("clipboard_event_property_notify: INCR PropertyDelete"));
}
if (g_incr_in_progress &&
(xevent->xproperty.atom == g_incr_atom_type) &&
(xevent->xproperty.state == PropertyNewValue))
{
LLOGLN(10, ("clipboard_event_property_notify: INCR PropertyNewValue"));
rv = XGetWindowProperty(g_display, g_wnd, g_incr_atom_type, 0, 0, 0,
AnyPropertyType, &actual_type_return, &actual_format_return,
&nitems_returned, &bytes_left, (unsigned char **) &data);
@ -1866,6 +1964,7 @@ clipboard_event_property_notify(XEvent *xevent)
return 0;
}
LLOGLN(10, ("clipboard_event_property_notify: new_data_len %d", new_data_len));
g_incr_data = cptr;
g_memcpy(g_incr_data + g_incr_data_size, data, new_data_len);
g_incr_data_size += new_data_len;

View File

@ -173,14 +173,14 @@ clipboard_send_data_response_for_file(char *data, int data_size)
LLOGLN(10, ("clipboard_send_data_response_for_file: g_last_clip_size %d",
g_last_clip_size));
g_hexdump(data, data_size);
//g_hexdump(data, data_size);
clipboard_get_files(data, data_size);
cItems = g_num_files;
bytes_after_header = cItems * 592 + 4;
make_stream(s);
init_stream(s, 64 + bytes_after_header);
out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
out_uint16_le(s, 1); // CB_RESPONSE_OK); /* 1 status */
out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
out_uint32_le(s, bytes_after_header);
out_uint32_le(s, cItems);
for (index = 0; index < cItems; index++)
@ -199,7 +199,7 @@ clipboard_send_data_response_for_file(char *data, int data_size)
/* file size */
out_uint32_le(s, 0);
out_uint32_le(s, g_files[index].size);
g_writeln("jay size %d", g_files[index].size);
//g_writeln("jay size %d", g_files[index].size);
g_snprintf(fn, 255, "%s", g_files[index].filename);
clipboard_out_unicode(s, fn, 256);
out_uint8s(s, 8); /* pad */
@ -207,7 +207,7 @@ clipboard_send_data_response_for_file(char *data, int data_size)
out_uint32_le(s, 0);
s_mark_end(s);
size = (int)(s->end - s->data);
g_hexdump(s->data, size);
//g_hexdump(s->data, size);
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
@ -270,7 +270,7 @@ clipboard_send_file_data(int streamId, int lindex,
init_stream(s, cbRequested + 64);
//g_memset(s->data + 12, 26, cbRequested);
size = g_file_read(fd, s->data + 12, cbRequested);
g_writeln("size %d", size);
//g_writeln("size %d", size);
if (size < 1)
{
LLOGLN(10, ("clipboard_send_file_data: read error, want %d got %d",
@ -307,7 +307,7 @@ clipboard_process_file_request(struct stream *s, int clip_msg_status,
//int clipDataId;
LLOGLN(10, ("clipboard_process_file_request:"));
g_hexdump(s->p, clip_msg_len);
//g_hexdump(s->p, clip_msg_len);
in_uint32_le(s, streamId);
in_uint32_le(s, lindex);
in_uint32_le(s, dwFlags);