chansrv: work on clipboard
This commit is contained in:
parent
37d4f5725c
commit
faec53b7f3
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user