/[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 420 - (show annotations)
Wed Jun 11 09:00:38 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 20778 byte(s)
Used the wrong variable by mistake when checking whether a format announce
should be sent or not after transferring data X -> Windows.

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

  ViewVC Help
Powered by ViewVC 1.1.26