summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv/clipboard.c
diff options
context:
space:
mode:
authorjsorg71 <jsorg71>2009-08-29 21:20:27 +0000
committerjsorg71 <jsorg71>2009-08-29 21:20:27 +0000
commit64fde0e24fa797afdff513886da57a5a68ef6c5f (patch)
tree37d215bb74ab45c4de73744d3977dc973aa5cd53 /sesman/chansrv/clipboard.c
parent185414584ddc7610b99ad2ac170fec66f39ac01f (diff)
downloadxrdp-proprietary-64fde0e24fa797afdff513886da57a5a68ef6c5f.tar.gz
xrdp-proprietary-64fde0e24fa797afdff513886da57a5a68ef6c5f.zip
clipboard work
Diffstat (limited to 'sesman/chansrv/clipboard.c')
-rw-r--r--sesman/chansrv/clipboard.c224
1 files changed, 198 insertions, 26 deletions
diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c
index d14be594..9b3839db 100644
--- a/sesman/chansrv/clipboard.c
+++ b/sesman/chansrv/clipboard.c
@@ -55,6 +55,13 @@ static Time g_selection_time = 0;
static struct stream* g_ins = 0;
+static XSelectionRequestEvent g_selection_request_event[16];
+static int g_selection_request_event_count = 0;
+
+static char* g_data_in;
+static int g_data_in_size;
+static int g_data_in_time;
+
extern int g_cliprdr_chan_id; /* in chansrv.c */
extern Display* g_display; /* in chansrv.c */
@@ -199,6 +206,7 @@ clipboard_deinit(void)
g_x_socket = 0;
g_free(g_last_clip_data);
g_last_clip_data = 0;
+ g_last_clip_size = 0;
free_stream(g_ins);
g_clip_up = 0;
return 0;
@@ -358,11 +366,20 @@ static int APP_CC
clipboard_process_format_announce(struct stream* s, int clip_msg_status,
int clip_msg_len)
{
+ Window owner;
+
LOG(1, ("clipboard_process_format_announce: CLIPRDR_FORMAT_ANNOUNCE"));
- //g_hexdump(s->p, s->end - s->p);
clipboard_send_format_ack();
g_selection_time = clipboard_get_time();
XSetSelectionOwner(g_display, g_clipboard_atom, g_wnd, g_selection_time);
+ //XSetSelectionOwner(g_display, XA_PRIMARY, g_wnd, g_selection_time);
+ g_got_selection = 1;
+ owner = XGetSelectionOwner(g_display, g_clipboard_atom);
+ if (owner != g_wnd)
+ {
+ g_got_selection = 0;
+ LOG(0, ("clipboard_process_format_announce: XSetSelectionOwner failed"));
+ }
return 0;
}
@@ -392,8 +409,77 @@ static int APP_CC
clipboard_process_data_response(struct stream* s, int clip_msg_status,
int clip_msg_len)
{
+ XEvent xev;
+ XSelectionRequestEvent* lev;
+ twchar* wtext;
+ twchar wchr;
+ int len;
+ int index;
+ int wtext_size;
+
LOG(1, ("clipboard_process_data_response: CLIPRDR_DATA_RESPONSE"));
- //g_hexdump(s->p, s->end - s->p);
+ len = (int)(s->end - s->p);
+ if (len < 1)
+ {
+ return 0;
+ }
+ g_hexdump(s->p, len);
+ wtext = (twchar*)g_malloc(((len / 2) + 1) * sizeof(twchar), 0);
+ if (wtext == 0)
+ {
+ return 0;
+ }
+ index = 0;
+ while (s_check(s))
+ {
+ in_uint16_le(s, wchr);
+ wtext[index] = wchr;
+ if (wchr == 0)
+ {
+ break;
+ }
+ index++;
+ }
+ wtext[index] = 0;
+ len = g_wcstombs(0, wtext, 0);
+ if (len >= 0)
+ {
+ g_free(g_data_in);
+ g_data_in_size = 0;
+ g_data_in = (char*)g_malloc(len + 16, 0);
+ if (g_data_in == 0)
+ {
+ g_free(wtext);
+ return 0;
+ }
+ g_data_in_size = len;
+ g_wcstombs(g_data_in, wtext, len + 1);
+ len = g_strlen(g_data_in);
+ g_data_in_time = g_time3();
+ }
+ if (g_data_in != 0)
+ {
+ for (index = 0; index < g_selection_request_event_count; index++)
+ {
+ lev = &(g_selection_request_event[index]);
+ XChangeProperty(g_display, lev->requestor, lev->property,
+ XA_STRING, 8, PropModeReplace, g_data_in,
+ g_strlen(g_data_in));
+ g_memset(&xev, 0, sizeof(xev));
+ xev.xselection.type = SelectionNotify;
+ xev.xselection.send_event = True;
+ xev.xselection.display = lev->display;
+ xev.xselection.requestor = lev->requestor;
+ xev.xselection.selection = lev->selection;
+ xev.xselection.target = lev->target;
+ xev.xselection.property = lev->property;
+ xev.xselection.time = CurrentTime;
+ XSendEvent(g_display, lev->requestor, False, NoEventMask, &xev);
+ LOG(1, ("clipboard_process_data_response: %d", lev->requestor));
+ }
+ }
+ g_selection_request_event_count = 0;
+ g_free(wtext);
return 0;
}
@@ -483,13 +569,18 @@ clipboard_process_selection_owner_notify(XEvent* xevent)
lxevent = (XFixesSelectionNotifyEvent*)xevent;
LOG(1, ("clipboard_process_selection_owner_notify: "
- "window %d subtype %d owner %d",
- lxevent->window, lxevent->subtype, lxevent->owner));
- if (lxevent->subtype == 0)
+ "window %d subtype %d owner %d g_wnd %d",
+ lxevent->window, lxevent->subtype, lxevent->owner, g_wnd));
+ if (lxevent->owner == g_wnd)
{
- XConvertSelection(g_display, g_clipboard_atom, XA_STRING,
- g_clip_property_atom, g_wnd, CurrentTime);
+ LOG(1, ("clipboard_process_selection_owner_notify: skipping, "
+ "onwer == g_wnd"));
+ g_got_selection = 1;
+ return 0;
}
+ g_got_selection = 0;
+ XConvertSelection(g_display, g_clipboard_atom, g_targets_atom,
+ g_clip_property_atom, g_wnd, lxevent->timestamp);
return 0;
}
@@ -595,9 +686,16 @@ clipboard_process_selection_notify(XEvent* xevent)
int n_items;
int fmt;
int rv;
+ int index;
+ int convert_to_string;
+ int send_format_announce;
+ int atom;
+ int* atoms;
Atom type;
LOG(1, ("clipboard_process_selection_notify:"));
+ convert_to_string = 0;
+ send_format_announce = 0;
rv = 0;
data = 0;
type = 0;
@@ -610,34 +708,71 @@ clipboard_process_selection_notify(XEvent* xevent)
}
if (rv == 0)
{
- rv = clipboard_get_window_property(g_wnd, lxevent->property, &type, &fmt,
+ rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
+ &type, &fmt,
&n_items, &data, &data_size);
if (rv != 0)
{
LOG(0, ("clipboard_process_selection_notify: "
"clipboard_get_window_property failed error %d", rv));
}
- XDeleteProperty(g_display, g_wnd, g_clip_property_atom);
+ XDeleteProperty(g_display, lxevent->requestor, lxevent->property);
}
if (rv == 0)
{
- if (type == XA_STRING)
+ if (lxevent->selection == g_clipboard_atom)
{
- g_free(g_last_clip_data);
- g_last_clip_size = data_size;
- g_last_clip_data = g_malloc(g_last_clip_size + 1, 0);
- g_last_clip_type = XA_STRING;
- g_memcpy(g_last_clip_data, data, g_last_clip_size);
- g_last_clip_data[g_last_clip_size] = 0;
+ if (lxevent->target == g_targets_atom)
+ {
+ if ((type == XA_ATOM) && (fmt == 32))
+ {
+ atoms = (int*)data;
+ for (index = 0; index < n_items; index++)
+ {
+ atom = atoms[index];
+ LOG(1, ("clipboard_process_selection_notify: %d %s %d", atom,
+ XGetAtomName(g_display, atom), XA_STRING));
+ if (atom == XA_STRING)
+ {
+ convert_to_string = 1;
+ }
+ }
+ }
+ else
+ {
+ LOG(0, ("clipboard_process_selection_notify: error, target is "
+ "'TARGETS' and type[%d] or fmt[%d] not right, should be "
+ "type[%d], fmt[%d]", type, fmt, XA_ATOM, 32));
+ }
+ }
+ else if (lxevent->target == XA_STRING)
+ {
+ LOG(10, ("clipboard_process_selection_notify: XA_STRING data_size %d",
+ data_size));
+ g_free(g_last_clip_data);
+ g_last_clip_size = data_size;
+ g_last_clip_data = g_malloc(g_last_clip_size + 1, 0);
+ g_last_clip_type = XA_STRING;
+ g_memcpy(g_last_clip_data, data, g_last_clip_size);
+ g_last_clip_data[g_last_clip_size] = 0;
+ send_format_announce = 1;
+ }
+ else
+ {
+ LOG(0, ("clipboard_process_selection_notify: unknown target"));
+ }
}
else
{
- LOG(0, ("clipboard_process_selection_notify: unknown "
- "clipboard data type %d", type));
- rv = 3;
+ LOG(0, ("clipboard_process_selection_notify: unknown selection"));
}
}
- if (rv == 0)
+ if (convert_to_string)
+ {
+ XConvertSelection(g_display, g_clipboard_atom, XA_STRING,
+ g_clip_property_atom, g_wnd, CurrentTime);
+ }
+ if (send_format_announce)
{
if (clipboard_send_format_announce() != 0)
{
@@ -696,8 +831,8 @@ clipboard_process_selection_request(XEvent* xevent)
XA_ATOM, 32, PropModeReplace, (tui8*)ui32, 4);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
- xev.xselection.serial = 0;
xev.xselection.send_event = True;
+ xev.xselection.display = lxevent->display;
xev.xselection.requestor = lxevent->requestor;
xev.xselection.selection = lxevent->selection;
xev.xselection.target = lxevent->target;
@@ -715,8 +850,8 @@ clipboard_process_selection_request(XEvent* xevent)
XA_INTEGER, 32, PropModeReplace, (tui8*)ui32, 1);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
- xev.xselection.serial = 0;
xev.xselection.send_event = True;
+ xev.xselection.display = lxevent->display;
xev.xselection.requestor = lxevent->requestor;
xev.xselection.selection = lxevent->selection;
xev.xselection.target = lxevent->target;
@@ -743,12 +878,33 @@ clipboard_process_selection_request(XEvent* xevent)
else if (lxevent->target == XA_STRING)
{
LOG(1, ("clipboard_process_selection_request: XA_STRING"));
+/*
+ if (g_abs((g_time3() - g_data_in_time)) < 1000)
+ {
+ LOG(1, ("clipboard_process_selection_request: XA_STRING---------------------------"));
+ XChangeProperty(g_display, lxevent->requestor, lxevent->property,
+ XA_STRING, 8, PropModeReplace, g_data_in,
+ g_strlen(g_data_in));
+ g_memset(&xev, 0, sizeof(xev));
+ xev.xselection.type = SelectionNotify;
+ xev.xselection.send_event = True;
+ xev.xselection.display = lxevent->display;
+ xev.xselection.requestor = lxevent->requestor;
+ xev.xselection.selection = lxevent->selection;
+ xev.xselection.target = lxevent->target;
+ xev.xselection.property = lxevent->property;
+ xev.xselection.time = lxevent->time;
+ XSendEvent(g_display, lxevent->requestor, False, NoEventMask, &xev);
+ return 0;
+ }
+*/
+/*
XChangeProperty(g_display, lxevent->requestor, lxevent->property,
- XA_STRING, 8, PropModeReplace, "test", 5);
+ XA_STRING, 8, PropModeReplace, "Jay--", 5);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
- xev.xselection.serial = 0;
xev.xselection.send_event = True;
+ xev.xselection.display = lxevent->display;
xev.xselection.requestor = lxevent->requestor;
xev.xselection.selection = lxevent->selection;
xev.xselection.target = lxevent->target;
@@ -756,6 +912,22 @@ clipboard_process_selection_request(XEvent* xevent)
xev.xselection.time = lxevent->time;
XSendEvent(g_display, lxevent->requestor, False, NoEventMask, &xev);
return 0;
+*/
+ if (g_selection_request_event_count > 10)
+ {
+ LOG(0, ("clipboard_process_selection_request: error, too many requests"));
+ }
+ else
+ {
+ g_memcpy(&(g_selection_request_event[g_selection_request_event_count]),
+ lxevent, sizeof(g_selection_request_event[0]));
+ if (g_selection_request_event_count == 0)
+ {
+ clipboard_send_data_request();
+ }
+ g_selection_request_event_count++;
+ return 0;
+ }
}
else
{
@@ -764,8 +936,8 @@ clipboard_process_selection_request(XEvent* xevent)
}
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
- xev.xselection.serial = 0;
xev.xselection.send_event = True;
+ xev.xselection.display = lxevent->display;
xev.xselection.requestor = lxevent->requestor;
xev.xselection.selection = lxevent->selection;
xev.xselection.target = lxevent->target;
@@ -791,7 +963,6 @@ static int APP_CC
clipboard_process_selection_clear(XEvent* xevent)
{
LOG(1, ("clipboard_process_selection_clear:"));
- g_got_selection = 0;
return 0;
}
@@ -850,6 +1021,7 @@ clipboard_check_wait_objs(void)
case MappingNotify:
break;
case PropertyNotify:
+ LOG(1, ("clipboard_check_wait_objs: PropertyNotify .window %d .state %d", xevent.xproperty.window, xevent.xproperty.state));
break;
default:
if (xevent.type == g_xfixes_event_base +