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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.383  
changed lines
  Added in v.402

  ViewVC Help
Powered by ViewVC 1.1.26