--- sourceforge.net/trunk/rdesktop/cliprdr.c 2003/06/06 09:30:06 392 +++ sourceforge.net/trunk/rdesktop/cliprdr.c 2003/06/06 09:32:15 395 @@ -26,6 +26,7 @@ extern Display *display; extern Window wnd; extern Time last_gesturetime; +extern Atom ipc_atom; // static Time selection_timestamp; static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom; @@ -35,6 +36,8 @@ static XSelectionEvent selection_event; static uint16 clipboard_channelno; static Atom targets[NUM_TARGETS]; +static int have_primary = 0; +static int rdesktop_is_selection_owner = 0; static void cliprdr_print_server_formats(void) @@ -75,9 +78,9 @@ static void cliprdr_send_format_announce(void) { - DEBUG_CLIPBOARD(("Sending format announce\n")); - STREAM s; + + DEBUG_CLIPBOARD(("Sending (empty) format announce\n")); int number_of_formats = 1; s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4); out_uint32_le(s, number_of_formats*36+12); @@ -101,6 +104,28 @@ clipboard_channelno); } +void cliprdr_ipc_format_announce(unsigned char *data, uint16 length) +{ + STREAM s; + rdesktop_is_selection_owner = 1; + DEBUG_CLIPBOARD(("cliprdr_ipc_format_announce called, length is %d, data is %s, sending native format announce\n", length, data)); + + s = sec_init(encryption ? SEC_ENCRYPT : 0, length+12+4+4); + out_uint32_le(s, length+12); + out_uint32_le(s, 0x13); + out_uint16_le(s, 2); + out_uint16_le(s, 0); + out_uint32_le(s, length); + out_uint8p(s, data, length); + out_uint32_le(s, 0); // Pad + s_mark_end(s); + + sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, + clipboard_channelno); +} + + + static void cliprdr_send_empty_datapacket(void) @@ -193,6 +218,7 @@ wnd, event->time); } + else /* Other clipboard data */ { @@ -221,11 +247,6 @@ return; } - DEBUG_CLIPBOARD(("Received %d bytes of clipboard data from X, there is %d remaining\n", - nitems, bytes_left)); - DEBUG_CLIPBOARD(("type_return is %s\n", - XGetAtomName(display, type_return))); - datap = data; if (nitems+1 <= MAX_CLIPRDR_STANDALONE_DATASIZE) @@ -285,7 +306,7 @@ datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE; } - DEBUG_CLIPBOARD(("Sending %d bytes of data\n", + DEBUG_CLIPBOARD(("Sending %u bytes of data\n", 12+bytes_left_to_transfer)); out = sec_init(encryption ? SEC_ENCRYPT : 0, 12+bytes_left_to_transfer); @@ -303,7 +324,8 @@ XFree(data); - cliprdr_send_format_announce(); + if (!rdesktop_clipboard_target_atom) + cliprdr_send_format_announce(); } @@ -314,6 +336,9 @@ cliprdr_handle_SelectionClear(void) { DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n")); + have_primary = 0; + ipc_send_message(RDESKTOP_IPC_CLIPRDR_PRIMARY_LOST, + "", 0); cliprdr_send_format_announce(); } @@ -343,6 +368,11 @@ { XSelectionEvent xev; + unsigned long nitems, bytes_left; + Atom type_return; + uint32 *wanted_formatcode; + int format; + DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n")); DEBUG_CLIPBOARD(("Requestor window id 0x%x ", (unsigned)xevent->requestor)); @@ -367,7 +397,26 @@ xev.property = xevent->property; xev.time = xevent->time; - if (targets_atom == xevent->target) + memcpy(&selection_event, &xev, sizeof(xev)); + + if (ipc_atom == xevent->target) + { + DEBUG_CLIPBOARD(("Target atom is ipc_atom, getting INTEGER from requestor\n")); + XGetWindowProperty(display, xevent->requestor, + rdesktop_clipboard_target_atom, + 0, + 1, + True, XA_INTEGER, + &type_return, + &format, + &nitems, + &bytes_left, + (unsigned char **)&wanted_formatcode); + DEBUG_CLIPBOARD(("Got wanted formatcode %d, format is %d\n", *wanted_formatcode, format)); + cliprdr_request_clipboard_data(*wanted_formatcode); + } + + else if (targets_atom == xevent->target) { DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n")); XChangeProperty(display, @@ -387,6 +436,7 @@ return; } else if (timestamp_atom == xevent->target) { + DEBUG_CLIPBOARD(("Sending TIMESTAMP\n")); XChangeProperty(display, xevent->requestor, xevent->property, @@ -403,7 +453,6 @@ } else /* Some other target */ { cliprdr_request_clipboard_data(CF_TEXT); - memcpy(&selection_event, &xev, sizeof(xev)); /* Return and wait for data, handled by cliprdr_handle_server_data */ } @@ -439,10 +488,14 @@ uint16 num_formats; cliprdr_dataformat *this, *next; - DEBUG_CLIPBOARD(("cliprdr_register_server_formats\n")); in_uint32_le(s, remaining_length); + DEBUG_CLIPBOARD(("cliprdr_register_server_formats, remaining_length is %d\n", remaining_length)); + num_formats = remaining_length / 36; + + ipc_send_message(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE, + s->p, remaining_length); if (NULL != server_formats) { this = server_formats; next = this->next; @@ -481,6 +534,10 @@ if (wnd != XGetSelectionOwner(display, primary_atom)) { warning("Failed to aquire ownership of PRIMARY clipboard\n"); + } + else + { + have_primary = 1; } XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime); if (wnd != XGetSelectionOwner(display, clipboard_atom)) @@ -490,8 +547,6 @@ } - - static void @@ -545,6 +600,9 @@ bytes_left_to_read)); memcpy(datap, s->p, bytes_left_to_read); } + DEBUG_CLIPBOARD(("Setting target atom (%s) on %d\n", + XGetAtomName(display, selection_event.property), + selection_event.requestor)); XChangeProperty(display, selection_event.requestor, selection_event.property, @@ -560,7 +618,7 @@ NoEventMask, (XEvent *)&selection_event); - if (flags & 0x12) + if (2 == flags) xfree(data); } @@ -582,6 +640,21 @@ selectionowner = XGetSelectionOwner(display, primary_atom); + if (rdesktop_is_selection_owner) + { + DEBUG_CLIPBOARD(("XChangeProperty, rdesktop_is_selection_owner\n")); + XChangeProperty(display, wnd, rdesktop_clipboard_target_atom, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *)&wanted_formatcode, 1); + + XConvertSelection(display, primary_atom, + ipc_atom, + rdesktop_clipboard_target_atom, + wnd, CurrentTime); + return; + } + + if (None != selectionowner) { @@ -682,6 +755,14 @@ } } +void cliprdr_ipc_primary_lost(unsigned char *data, uint16 length) +{ + DEBUG_CLIPBOARD(("cliprdr_ipc_primary_lost called\n")); + if (!have_primary) + cliprdr_send_format_announce(); + rdesktop_is_selection_owner = 0; +} + void cliprdr_init(void) { @@ -697,5 +778,10 @@ targets[3] = XInternAtom(display, "text/unicode", False); targets[4] = XInternAtom(display, "TIMESTAMP", False); targets[5] = XInternAtom(display, "STRING", False); + ipc_register_ipcnotify(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE, + cliprdr_ipc_format_announce); + ipc_register_ipcnotify(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE, + cliprdr_ipc_primary_lost); + }