69 |
before requesting clipboard data from a fellow rdesktop using |
before requesting clipboard data from a fellow rdesktop using |
70 |
the _RDESKTOP_CLIPBOARD_FORMATS target. */ |
the _RDESKTOP_CLIPBOARD_FORMATS target. */ |
71 |
static Atom rdesktop_clipboard_target_atom; |
static Atom rdesktop_clipboard_target_atom; |
72 |
|
/* Atoms _RDESKTOP_PRIMARY_TIMESTAMP_TARGET and _RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET |
73 |
|
are used to store the timestamps for when a window got ownership of the selections. |
74 |
|
We use these to determine which is more recent and should be used. */ |
75 |
|
static Atom rdesktop_primary_timestamp_target_atom, rdesktop_clipboard_timestamp_target_atom; |
76 |
|
/* Storage for timestamps since we get them in two separate notifications. */ |
77 |
|
static Time primary_timestamp, clipboard_timestamp; |
78 |
/* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses: |
/* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses: |
79 |
- The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange |
- The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange |
80 |
of Windows native clipboard data. |
of Windows native clipboard data. |
378 |
} |
} |
379 |
} |
} |
380 |
|
|
381 |
|
static void |
382 |
|
xclip_clear_target_props() |
383 |
|
{ |
384 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
385 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom); |
386 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom); |
387 |
|
} |
388 |
|
|
389 |
/* This function is called for SelectionNotify events. |
/* This function is called for SelectionNotify events. |
390 |
The SelectionNotify event is sent from the clipboard owner to the requestor |
The SelectionNotify event is sent from the clipboard owner to the requestor |
391 |
after his request was satisfied. |
after his request was satisfied. |
409 |
XGetAtomName(g_display, event->target), |
XGetAtomName(g_display, event->target), |
410 |
XGetAtomName(g_display, event->property))); |
XGetAtomName(g_display, event->property))); |
411 |
|
|
412 |
if (event->property == None) |
if (event->target == timestamp_atom) |
413 |
goto fail; |
{ |
414 |
|
if (event->selection == primary_atom) |
415 |
|
{ |
416 |
|
res = XGetWindowProperty(g_display, g_wnd, |
417 |
|
rdesktop_primary_timestamp_target_atom, 0, |
418 |
|
XMaxRequestSize(g_display), False, XA_INTEGER, |
419 |
|
&type, &format, &nitems, &bytes_left, &data); |
420 |
|
} |
421 |
|
else |
422 |
|
{ |
423 |
|
res = XGetWindowProperty(g_display, g_wnd, |
424 |
|
rdesktop_clipboard_timestamp_target_atom, 0, |
425 |
|
XMaxRequestSize(g_display), False, XA_INTEGER, |
426 |
|
&type, &format, &nitems, &bytes_left, &data); |
427 |
|
} |
428 |
|
|
429 |
|
|
430 |
|
if ((res != Success) || (nitems != 1)) |
431 |
|
{ |
432 |
|
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n")); |
433 |
|
goto fail; |
434 |
|
} |
435 |
|
|
436 |
|
if (event->selection == primary_atom) |
437 |
|
{ |
438 |
|
primary_timestamp = *(Time *) data; |
439 |
|
if (primary_timestamp == 0) |
440 |
|
primary_timestamp++; |
441 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom); |
442 |
|
DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n", |
443 |
|
(unsigned) primary_timestamp)); |
444 |
|
} |
445 |
|
else |
446 |
|
{ |
447 |
|
clipboard_timestamp = *(Time *) data; |
448 |
|
if (clipboard_timestamp == 0) |
449 |
|
clipboard_timestamp++; |
450 |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom); |
451 |
|
DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n", |
452 |
|
(unsigned) clipboard_timestamp)); |
453 |
|
} |
454 |
|
|
455 |
|
XFree(data); |
456 |
|
|
457 |
|
if (primary_timestamp && clipboard_timestamp) |
458 |
|
{ |
459 |
|
if (primary_timestamp > clipboard_timestamp) |
460 |
|
{ |
461 |
|
DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n")); |
462 |
|
XConvertSelection(g_display, primary_atom, targets_atom, |
463 |
|
rdesktop_clipboard_target_atom, g_wnd, |
464 |
|
event->time); |
465 |
|
} |
466 |
|
else |
467 |
|
{ |
468 |
|
DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n")); |
469 |
|
XConvertSelection(g_display, clipboard_atom, targets_atom, |
470 |
|
rdesktop_clipboard_target_atom, g_wnd, |
471 |
|
event->time); |
472 |
|
} |
473 |
|
} |
474 |
|
|
475 |
|
return; |
476 |
|
} |
477 |
|
|
478 |
res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
479 |
0, XMaxRequestSize(g_display), False, AnyPropertyType, |
0, XMaxRequestSize(g_display), False, AnyPropertyType, |
480 |
&type, &format, &nitems, &bytes_left, &data); |
&type, &format, &nitems, &bytes_left, &data); |
481 |
|
|
482 |
|
xclip_clear_target_props(); |
483 |
|
|
484 |
if (res != Success) |
if (res != Success) |
485 |
{ |
{ |
486 |
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n")); |
DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n")); |
496 |
{ |
{ |
497 |
XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask)); |
XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask)); |
498 |
} |
} |
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
|
499 |
XFree(data); |
XFree(data); |
500 |
g_incr_target = event->target; |
g_incr_target = event->target; |
501 |
g_waiting_for_INCR = 1; |
g_waiting_for_INCR = 1; |
502 |
return; |
return; |
503 |
} |
} |
504 |
|
|
|
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
|
|
|
|
505 |
/* Negotiate target format */ |
/* Negotiate target format */ |
506 |
if (event->target == targets_atom) |
if (event->target == targets_atom) |
507 |
{ |
{ |
578 |
return; |
return; |
579 |
|
|
580 |
fail: |
fail: |
581 |
XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom); |
xclip_clear_target_props(); |
582 |
if (data) |
if (data) |
583 |
XFree(data); |
XFree(data); |
584 |
helper_cliprdr_send_empty_response(); |
helper_cliprdr_send_empty_response(); |
885 |
void |
void |
886 |
ui_clip_request_data(uint32 format) |
ui_clip_request_data(uint32 format) |
887 |
{ |
{ |
888 |
Window selectionowner; |
Window primary_owner, clipboard_owner; |
889 |
|
|
890 |
DEBUG_CLIPBOARD(("Request from server for format %d\n", format)); |
DEBUG_CLIPBOARD(("Request from server for format %d\n", format)); |
891 |
rdp_clipboard_request_format = format; |
rdp_clipboard_request_format = format; |
892 |
|
|
893 |
|
xclip_clear_target_props(); |
894 |
|
|
895 |
if (rdesktop_is_selection_owner) |
if (rdesktop_is_selection_owner) |
896 |
{ |
{ |
897 |
XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom, |
902 |
return; |
return; |
903 |
} |
} |
904 |
|
|
905 |
selectionowner = XGetSelectionOwner(g_display, primary_atom); |
primary_owner = XGetSelectionOwner(g_display, primary_atom); |
906 |
if (selectionowner != None) |
clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom); |
907 |
|
|
908 |
|
/* Both available */ |
909 |
|
if ((primary_owner != None) && (clipboard_owner != None)) |
910 |
|
{ |
911 |
|
primary_timestamp = 0; |
912 |
|
clipboard_timestamp = 0; |
913 |
|
XConvertSelection(g_display, primary_atom, timestamp_atom, |
914 |
|
rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime); |
915 |
|
XConvertSelection(g_display, clipboard_atom, timestamp_atom, |
916 |
|
rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime); |
917 |
|
return; |
918 |
|
} |
919 |
|
|
920 |
|
/* Just PRIMARY */ |
921 |
|
if (primary_owner != None) |
922 |
{ |
{ |
923 |
XConvertSelection(g_display, primary_atom, targets_atom, |
XConvertSelection(g_display, primary_atom, targets_atom, |
924 |
rdesktop_clipboard_target_atom, g_wnd, CurrentTime); |
rdesktop_clipboard_target_atom, g_wnd, CurrentTime); |
925 |
return; |
return; |
926 |
} |
} |
927 |
|
|
928 |
/* No PRIMARY, try CLIPBOARD */ |
/* Just CLIPBOARD */ |
929 |
selectionowner = XGetSelectionOwner(g_display, clipboard_atom); |
if (clipboard_owner != None) |
|
if (selectionowner != None) |
|
930 |
{ |
{ |
931 |
XConvertSelection(g_display, clipboard_atom, targets_atom, |
XConvertSelection(g_display, clipboard_atom, targets_atom, |
932 |
rdesktop_clipboard_target_atom, g_wnd, CurrentTime); |
rdesktop_clipboard_target_atom, g_wnd, CurrentTime); |
956 |
timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False); |
timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False); |
957 |
rdesktop_clipboard_target_atom = |
rdesktop_clipboard_target_atom = |
958 |
XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False); |
XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False); |
959 |
|
rdesktop_primary_timestamp_target_atom = |
960 |
|
XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False); |
961 |
|
rdesktop_clipboard_timestamp_target_atom = |
962 |
|
XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False); |
963 |
incr_atom = XInternAtom(g_display, "INCR", False); |
incr_atom = XInternAtom(g_display, "INCR", False); |
964 |
format_string_atom = XInternAtom(g_display, "STRING", False); |
format_string_atom = XInternAtom(g_display, "STRING", False); |
965 |
format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False); |
format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False); |