/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 394 - (hide annotations)
Fri Jun 6 09:31:28 2003 UTC (21 years ago) by forsberg
File MIME type: text/plain
File size: 20645 byte(s)
Handle transfers rdesktop <-> rdesktop with native windows formats.

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

  ViewVC Help
Powered by ViewVC 1.1.26