/[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 395 - (hide annotations)
Fri Jun 6 09:32:15 2003 UTC (21 years 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 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 395 STREAM s;
82    
83 forsberg 394 DEBUG_CLIPBOARD(("Sending (empty) format announce\n"));
84 forsberg 387 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 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 forsberg 386
265 forsberg 391 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0,
266     clipboard_channelno);
267 forsberg 388
268 forsberg 391 }
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 forsberg 395 DEBUG_CLIPBOARD(("Sending %u bytes of data\n",
310 forsberg 391 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 forsberg 394 if (!rdesktop_clipboard_target_atom)
328     cliprdr_send_format_announce();
329 forsberg 386
330     }
331    
332    
333 forsberg 383 }
334    
335     void
336     cliprdr_handle_SelectionClear(void)
337     {
338     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
339 forsberg 394 have_primary = 0;
340     ipc_send_message(RDESKTOP_IPC_CLIPRDR_PRIMARY_LOST,
341     "", 0);
342 forsberg 387 cliprdr_send_format_announce();
343 forsberg 383 }
344    
345    
346 forsberg 384 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 forsberg 390 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
362     clipboard_channelno);
363 forsberg 384 }
364    
365    
366 forsberg 383 void
367     cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
368     {
369    
370     XSelectionEvent xev;
371 forsberg 394 unsigned long nitems, bytes_left;
372     Atom type_return;
373     uint32 *wanted_formatcode;
374     int format;
375    
376 forsberg 383 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
377 forsberg 384 DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
378     (unsigned)xevent->requestor));
379 forsberg 383 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 forsberg 384 (unsigned)xevent->target,
388 forsberg 383 XGetAtomName(display, xevent->property),
389 forsberg 384 (unsigned)xevent->property));
390 forsberg 383
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 forsberg 394 memcpy(&selection_event, &xev, sizeof(xev));
401    
402     if (ipc_atom == xevent->target)
403 forsberg 383 {
404 forsberg 394 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 forsberg 395 (unsigned char **)&wanted_formatcode);
415 forsberg 394 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 forsberg 383 DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
422 forsberg 391 XChangeProperty(display,
423     xevent->requestor,
424     xevent->property,
425     XA_ATOM,
426     32,
427     PropModeAppend,
428     (unsigned char *)&targets,
429     NUM_TARGETS);
430 forsberg 383
431 forsberg 391 XSendEvent(display,
432     xevent->requestor,
433     False,
434     NoEventMask,
435     (XEvent *)&xev);
436 forsberg 383 return;
437     } else if (timestamp_atom == xevent->target)
438     {
439 forsberg 395 DEBUG_CLIPBOARD(("Sending TIMESTAMP\n"));
440 forsberg 391 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 forsberg 383 } else /* Some other target */
454     {
455 forsberg 384 cliprdr_request_clipboard_data(CF_TEXT);
456     /* Return and wait for data, handled by
457     cliprdr_handle_server_data */
458     }
459     }
460 forsberg 383
461    
462 forsberg 384 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 forsberg 390 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0,
477     clipboard_channelno);
478 forsberg 383 }
479    
480 forsberg 384
481 forsberg 383
482 forsberg 384
483    
484 forsberg 383 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 forsberg 394 DEBUG_CLIPBOARD(("cliprdr_register_server_formats, remaining_length is %d\n", remaining_length));
493 forsberg 383
494 forsberg 394
495 forsberg 383 num_formats = remaining_length / 36;
496 forsberg 394
497     ipc_send_message(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE,
498     s->p, remaining_length);
499 forsberg 383 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 forsberg 384 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
517     this->identifier));
518 forsberg 383 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 forsberg 388 XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
534 forsberg 383 if (wnd != XGetSelectionOwner(display, primary_atom))
535     {
536     warning("Failed to aquire ownership of PRIMARY clipboard\n");
537 forsberg 394 }
538     else
539     {
540     have_primary = 1;
541 forsberg 383 }
542 forsberg 388 XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
543 forsberg 383 if (wnd != XGetSelectionOwner(display, clipboard_atom))
544     {
545     warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
546     }
547    
548     }
549    
550 forsberg 384
551 forsberg 385
552 forsberg 383 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 forsberg 392 void cliprdr_handle_server_data(uint32 length, uint32 flags, STREAM s)
564 forsberg 384 {
565 forsberg 392 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 forsberg 395 DEBUG_CLIPBOARD(("Setting target atom (%s) on %d\n",
604     XGetAtomName(display, selection_event.property),
605     selection_event.requestor));
606 forsberg 388 XChangeProperty(display,
607     selection_event.requestor,
608     selection_event.property,
609     XInternAtom(display, "STRING", False),
610     8,
611     PropModeAppend,
612     data,
613 forsberg 392 remaining_length-1);
614 forsberg 384
615 forsberg 388 XSendEvent(display,
616     selection_event.requestor,
617     False,
618     NoEventMask,
619     (XEvent *)&selection_event);
620 forsberg 384
621 forsberg 393 if (2 == flags)
622 forsberg 392 xfree(data);
623    
624 forsberg 384 }
625    
626 forsberg 385 void cliprdr_handle_server_data_request(STREAM s)
627     {
628 forsberg 386 Window selectionowner;
629 forsberg 385 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 forsberg 386 selectionowner = XGetSelectionOwner(display, primary_atom);
642 forsberg 385
643 forsberg 394 if (rdesktop_is_selection_owner)
644     {
645 forsberg 395 DEBUG_CLIPBOARD(("XChangeProperty, rdesktop_is_selection_owner\n"));
646 forsberg 394 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 forsberg 386 if (None != selectionowner)
659     {
660 forsberg 385
661 forsberg 386 /* FIXME: Perhaps we should check if we are the owner? */
662 forsberg 385
663 forsberg 386 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 forsberg 385 {
673 forsberg 386 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 forsberg 385 }
677 forsberg 386
678    
679 forsberg 385 }
680    
681    
682 forsberg 390 void cliprdr_callback(STREAM s, uint16 channelno)
683 forsberg 383 {
684 forsberg 389 static int failed_clipboard_acks = 0;
685     struct timeval timeval;
686 forsberg 383 uint32 length, flags;
687     uint16 ptype0, ptype1;
688 forsberg 390 clipboard_channelno = channelno;
689     DEBUG_CLIPBOARD(("cliprdr_callback called with channelno %d, clipboard data:\n", channelno));
690 forsberg 383 #ifdef WITH_DEBUG_CLIPBOARD
691 forsberg 392 // hexdump(s->p, s->end - s->p);
692 forsberg 383 #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 forsberg 392 if (3 == flags || 1 == flags) /* Single-write op or first-packet-of-several op */
699 forsberg 383 {
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 forsberg 389 failed_clipboard_acks = 0;
713 forsberg 383 return;
714 forsberg 384
715 forsberg 389 } 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 forsberg 383 } else if (2 == ptype0 && 0 == ptype1)
736     {
737     cliprdr_register_server_formats(s);
738     cliprdr_select_X_clipboards();
739 forsberg 384 cliprdr_ack_format_list();
740 forsberg 383 return;
741 forsberg 384 } else if (5 == ptype0 && 1 == ptype1)
742     {
743 forsberg 392 cliprdr_handle_server_data(length, flags, s);
744 forsberg 385 } else if (4 == ptype0 && 0 == ptype1)
745     {
746     cliprdr_handle_server_data_request(s);
747 forsberg 383 }
748 forsberg 385
749 forsberg 383
750 forsberg 392 }
751     else
752     {
753     DEBUG_CLIPBOARD(("Handling middle or last packet\n"));
754     cliprdr_handle_server_data(length, flags, s);
755 forsberg 383 }
756     }
757    
758 forsberg 394 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 forsberg 384
766 forsberg 394
767 forsberg 383 void cliprdr_init(void)
768     {
769     primary_atom = XInternAtom(display, "PRIMARY", False);
770     clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
771 forsberg 386 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 forsberg 391 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 forsberg 394 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 forsberg 391
786 forsberg 394
787 forsberg 383 }

  ViewVC Help
Powered by ViewVC 1.1.26