/[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 418 - (hide annotations)
Fri Jun 6 12:34:56 2003 UTC (21 years ago) by forsberg
File MIME type: text/plain
File size: 20781 byte(s)
Added headers needed for compilation under FreeBSD (4.8 stable).
Moved DEBUG_CLIPBOARD in cliprdr_send_format_announce.

(Thanks goes to Maikel Verheijen <maikel <at> ladot <dot> com> for pointing
 this out)

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 forsberg 418 #include <sys/time.h>
24     #include <sys/types.h>
25     #include <unistd.h>
26 forsberg 383 #include "rdesktop.h"
27    
28     extern BOOL encryption;
29     extern Display *display;
30     extern Window wnd;
31 forsberg 388 extern Time last_gesturetime;
32 forsberg 394 extern Atom ipc_atom;
33 forsberg 383
34 forsberg 388 // static Time selection_timestamp;
35 forsberg 383 static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
36 forsberg 391 static Atom rdesktop_clipboard_target_atom, incr_atom;
37 forsberg 383 static cliprdr_dataformat *server_formats = NULL;
38     static uint16 num_server_formats = 0;
39 forsberg 384 static XSelectionEvent selection_event;
40 forsberg 390 static uint16 clipboard_channelno;
41 forsberg 391 static Atom targets[NUM_TARGETS];
42 forsberg 394 static int have_primary = 0;
43     static int rdesktop_is_selection_owner = 0;
44 forsberg 383
45     static void
46 forsberg 396 cliprdr_print_server_formats(void)
47 forsberg 383 {
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 forsberg 396 while (NULL != this)
54 forsberg 383 {
55     DEBUG_CLIPBOARD(("Format code %d\n", this->identifier));
56     i++;
57     this = this->next;
58     }
59 forsberg 384 DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
60 forsberg 383 #endif
61     }
62 forsberg 396
63 forsberg 388 /*
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 forsberg 396 */
81 forsberg 383
82 forsberg 386 static void
83 forsberg 396 cliprdr_send_format_announce(void)
84 forsberg 387 {
85 forsberg 395 STREAM s;
86 forsberg 418 int number_of_formats = 1;
87 forsberg 394 DEBUG_CLIPBOARD(("Sending (empty) format announce\n"));
88 forsberg 396 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 forsberg 387 out_uint32_le(s, 0x13);
91     out_uint16_le(s, 2);
92     out_uint16_le(s, 0);
93 forsberg 396 out_uint32_le(s, number_of_formats * 36);
94 forsberg 387
95 forsberg 396 // 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 forsberg 387
99 forsberg 396
100     out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
101 forsberg 387 out_uint8s(s, 32);
102    
103 forsberg 396 out_uint32_le(s, 0);
104 forsberg 387
105     s_mark_end(s);
106 forsberg 396 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
107 forsberg 387 }
108    
109 forsberg 396 void
110     cliprdr_ipc_format_announce(unsigned char *data, uint16 length)
111 forsberg 394 {
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 forsberg 387
116 forsberg 396 s = sec_init(encryption ? SEC_ENCRYPT : 0, length + 12 + 4 + 4);
117     out_uint32_le(s, length + 12);
118 forsberg 394 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 forsberg 396 out_uint32_le(s, 0); // Pad
124 forsberg 394 s_mark_end(s);
125    
126 forsberg 396 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
127 forsberg 394 }
128    
129    
130    
131    
132 forsberg 387 static void
133 forsberg 386 cliprdr_send_empty_datapacket(void)
134     {
135     STREAM out;
136 forsberg 396 out = sec_init(encryption ? SEC_ENCRYPT : 0, 20);
137 forsberg 386 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 forsberg 396
146     sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
147 forsberg 386 }
148    
149    
150 forsberg 396 void
151     cliprdr_handle_SelectionNotify(XSelectionEvent * event)
152 forsberg 383 {
153 forsberg 386
154 forsberg 396 unsigned char *data, *datap;
155     unsigned long nitems, bytes_left;
156    
157 forsberg 391 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 forsberg 396
167 forsberg 383 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
168 forsberg 386
169 forsberg 396 if (None == event->property)
170     {
171 forsberg 386 cliprdr_send_empty_datapacket();
172 forsberg 396 return; /* Selection failed */
173     }
174 forsberg 386
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 forsberg 396 if (targets_atom == event->target)
181     {
182 forsberg 386 /* Response to TARGETS request. Let's find the target
183     we want and request that */
184 forsberg 396 res = XGetWindowProperty(display, wnd,
185 forsberg 386 rdesktop_clipboard_target_atom,
186 forsberg 396 0L, 4096L, False, AnyPropertyType,
187     &type_return, &format, &nitems, &bytes_left, &data);
188 forsberg 386
189 forsberg 396 if (Success != res)
190 forsberg 386 {
191     DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
192     cliprdr_send_empty_datapacket();
193     return;
194     }
195    
196 forsberg 396 if (None == type_return)
197 forsberg 386 /* The owner might no support TARGETS. Just try
198     STRING */
199     best_target = XA_STRING;
200 forsberg 396 else
201 forsberg 386 {
202     /* FIXME: We should choose format here based
203     on what the server wanted */
204 forsberg 396 supported_targets = (Atom *) data;
205     for (i = 0; i < nitems; i++)
206 forsberg 391 {
207 forsberg 396 DEBUG_CLIPBOARD(("Target %d: %s\n",
208     i, XGetAtomName(display, supported_targets[i])));
209 forsberg 391 }
210 forsberg 386 best_target = XInternAtom(display, "TEXT", False);
211 forsberg 396
212    
213 forsberg 386 }
214    
215 forsberg 396 XConvertSelection(display, primary_atom,
216     best_target, rdesktop_clipboard_target_atom, wnd, event->time);
217 forsberg 386
218 forsberg 396 }
219 forsberg 394
220 forsberg 396 else /* Other clipboard data */
221 forsberg 386 {
222 forsberg 396
223     res = XGetWindowProperty(display, wnd,
224 forsberg 386 rdesktop_clipboard_target_atom,
225 forsberg 396 0L, 0x1FFFFFF,
226     True, AnyPropertyType,
227     &type_return, &format, &nitems, &bytes_left, &data);
228 forsberg 386
229 forsberg 391
230     /* FIXME: We need to handle INCR as well,
231 forsberg 396 this is a temporary solution. */
232 forsberg 391
233 forsberg 396 if (incr_atom == type_return)
234 forsberg 391 {
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 forsberg 396 if (Success != res)
241 forsberg 386 {
242     DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
243     cliprdr_send_empty_datapacket();
244     return;
245     }
246    
247 forsberg 391 datap = data;
248    
249 forsberg 396 if (nitems + 1 <= MAX_CLIPRDR_STANDALONE_DATASIZE)
250 forsberg 391 {
251 forsberg 396 out = sec_init(encryption ? SEC_ENCRYPT : 0, 20 + nitems + 1);
252     out_uint32_le(out, 12 + nitems + 1);
253 forsberg 391 out_uint32_le(out, 0x13);
254     out_uint16_le(out, 5);
255     out_uint16_le(out, 1);
256 forsberg 396 out_uint32_le(out, nitems + 1);
257     out_uint8p(out, datap, nitems + 1);
258 forsberg 391 out_uint32_le(out, 0);
259     s_mark_end(out);
260 forsberg 388
261 forsberg 396 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
262    
263     }
264 forsberg 391 else
265     {
266     DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
267 forsberg 396 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 forsberg 391 out_uint32_le(out, 0x11);
272     out_uint16_le(out, 5);
273     out_uint16_le(out, 1);
274     out_uint32_le(out, nitems);
275 forsberg 396 out_uint8p(out, datap, MAX_CLIPRDR_STANDALONE_DATASIZE);
276 forsberg 391 s_mark_end(out);
277    
278 forsberg 396 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
279    
280 forsberg 391 bytes_left_to_transfer = nitems - MAX_CLIPRDR_STANDALONE_DATASIZE;
281 forsberg 396 datap += MAX_CLIPRDR_STANDALONE_DATASIZE;
282 forsberg 391
283 forsberg 396 while (bytes_left_to_transfer > MAX_CLIPRDR_STANDALONE_DATASIZE)
284 forsberg 391 {
285     DEBUG_CLIPBOARD(("Sending %d bytes of data\n",
286 forsberg 396 16 + MAX_CLIPRDR_CONTINUATION_DATASIZE));
287     out = sec_init(encryption ? SEC_ENCRYPT : 0,
288     8 + MAX_CLIPRDR_CONTINUATION_DATASIZE);
289 forsberg 391 out_uint32_le(out, nitems);
290     out_uint32_le(out, 0x10);
291 forsberg 396 out_uint8p(out, datap, MAX_CLIPRDR_CONTINUATION_DATASIZE);
292 forsberg 391 s_mark_end(out);
293    
294 forsberg 396 sec_send_to_channel(out,
295     encryption ? SEC_ENCRYPT : 0,
296 forsberg 391 clipboard_channelno);
297 forsberg 396 bytes_left_to_transfer -= MAX_CLIPRDR_CONTINUATION_DATASIZE;
298     datap += MAX_CLIPRDR_CONTINUATION_DATASIZE;
299    
300 forsberg 391 }
301 forsberg 396 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 forsberg 391 out_uint32_le(out, nitems);
305     out_uint32_le(out, 0x12);
306 forsberg 396 out_uint8p(out, datap, bytes_left_to_transfer);
307 forsberg 391 out_uint32_le(out, 0x0);
308     s_mark_end(out);
309    
310 forsberg 396 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
311    
312 forsberg 391 }
313    
314    
315     XFree(data);
316 forsberg 394 if (!rdesktop_clipboard_target_atom)
317     cliprdr_send_format_announce();
318 forsberg 396
319 forsberg 386 }
320 forsberg 396
321    
322 forsberg 383 }
323    
324     void
325     cliprdr_handle_SelectionClear(void)
326     {
327     DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
328 forsberg 394 have_primary = 0;
329 forsberg 396 ipc_send_message(RDESKTOP_IPC_CLIPRDR_PRIMARY_LOST, "", 0);
330 forsberg 387 cliprdr_send_format_announce();
331 forsberg 383 }
332    
333    
334 forsberg 384 static void
335 forsberg 396 cliprdr_request_clipboard_data(uint32 formatcode)
336 forsberg 384 {
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 forsberg 396 out_uint32_le(s, 4); // Remaining length
344 forsberg 384 out_uint32_le(s, formatcode);
345 forsberg 396 out_uint32_le(s, 0); // Unknown. Garbage pad?
346 forsberg 384
347     s_mark_end(s);
348    
349 forsberg 396 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
350 forsberg 384 }
351    
352    
353 forsberg 383 void
354 forsberg 396 cliprdr_handle_SelectionRequest(XSelectionRequestEvent * xevent)
355 forsberg 383 {
356    
357     XSelectionEvent xev;
358 forsberg 396 unsigned long nitems, bytes_left;
359     Atom type_return;
360 forsberg 394 uint32 *wanted_formatcode;
361     int format;
362 forsberg 396
363 forsberg 383 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
364 forsberg 396 DEBUG_CLIPBOARD(("Requestor window id 0x%x ", (unsigned) xevent->requestor));
365     if (clipboard_atom == xevent->selection)
366     {
367 forsberg 383 DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
368 forsberg 396 }
369     if (primary_atom == xevent->selection)
370     {
371 forsberg 383 DEBUG_CLIPBOARD(("wants PRIMARY\n"));
372 forsberg 396 }
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 forsberg 383
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 forsberg 394 memcpy(&selection_event, &xev, sizeof(xev));
388    
389     if (ipc_atom == xevent->target)
390 forsberg 383 {
391 forsberg 394 DEBUG_CLIPBOARD(("Target atom is ipc_atom, getting INTEGER from requestor\n"));
392     XGetWindowProperty(display, xevent->requestor,
393     rdesktop_clipboard_target_atom,
394 forsberg 396 0,
395 forsberg 394 1,
396     True, XA_INTEGER,
397     &type_return,
398 forsberg 396 &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 forsberg 394 cliprdr_request_clipboard_data(*wanted_formatcode);
403     }
404    
405 forsberg 396 else if (targets_atom == xevent->target)
406 forsberg 394 {
407 forsberg 383 DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
408 forsberg 396 XChangeProperty(display,
409 forsberg 391 xevent->requestor,
410     xevent->property,
411     XA_ATOM,
412 forsberg 396 32, PropModeAppend, (unsigned char *) &targets, NUM_TARGETS);
413 forsberg 383
414 forsberg 396 XSendEvent(display, xevent->requestor, False, NoEventMask, (XEvent *) & xev);
415 forsberg 383 return;
416 forsberg 396 }
417     else if (timestamp_atom == xevent->target)
418 forsberg 383 {
419 forsberg 395 DEBUG_CLIPBOARD(("Sending TIMESTAMP\n"));
420 forsberg 396 XChangeProperty(display,
421 forsberg 391 xevent->requestor,
422     xevent->property,
423     XA_INTEGER,
424 forsberg 396 32, PropModeAppend, (unsigned char *) &last_gesturetime, 1);
425     XSendEvent(display, xevent->requestor, False, NoEventMask, (XEvent *) & xev);
426     }
427     else /* Some other target */
428 forsberg 383 {
429 forsberg 384 cliprdr_request_clipboard_data(CF_TEXT);
430     /* Return and wait for data, handled by
431     cliprdr_handle_server_data */
432     }
433     }
434 forsberg 383
435    
436 forsberg 396 static void
437     cliprdr_ack_format_list(void)
438 forsberg 384 {
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 forsberg 396 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, clipboard_channelno);
451 forsberg 383 }
452    
453    
454 forsberg 384
455    
456 forsberg 396
457 forsberg 383 static void
458 forsberg 396 cliprdr_register_server_formats(STREAM s)
459 forsberg 383 {
460     uint32 remaining_length, pad;
461     uint16 num_formats;
462     cliprdr_dataformat *this, *next;
463    
464     in_uint32_le(s, remaining_length);
465 forsberg 396 DEBUG_CLIPBOARD(("cliprdr_register_server_formats, remaining_length is %d\n",
466     remaining_length));
467 forsberg 383
468 forsberg 394
469 forsberg 383 num_formats = remaining_length / 36;
470 forsberg 394
471 forsberg 396 ipc_send_message(RDESKTOP_IPC_CLIPRDR_FORMAT_ANNOUNCE, s->p, remaining_length);
472     if (NULL != server_formats)
473     {
474 forsberg 383 this = server_formats;
475     next = this->next;
476 forsberg 396 while (NULL != next)
477     {
478 forsberg 383 xfree(this);
479     this = NULL;
480     this = next;
481     next = this->next;
482     }
483 forsberg 396 }
484 forsberg 383 this = xmalloc(sizeof(cliprdr_dataformat));
485     this->next = NULL;
486     server_formats = this;
487     num_server_formats = num_formats;
488 forsberg 396 while (1 < num_formats)
489     {
490 forsberg 383 in_uint32_le(s, this->identifier);
491     in_uint8a(s, this->textual_description, 32);
492 forsberg 396 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
493 forsberg 384 this->identifier));
494 forsberg 396 this->next = xmalloc(sizeof(cliprdr_dataformat));
495 forsberg 383 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 forsberg 396 this->next = NULL;
502 forsberg 383 in_uint32_le(s, pad);
503     cliprdr_print_server_formats();
504     }
505    
506     static void
507 forsberg 396 cliprdr_select_X_clipboards(void)
508 forsberg 383 {
509 forsberg 388 XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
510 forsberg 383 if (wnd != XGetSelectionOwner(display, primary_atom))
511     {
512     warning("Failed to aquire ownership of PRIMARY clipboard\n");
513 forsberg 396 }
514 forsberg 394 else
515     {
516     have_primary = 1;
517 forsberg 383 }
518 forsberg 388 XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
519 forsberg 396 if (wnd != XGetSelectionOwner(display, clipboard_atom))
520 forsberg 383 {
521     warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
522 forsberg 396 }
523    
524 forsberg 383 }
525    
526 forsberg 384
527 forsberg 385
528 forsberg 396 static void
529 forsberg 383 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 forsberg 396 DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
535 forsberg 383 remaining_length, pad));
536     cliprdr_send_format_announce();
537     }
538    
539 forsberg 396 void
540     cliprdr_handle_server_data(uint32 length, uint32 flags, STREAM s)
541 forsberg 384 {
542 forsberg 392 static uint32 remaining_length;
543     static char *data, *datap;
544     static uint32 bytes_left_to_read;
545 forsberg 396 DEBUG_CLIPBOARD(("In cliprdr_handle_server_data, flags is %d\n", flags));
546     if (3 == flags) /* One-op write, no packets follows */
547 forsberg 392 {
548     in_uint32_le(s, remaining_length);
549     data = s->p;
550 forsberg 396 }
551     else if (1 == flags) /* First of several packets */
552     {
553 forsberg 392 in_uint32_le(s, remaining_length);
554 forsberg 396 DEBUG_CLIPBOARD(("Remaining length is %d\n", remaining_length));
555 forsberg 392 data = xmalloc(remaining_length);
556     datap = data;
557 forsberg 396 DEBUG_CLIPBOARD(("Copying first %d bytes\n", MAX_CLIPRDR_STANDALONE_DATASIZE));
558 forsberg 392 memcpy(datap, s->p, MAX_CLIPRDR_STANDALONE_DATASIZE);
559    
560 forsberg 396 datap += MAX_CLIPRDR_STANDALONE_DATASIZE;
561     bytes_left_to_read = remaining_length - MAX_CLIPRDR_STANDALONE_DATASIZE;
562 forsberg 392 return;
563 forsberg 396 }
564     else if (0 == flags)
565 forsberg 392 {
566 forsberg 396 DEBUG_CLIPBOARD(("Copying %d middle bytes", MAX_CLIPRDR_CONTINUATION_DATASIZE));
567 forsberg 392 memcpy(datap, s->p, MAX_CLIPRDR_CONTINUATION_DATASIZE);
568    
569 forsberg 396 datap += MAX_CLIPRDR_CONTINUATION_DATASIZE;
570     bytes_left_to_read -= MAX_CLIPRDR_CONTINUATION_DATASIZE;
571 forsberg 392 return;
572 forsberg 396 }
573     else if (2 == flags)
574 forsberg 392 {
575 forsberg 396 DEBUG_CLIPBOARD(("Copying last %d bytes\n", bytes_left_to_read));
576 forsberg 392 memcpy(datap, s->p, bytes_left_to_read);
577     }
578 forsberg 395 DEBUG_CLIPBOARD(("Setting target atom (%s) on %d\n",
579     XGetAtomName(display, selection_event.property),
580     selection_event.requestor));
581 forsberg 396 XChangeProperty(display,
582 forsberg 388 selection_event.requestor,
583     selection_event.property,
584     XInternAtom(display, "STRING", False),
585 forsberg 396 8, PropModeAppend, data, remaining_length - 1);
586 forsberg 384
587 forsberg 396 XSendEvent(display,
588     selection_event.requestor, False, NoEventMask, (XEvent *) & selection_event);
589 forsberg 384
590 forsberg 393 if (2 == flags)
591 forsberg 392 xfree(data);
592    
593 forsberg 384 }
594    
595 forsberg 396 void
596     cliprdr_handle_server_data_request(STREAM s)
597 forsberg 385 {
598 forsberg 386 Window selectionowner;
599 forsberg 385 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 forsberg 396 DEBUG_CLIPBOARD(("Request from server for format %d\n", wanted_formatcode));
609 forsberg 385
610 forsberg 386 selectionowner = XGetSelectionOwner(display, primary_atom);
611 forsberg 385
612 forsberg 394 if (rdesktop_is_selection_owner)
613     {
614 forsberg 395 DEBUG_CLIPBOARD(("XChangeProperty, rdesktop_is_selection_owner\n"));
615 forsberg 394 XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
616     XA_INTEGER, 32, PropModeReplace,
617 forsberg 396 (unsigned char *) &wanted_formatcode, 1);
618 forsberg 394
619 forsberg 396 XConvertSelection(display, primary_atom,
620     ipc_atom, rdesktop_clipboard_target_atom, wnd, CurrentTime);
621 forsberg 394 return;
622     }
623    
624    
625 forsberg 396 if (None != selectionowner)
626 forsberg 386 {
627 forsberg 396
628 forsberg 386 /* FIXME: Perhaps we should check if we are the owner? */
629 forsberg 385
630 forsberg 396 XConvertSelection(display, primary_atom,
631     targets_atom, rdesktop_clipboard_target_atom, wnd, CurrentTime);
632 forsberg 386
633     /* The rest of the transfer is handled in
634     cliprdr_handle_SelectionNotify */
635    
636 forsberg 396 }
637     else
638 forsberg 385 {
639 forsberg 386
640 forsberg 402 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 forsberg 385 }
659 forsberg 386
660    
661 forsberg 385 }
662    
663 forsberg 396
664     void
665     cliprdr_callback(STREAM s, uint16 channelno)
666 forsberg 383 {
667 forsberg 389 static int failed_clipboard_acks = 0;
668     struct timeval timeval;
669 forsberg 383 uint32 length, flags;
670     uint16 ptype0, ptype1;
671 forsberg 390 clipboard_channelno = channelno;
672 forsberg 396 DEBUG_CLIPBOARD(("cliprdr_callback called with channelno %d, clipboard data:\n",
673     channelno));
674 forsberg 383 #ifdef WITH_DEBUG_CLIPBOARD
675 forsberg 396 // hexdump(s->p, s->end - s->p);
676 forsberg 383 #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 forsberg 396 if (3 == flags || 1 == flags) /* Single-write op or first-packet-of-several op */
683 forsberg 383 {
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 forsberg 396 if (1 == ptype0 && 0 == ptype1)
688     {
689 forsberg 383 cliprdr_handle_first_handshake(s);
690     return;
691 forsberg 396 }
692     else if (3 == ptype0 && 1 == ptype1)
693 forsberg 383 {
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 forsberg 389 failed_clipboard_acks = 0;
699 forsberg 383 return;
700 forsberg 384
701 forsberg 396 }
702     else if (3 == ptype0 && 2 == ptype1)
703 forsberg 389 {
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 forsberg 396
714 forsberg 389 cliprdr_send_format_announce();
715     /* Make sure we don't get stuck in this loop */
716     failed_clipboard_acks++;
717 forsberg 396 }
718 forsberg 389 else
719     {
720     warning("Reached maximum number of clipboard format announce attempts. Pasting in Windows probably won't work well now.\n");
721     }
722 forsberg 396 }
723     else if (2 == ptype0 && 0 == ptype1)
724 forsberg 383 {
725     cliprdr_register_server_formats(s);
726     cliprdr_select_X_clipboards();
727 forsberg 384 cliprdr_ack_format_list();
728 forsberg 383 return;
729 forsberg 396 }
730     else if (5 == ptype0 && 1 == ptype1)
731 forsberg 384 {
732 forsberg 392 cliprdr_handle_server_data(length, flags, s);
733 forsberg 396 }
734     else if (4 == ptype0 && 0 == ptype1)
735 forsberg 385 {
736     cliprdr_handle_server_data_request(s);
737 forsberg 383 }
738 forsberg 385
739 forsberg 396
740     }
741     else
742 forsberg 392 {
743     DEBUG_CLIPBOARD(("Handling middle or last packet\n"));
744     cliprdr_handle_server_data(length, flags, s);
745 forsberg 383 }
746     }
747    
748 forsberg 396 void
749     cliprdr_ipc_primary_lost(unsigned char *data, uint16 length)
750 forsberg 394 {
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 forsberg 384
757 forsberg 394
758 forsberg 396 void
759     cliprdr_init(void)
760 forsberg 383 {
761     primary_atom = XInternAtom(display, "PRIMARY", False);
762     clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
763 forsberg 386 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 forsberg 391 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 forsberg 396 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 forsberg 391
776 forsberg 394
777 forsberg 383 }

  ViewVC Help
Powered by ViewVC 1.1.26