/[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 402 - (show annotations)
Fri Jun 6 10:39:10 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 20717 byte(s)
Try getting clipboard from CLIPBOARD if there is no owner for PRIMARY.

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

  ViewVC Help
Powered by ViewVC 1.1.26