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

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

  ViewVC Help
Powered by ViewVC 1.1.26