/[rdesktop]/sourceforge.net/trunk/rdesktop/cliprdr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/cliprdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 395 - (show annotations)
Fri Jun 6 09:32:15 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 20692 byte(s)
Moved some debug code.
Fixed a compiler warning by typecasting correctly.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Clipboard functions
4 Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <X11/Xlib.h>
22 #include <X11/Xatom.h>
23 #include "rdesktop.h"
24
25 extern BOOL encryption;
26 extern Display *display;
27 extern Window wnd;
28 extern Time last_gesturetime;
29 extern Atom ipc_atom;
30
31 // static Time selection_timestamp;
32 static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
33 static Atom rdesktop_clipboard_target_atom, incr_atom;
34 static cliprdr_dataformat *server_formats = NULL;
35 static uint16 num_server_formats = 0;
36 static XSelectionEvent selection_event;
37 static uint16 clipboard_channelno;
38 static Atom targets[NUM_TARGETS];
39 static int have_primary = 0;
40 static int rdesktop_is_selection_owner = 0;
41
42 static void
43 cliprdr_print_server_formats(void)
44 {
45 #ifdef WITH_DEBUG_CLIPBOARD
46 cliprdr_dataformat *this;
47 uint16 i = 0;
48 this = server_formats;
49 DEBUG_CLIPBOARD(("There should be %d server formats.\n", num_server_formats));
50 while (NULL != this)
51 {
52 DEBUG_CLIPBOARD(("Format code %d\n", this->identifier));
53 i++;
54 this = this->next;
55 }
56 DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
57 #endif
58 }
59 /*
60 static void
61 cliprdr_set_selection_timestamp(void)
62 {
63 XEvent xev;
64 DEBUG_CLIPBOARD(("Changing a property in order to get a timestamp\n"));
65 fflush(stdout);
66 XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
67 XA_ATOM, 32, PropModeAppend, 0, 0);
68 DEBUG_CLIPBOARD(("Waiting for PropertyChange on wnd\n"));
69 fflush(stdout);
70 XWindowEvent(display, wnd,
71 PropertyChangeMask, &xev);
72 DEBUG_CLIPBOARD(("Setting selection_timestamp\n"));
73 fflush(stdout);
74 selection_timestamp = xev.xproperty.time;
75 }
76 */
77
78 static void
79 cliprdr_send_format_announce(void)
80 {
81 STREAM s;
82
83 DEBUG_CLIPBOARD(("Sending (empty) format announce\n"));
84 int number_of_formats = 1;
85 s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4);
86 out_uint32_le(s, number_of_formats*36+12);
87 out_uint32_le(s, 0x13);
88 out_uint16_le(s, 2);
89 out_uint16_le(s, 0);
90 out_uint32_le(s, number_of_formats*36);
91
92 // out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
93 // rdp_out_unistr(s, "", 16);
94 // out_uint8s(s, 32);
95
96
97 out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
98 out_uint8s(s, 32);
99
100 out_uint32_le(s, 0);
101
102 s_mark_end(s);
103 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
104 clipboard_channelno);
105 }
106
107 void cliprdr_ipc_format_announce(unsigned char *data, uint16 length)
108 {
109 STREAM s;
110 rdesktop_is_selection_owner = 1;
111 DEBUG_CLIPBOARD(("cliprdr_ipc_format_announce called, length is %d, data is %s, sending native format announce\n", length, data));
112
113 s = sec_init(encryption ? SEC_ENCRYPT : 0, length+12+4+4);
114 out_uint32_le(s, length+12);
115 out_uint32_le(s, 0x13);
116 out_uint16_le(s, 2);
117 out_uint16_le(s, 0);
118 out_uint32_le(s, length);
119 out_uint8p(s, data, length);
120 out_uint32_le(s, 0); // Pad
121 s_mark_end(s);
122
123 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
124 clipboard_channelno);
125 }
126
127
128
129
130 static void
131 cliprdr_send_empty_datapacket(void)
132 {
133 STREAM out;
134 out = sec_init(encryption ? SEC_ENCRYPT : 0,
135 20);
136 out_uint32_le(out, 12);
137 out_uint32_le(out, 0x13);
138 out_uint16_le(out, 5);
139 out_uint16_le(out, 1);
140 out_uint32_le(out, 0);
141 /* Insert null string here? */
142 out_uint32_le(out, 0);
143 s_mark_end(out);
144
145 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
146 clipboard_channelno);
147 }
148
149
150 void
151 cliprdr_handle_SelectionNotify(XSelectionEvent *event)
152 {
153
154 unsigned char *data, *datap;
155 unsigned long nitems, bytes_left;
156
157 unsigned long bytes_left_to_transfer;
158 int res, i;
159
160 int format;
161 Atom type_return;
162 Atom best_target;
163 Atom *supported_targets;
164
165 STREAM out;
166
167 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
168
169 if (None == event->property) {
170 cliprdr_send_empty_datapacket();
171 return; /* Selection failed */
172 }
173
174 DEBUG_CLIPBOARD(("selection: %s, target: %s, property: %s\n",
175 XGetAtomName(display, event->selection),
176 XGetAtomName(display, event->target),
177 XGetAtomName(display, event->property)));
178
179 if (targets_atom == event->target) {
180 /* Response to TARGETS request. Let's find the target
181 we want and request that */
182 res = XGetWindowProperty(display, wnd,
183 rdesktop_clipboard_target_atom,
184 0L, 4096L, False, AnyPropertyType,
185 &type_return,
186 &format, &nitems, &bytes_left, &data);
187
188 if (Success != res)
189 {
190 DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
191 cliprdr_send_empty_datapacket();
192 return;
193 }
194
195 if (None == type_return)
196 /* The owner might no support TARGETS. Just try
197 STRING */
198 best_target = XA_STRING;
199 else
200 {
201 /* FIXME: We should choose format here based
202 on what the server wanted */
203 supported_targets = (Atom *)data;
204 for (i=0;i<nitems;i++)
205 {
206 DEBUG_CLIPBOARD(("Target %d: %s\n",
207 i, XGetAtomName(display,
208 supported_targets[i])));
209 }
210 best_target = XInternAtom(display, "TEXT", False);
211
212
213 }
214
215 XConvertSelection(display, primary_atom,
216 best_target,
217 rdesktop_clipboard_target_atom,
218 wnd, event->time);
219
220 }
221
222 else /* Other clipboard data */
223 {
224
225 res = XGetWindowProperty(display, wnd,
226 rdesktop_clipboard_target_atom,
227 0L, 0x1FFFFFF,
228 True, AnyPropertyType,
229 &type_return,
230 &format, &nitems, &bytes_left, &data);
231
232
233 /* FIXME: We need to handle INCR as well,
234 this is a temporary solution. */
235
236 if (incr_atom == type_return)
237 {
238 warning("We don't support INCR transfers at this time. Try cutting less data\n");
239 cliprdr_send_empty_datapacket();
240 }
241
242
243 if (Success != res)
244 {
245 DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
246 cliprdr_send_empty_datapacket();
247 return;
248 }
249
250 datap = data;
251
252 if (nitems+1 <= MAX_CLIPRDR_STANDALONE_DATASIZE)
253 {
254 out = sec_init(encryption ? SEC_ENCRYPT : 0,
255 20+nitems+1);
256 out_uint32_le(out, 12+nitems+1);
257 out_uint32_le(out, 0x13);
258 out_uint16_le(out, 5);
259 out_uint16_le(out, 1);
260 out_uint32_le(out, nitems+1);
261 out_uint8p(out, datap, nitems+1);
262 out_uint32_le(out, 0);
263 s_mark_end(out);
264
265 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
266 clipboard_channelno);
267
268 }
269 else
270 {
271 DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
272 16+MAX_CLIPRDR_STANDALONE_DATASIZE));
273 out = sec_init(encryption ? SEC_ENCRYPT : 0,
274 16+MAX_CLIPRDR_STANDALONE_DATASIZE);
275 out_uint32_le(out, nitems+12);
276 out_uint32_le(out, 0x11);
277 out_uint16_le(out, 5);
278 out_uint16_le(out, 1);
279 out_uint32_le(out, nitems);
280 out_uint8p(out, datap,
281 MAX_CLIPRDR_STANDALONE_DATASIZE);
282 s_mark_end(out);
283
284 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
285 clipboard_channelno);
286
287 bytes_left_to_transfer = nitems - MAX_CLIPRDR_STANDALONE_DATASIZE;
288 datap+=MAX_CLIPRDR_STANDALONE_DATASIZE;
289
290 while (bytes_left_to_transfer > MAX_CLIPRDR_STANDALONE_DATASIZE)
291 {
292 DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
293 16+MAX_CLIPRDR_CONTINUATION_DATASIZE));
294 out = sec_init(encryption ? SEC_ENCRYPT : 0,
295 8+MAX_CLIPRDR_CONTINUATION_DATASIZE);
296 out_uint32_le(out, nitems);
297 out_uint32_le(out, 0x10);
298 out_uint8p(out, datap,
299 MAX_CLIPRDR_CONTINUATION_DATASIZE);
300 s_mark_end(out);
301
302 sec_send_to_channel(out,
303 encryption ? SEC_ENCRYPT : 0,
304 clipboard_channelno);
305 bytes_left_to_transfer-= MAX_CLIPRDR_CONTINUATION_DATASIZE;
306 datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE;
307
308 }
309 DEBUG_CLIPBOARD(("Sending %u bytes of data\n",
310 12+bytes_left_to_transfer));
311 out = sec_init(encryption ? SEC_ENCRYPT : 0,
312 12+bytes_left_to_transfer);
313 out_uint32_le(out, nitems);
314 out_uint32_le(out, 0x12);
315 out_uint8p(out, datap,
316 bytes_left_to_transfer);
317 out_uint32_le(out, 0x0);
318 s_mark_end(out);
319
320 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
321 clipboard_channelno);
322
323 }
324
325
326 XFree(data);
327 if (!rdesktop_clipboard_target_atom)
328 cliprdr_send_format_announce();
329
330 }
331
332
333 }
334
335 void
336 cliprdr_handle_SelectionClear(void)
337 {
338 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
339 have_primary = 0;
340 ipc_send_message(RDESKTOP_IPC_CLIPRDR_PRIMARY_LOST,
341 "", 0);
342 cliprdr_send_format_announce();
343 }
344
345
346 static void
347 cliprdr_request_clipboard_data(uint32 formatcode)
348 {
349 STREAM s;
350 s = sec_init(encryption ? SEC_ENCRYPT : 0, 24);
351 out_uint32_le(s, 16);
352 out_uint32_le(s, 0x13);
353 out_uint16_le(s, 4);
354 out_uint16_le(s, 0);
355 out_uint32_le(s, 4); // Remaining length
356 out_uint32_le(s, formatcode);
357 out_uint32_le(s, 0); // Unknown. Garbage pad?
358
359 s_mark_end(s);
360
361 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
362 clipboard_channelno);
363 }
364
365
366 void
367 cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
368 {
369
370 XSelectionEvent xev;
371 unsigned long nitems, bytes_left;
372 Atom type_return;
373 uint32 *wanted_formatcode;
374 int format;
375
376 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
377 DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
378 (unsigned)xevent->requestor));
379 if (clipboard_atom == xevent->selection) {
380 DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
381 }
382 if (primary_atom == xevent->selection) {
383 DEBUG_CLIPBOARD(("wants PRIMARY\n"));
384 }
385 DEBUG_CLIPBOARD(("Target is %s (0x%x), property is %s (0x%x)\n",
386 XGetAtomName(display, xevent->target),
387 (unsigned)xevent->target,
388 XGetAtomName(display, xevent->property),
389 (unsigned)xevent->property));
390
391 xev.type = SelectionNotify;
392 xev.serial = 0;
393 xev.send_event = True;
394 xev.requestor = xevent->requestor;
395 xev.selection = xevent->selection;
396 xev.target = xevent->target;
397 xev.property = xevent->property;
398 xev.time = xevent->time;
399
400 memcpy(&selection_event, &xev, sizeof(xev));
401
402 if (ipc_atom == xevent->target)
403 {
404 DEBUG_CLIPBOARD(("Target atom is ipc_atom, getting INTEGER from requestor\n"));
405 XGetWindowProperty(display, xevent->requestor,
406 rdesktop_clipboard_target_atom,
407 0,
408 1,
409 True, XA_INTEGER,
410 &type_return,
411 &format,
412 &nitems,
413 &bytes_left,
414 (unsigned char **)&wanted_formatcode);
415 DEBUG_CLIPBOARD(("Got wanted formatcode %d, format is %d\n", *wanted_formatcode, format));
416 cliprdr_request_clipboard_data(*wanted_formatcode);
417 }
418
419 else if (targets_atom == xevent->target)
420 {
421 DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
422 XChangeProperty(display,
423 xevent->requestor,
424 xevent->property,
425 XA_ATOM,
426 32,
427 PropModeAppend,
428 (unsigned char *)&targets,
429 NUM_TARGETS);
430
431 XSendEvent(display,
432 xevent->requestor,
433 False,
434 NoEventMask,
435 (XEvent *)&xev);
436 return;
437 } else if (timestamp_atom == xevent->target)
438 {
439 DEBUG_CLIPBOARD(("Sending TIMESTAMP\n"));
440 XChangeProperty(display,
441 xevent->requestor,
442 xevent->property,
443 XA_INTEGER,
444 32,
445 PropModeAppend,
446 (unsigned char *)&last_gesturetime,
447 1);
448 XSendEvent(display,
449 xevent->requestor,
450 False,
451 NoEventMask,
452 (XEvent *)&xev);
453 } else /* Some other target */
454 {
455 cliprdr_request_clipboard_data(CF_TEXT);
456 /* Return and wait for data, handled by
457 cliprdr_handle_server_data */
458 }
459 }
460
461
462 static void
463 cliprdr_ack_format_list(void)
464 {
465 STREAM s;
466 s = sec_init(encryption ? SEC_ENCRYPT : 0, 20);
467 out_uint32_le(s, 12);
468 out_uint32_le(s, 0x13);
469 out_uint16_le(s, 3);
470 out_uint16_le(s, 1);
471 out_uint32_le(s, 0);
472 out_uint32_le(s, 0x0000c0da);
473
474 s_mark_end(s);
475
476 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
477 clipboard_channelno);
478 }
479
480
481
482
483
484 static void
485 cliprdr_register_server_formats(STREAM s)
486 {
487 uint32 remaining_length, pad;
488 uint16 num_formats;
489 cliprdr_dataformat *this, *next;
490
491 in_uint32_le(s, remaining_length);
492 DEBUG_CLIPBOARD(("cliprdr_register_server_formats, remaining_length is %d\n", remaining_length));
493
494
495 num_formats = remaining_length / 36;
496
497 ipc_send_message(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE,
498 s->p, remaining_length);
499 if (NULL != server_formats) {
500 this = server_formats;
501 next = this->next;
502 while (NULL != next) {
503 xfree(this);
504 this = NULL;
505 this = next;
506 next = this->next;
507 }
508 }
509 this = xmalloc(sizeof(cliprdr_dataformat));
510 this->next = NULL;
511 server_formats = this;
512 num_server_formats = num_formats;
513 while (1 < num_formats) {
514 in_uint32_le(s, this->identifier);
515 in_uint8a(s, this->textual_description, 32);
516 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
517 this->identifier));
518 this-> next = xmalloc(sizeof(cliprdr_dataformat));
519 this = this->next;
520 num_formats--;
521 }
522 in_uint32_le(s, this->identifier);
523 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));
524 in_uint8a(s, this->textual_description, 32);
525 this -> next = NULL;
526 in_uint32_le(s, pad);
527 cliprdr_print_server_formats();
528 }
529
530 static void
531 cliprdr_select_X_clipboards(void)
532 {
533 XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
534 if (wnd != XGetSelectionOwner(display, primary_atom))
535 {
536 warning("Failed to aquire ownership of PRIMARY clipboard\n");
537 }
538 else
539 {
540 have_primary = 1;
541 }
542 XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
543 if (wnd != XGetSelectionOwner(display, clipboard_atom))
544 {
545 warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
546 }
547
548 }
549
550
551
552 static void
553 cliprdr_handle_first_handshake(STREAM s)
554 {
555 uint32 remaining_length, pad;
556 in_uint32_le(s, remaining_length);
557 in_uint32_le(s, pad);
558 DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
559 remaining_length, pad));
560 cliprdr_send_format_announce();
561 }
562
563 void cliprdr_handle_server_data(uint32 length, uint32 flags, STREAM s)
564 {
565 static uint32 remaining_length;
566 static char *data, *datap;
567 static uint32 bytes_left_to_read;
568 DEBUG_CLIPBOARD(("In cliprdr_handle_server_data, flags is %d\n",
569 flags));
570 if (3 == flags) /* One-op write, no packets follows */
571 {
572 in_uint32_le(s, remaining_length);
573 data = s->p;
574 } else if (1 == flags) /* First of several packets */
575 {
576 in_uint32_le(s, remaining_length);
577 DEBUG_CLIPBOARD(("Remaining length is %d\n",
578 remaining_length));
579 data = xmalloc(remaining_length);
580 datap = data;
581 DEBUG_CLIPBOARD(("Copying first %d bytes\n",
582 MAX_CLIPRDR_STANDALONE_DATASIZE));
583 memcpy(datap, s->p, MAX_CLIPRDR_STANDALONE_DATASIZE);
584
585 datap+=MAX_CLIPRDR_STANDALONE_DATASIZE;
586 bytes_left_to_read = remaining_length-MAX_CLIPRDR_STANDALONE_DATASIZE;
587 return;
588 } else if (0 == flags)
589 {
590 DEBUG_CLIPBOARD(("Copying %d middle bytes",
591 MAX_CLIPRDR_CONTINUATION_DATASIZE));
592 memcpy(datap, s->p, MAX_CLIPRDR_CONTINUATION_DATASIZE);
593
594 datap+=MAX_CLIPRDR_CONTINUATION_DATASIZE;
595 bytes_left_to_read-=MAX_CLIPRDR_CONTINUATION_DATASIZE;
596 return;
597 } else if (2 == flags)
598 {
599 DEBUG_CLIPBOARD(("Copying last %d bytes\n",
600 bytes_left_to_read));
601 memcpy(datap, s->p, bytes_left_to_read);
602 }
603 DEBUG_CLIPBOARD(("Setting target atom (%s) on %d\n",
604 XGetAtomName(display, selection_event.property),
605 selection_event.requestor));
606 XChangeProperty(display,
607 selection_event.requestor,
608 selection_event.property,
609 XInternAtom(display, "STRING", False),
610 8,
611 PropModeAppend,
612 data,
613 remaining_length-1);
614
615 XSendEvent(display,
616 selection_event.requestor,
617 False,
618 NoEventMask,
619 (XEvent *)&selection_event);
620
621 if (2 == flags)
622 xfree(data);
623
624 }
625
626 void cliprdr_handle_server_data_request(STREAM s)
627 {
628 Window selectionowner;
629 uint32 remaining_length;
630 uint32 wanted_formatcode, pad;
631
632 in_uint32_le(s, remaining_length);
633 in_uint32_le(s, wanted_formatcode);
634 in_uint32_le(s, pad);
635
636 /* FIXME: Check that we support this formatcode */
637
638 DEBUG_CLIPBOARD(("Request from server for format %d\n",
639 wanted_formatcode));
640
641 selectionowner = XGetSelectionOwner(display, primary_atom);
642
643 if (rdesktop_is_selection_owner)
644 {
645 DEBUG_CLIPBOARD(("XChangeProperty, rdesktop_is_selection_owner\n"));
646 XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
647 XA_INTEGER, 32, PropModeReplace,
648 (unsigned char *)&wanted_formatcode, 1);
649
650 XConvertSelection(display, primary_atom,
651 ipc_atom,
652 rdesktop_clipboard_target_atom,
653 wnd, CurrentTime);
654 return;
655 }
656
657
658 if (None != selectionowner)
659 {
660
661 /* FIXME: Perhaps we should check if we are the owner? */
662
663 XConvertSelection(display, primary_atom,
664 targets_atom,
665 rdesktop_clipboard_target_atom,
666 wnd, CurrentTime);
667
668 /* The rest of the transfer is handled in
669 cliprdr_handle_SelectionNotify */
670
671 } else
672 {
673 DEBUG_CLIPBOARD(("There were no owner for PRIMARY, sending empty string\n")); // FIXME: Should we always send an empty string?
674
675 cliprdr_send_empty_datapacket();
676 }
677
678
679 }
680
681
682 void cliprdr_callback(STREAM s, uint16 channelno)
683 {
684 static int failed_clipboard_acks = 0;
685 struct timeval timeval;
686 uint32 length, flags;
687 uint16 ptype0, ptype1;
688 clipboard_channelno = channelno;
689 DEBUG_CLIPBOARD(("cliprdr_callback called with channelno %d, clipboard data:\n", channelno));
690 #ifdef WITH_DEBUG_CLIPBOARD
691 // hexdump(s->p, s->end - s->p);
692 #endif
693 in_uint32_le(s, length);
694 in_uint32_le(s, flags);
695
696 DEBUG_CLIPBOARD(("length is %d, flags are %d\n", length, flags));
697
698 if (3 == flags || 1 == flags) /* Single-write op or first-packet-of-several op */
699 {
700 in_uint16_le(s, ptype0);
701 in_uint16_le(s, ptype1);
702 DEBUG_CLIPBOARD(("ptype0 is %d, ptype1 is %d\n", ptype0, ptype1));
703 if (1 == ptype0 && 0 == ptype1) {
704 cliprdr_handle_first_handshake(s);
705 return;
706 } else if (3 == ptype0 && 1 == ptype1)
707 {
708 // Acknowledgment on our format announce. Do we care? Not right now.
709 // There is a strange pad in this packet that we might need some time,
710 // but probably not.
711 DEBUG_CLIPBOARD(("Received format announce ACK\n"));
712 failed_clipboard_acks = 0;
713 return;
714
715 } else if (3 == ptype0 && 2 == ptype1)
716 {
717 DEBUG_CLIPBOARD(("Received failed clipboard format announce ACK, retrying\n"));
718
719 /* This is a fairly portable way to sleep 1/10 of
720 a second.. */
721 timeval.tv_sec = 0;
722 timeval.tv_usec = 100;
723 select(0, NULL, NULL, NULL, &timeval);
724 if (failed_clipboard_acks < 3)
725 {
726
727 cliprdr_send_format_announce();
728 /* Make sure we don't get stuck in this loop */
729 failed_clipboard_acks++;
730 }
731 else
732 {
733 warning("Reached maximum number of clipboard format announce attempts. Pasting in Windows probably won't work well now.\n");
734 }
735 } else if (2 == ptype0 && 0 == ptype1)
736 {
737 cliprdr_register_server_formats(s);
738 cliprdr_select_X_clipboards();
739 cliprdr_ack_format_list();
740 return;
741 } else if (5 == ptype0 && 1 == ptype1)
742 {
743 cliprdr_handle_server_data(length, flags, s);
744 } else if (4 == ptype0 && 0 == ptype1)
745 {
746 cliprdr_handle_server_data_request(s);
747 }
748
749
750 }
751 else
752 {
753 DEBUG_CLIPBOARD(("Handling middle or last packet\n"));
754 cliprdr_handle_server_data(length, flags, s);
755 }
756 }
757
758 void cliprdr_ipc_primary_lost(unsigned char *data, uint16 length)
759 {
760 DEBUG_CLIPBOARD(("cliprdr_ipc_primary_lost called\n"));
761 if (!have_primary)
762 cliprdr_send_format_announce();
763 rdesktop_is_selection_owner = 0;
764 }
765
766
767 void cliprdr_init(void)
768 {
769 primary_atom = XInternAtom(display, "PRIMARY", False);
770 clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
771 targets_atom = XInternAtom(display, "TARGETS", False);
772 timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
773 rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
774 incr_atom = XInternAtom(display, "INCR", False);
775 targets[0] = targets_atom;
776 targets[1] = XInternAtom(display, "TEXT", False);
777 targets[2] = XInternAtom(display, "UTF8_STRING", False);
778 targets[3] = XInternAtom(display, "text/unicode", False);
779 targets[4] = XInternAtom(display, "TIMESTAMP", False);
780 targets[5] = XInternAtom(display, "STRING", False);
781 ipc_register_ipcnotify(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE,
782 cliprdr_ipc_format_announce);
783 ipc_register_ipcnotify(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE,
784 cliprdr_ipc_primary_lost);
785
786
787 }

  ViewVC Help
Powered by ViewVC 1.1.26