/[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 422 - (hide annotations)
Mon Jun 16 09:03:55 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 21031 byte(s)
Try using STRING instead of TEXT if TEXT doesn't exist in the targets list.

This might solve trouble cutting in X, pasting to Windows when source OS is
(FJK-)IRIX.

There is still a need for better code when selecting format. This is a quick
hack.

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

  ViewVC Help
Powered by ViewVC 1.1.26