/[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 388 by forsberg, Fri Jun 6 09:26:11 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    
30    // static Time selection_timestamp;
31  static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;  static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
32    static Atom rdesktop_clipboard_target_atom;
33  static cliprdr_dataformat *server_formats = NULL;  static cliprdr_dataformat *server_formats = NULL;
34  static uint16 num_server_formats = 0;  static uint16 num_server_formats = 0;
35    static XSelectionEvent selection_event;
36    
37  static void  static void
38  cliprdr_print_server_formats(void)  cliprdr_print_server_formats(void)
# Line 45  cliprdr_print_server_formats(void) Line 48  cliprdr_print_server_formats(void)
48                  i++;                  i++;
49                  this = this->next;                  this = this->next;
50          }          }
51          DEBUG_CLIPBOARD(("There was %d server formats.\n", i));          DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
52  #endif  #endif
53  }  }
54    /*
55    static void
56    cliprdr_set_selection_timestamp(void)
57    {
58            XEvent xev;
59            DEBUG_CLIPBOARD(("Changing a property in order to get a timestamp\n"));
60            fflush(stdout);
61            XChangeProperty(display, wnd, rdesktop_clipboard_target_atom,
62                            XA_ATOM, 32, PropModeAppend, 0, 0);
63            DEBUG_CLIPBOARD(("Waiting for PropertyChange on wnd\n"));
64            fflush(stdout);
65            XWindowEvent(display, wnd,
66                         PropertyChangeMask, &xev);
67            DEBUG_CLIPBOARD(("Setting selection_timestamp\n"));
68            fflush(stdout);
69            selection_timestamp = xev.xproperty.time;
70    }      
71    */      
72    
73    static void
74    cliprdr_send_format_announce(void)
75    {
76            DEBUG_CLIPBOARD(("Sending format announce\n"));
77    
78            STREAM s;
79            int number_of_formats = 1;
80            s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4);
81            out_uint32_le(s, number_of_formats*36+12);
82            out_uint32_le(s, 0x13);
83            out_uint16_le(s, 2);
84            out_uint16_le(s, 0);
85            out_uint32_le(s, number_of_formats*36);
86            
87            //      out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
88            //      rdp_out_unistr(s, "", 16);
89            //      out_uint8s(s, 32);
90    
91    
92            out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
93            out_uint8s(s, 32);
94    
95            out_uint32_le(s, 0);
96    
97            s_mark_end(s);
98            sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
99    }
100    
101    
102    static void
103    cliprdr_send_empty_datapacket(void)
104    {
105            STREAM out;
106            out =  sec_init(encryption ? SEC_ENCRYPT : 0,
107                            20);
108            out_uint32_le(out, 12);
109            out_uint32_le(out, 0x13);
110            out_uint16_le(out, 5);
111            out_uint16_le(out, 1);
112            out_uint32_le(out, 0);
113            /* Insert null string here? */
114            out_uint32_le(out, 0);
115            s_mark_end(out);
116            
117            sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!  
118    }
119    
120    
121  void  void
122  cliprdr_handle_SelectionNotify(void)  cliprdr_handle_SelectionNotify(XSelectionEvent *event)
123  {  {
124    
125            unsigned char   *data;
126            unsigned long   nitems, bytes_left;
127            int res;
128    
129            int format;
130            Atom type_return;
131            Atom best_target;
132    
133            STREAM out;
134            
135          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
136    
137            if (None == event->property) {
138                    cliprdr_send_empty_datapacket();
139                    return; /* Selection failed */
140            }
141    
142            DEBUG_CLIPBOARD(("selection: %s, target: %s, property: %s\n",
143                             XGetAtomName(display, event->selection),
144                             XGetAtomName(display, event->target),
145                             XGetAtomName(display, event->property)));
146    
147            if (targets_atom == event->target) {
148                    /* Response to TARGETS request. Let's find the target
149                       we want and request that */
150                    res = XGetWindowProperty(display, wnd,
151                                             rdesktop_clipboard_target_atom,
152                                             0L, 4096L, False, AnyPropertyType,
153                                             &type_return,
154                                             &format, &nitems, &bytes_left, &data);
155    
156                    if (Success != res)
157                    {
158                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
159                            cliprdr_send_empty_datapacket();
160                            return;
161                    }
162    
163                    if (None == type_return)
164                            /* The owner might no support TARGETS. Just try
165                               STRING */
166                            best_target = XA_STRING;
167                    else
168                    {
169                            /* FIXME: We should choose format here based
170                               on what the server wanted */
171                            best_target = XInternAtom(display, "TEXT", False);
172                            
173                            
174                    }
175    
176                    XConvertSelection(display, primary_atom,
177                                      best_target,
178                                      rdesktop_clipboard_target_atom,
179                                      wnd, event->time);
180    
181            }
182            else  /* Other clipboard data */
183            {
184                    
185                    res = XGetWindowProperty(display, wnd,
186                                             rdesktop_clipboard_target_atom,
187                                             0L, 4096L, False, AnyPropertyType,
188                                             &type_return,
189                                             &format, &nitems, &bytes_left, &data);
190    
191                    if (Success != res)
192                    {
193                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
194                            cliprdr_send_empty_datapacket();
195                            return;
196                    }
197    
198                    /* We need to handle INCR as well */
199    
200                    out =  sec_init(encryption ? SEC_ENCRYPT : 0,
201                                    20+nitems);
202                    out_uint32_le(out, 12+nitems);
203                    out_uint32_le(out, 0x13);
204                    out_uint16_le(out, 5);
205                    out_uint16_le(out, 1);
206                    out_uint32_le(out, nitems);
207                    out_uint8p(out, data, nitems);
208                    /* Insert null string here? */
209                    out_uint32_le(out, 0);
210                    s_mark_end(out);
211            
212                    sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!  
213    
214                    cliprdr_send_format_announce();
215                    
216            }
217            
218            
219  }  }
220    
221  void  void
222  cliprdr_handle_SelectionClear(void)  cliprdr_handle_SelectionClear(void)
223  {  {
224          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
225            cliprdr_send_format_announce();
226  }  }
227    
228  void print_X_error(int res)  
229    static void
230    cliprdr_request_clipboard_data(uint32 formatcode)
231  {  {
232          switch(res) {          STREAM s;
233          case Success:          s = sec_init(encryption ? SEC_ENCRYPT : 0, 24);
234                  DEBUG_CLIPBOARD(("Success\n"));          out_uint32_le(s, 16);
235                  break;          out_uint32_le(s, 0x13);
236            out_uint16_le(s, 4);
237          case BadAtom:          out_uint16_le(s, 0);
238                  DEBUG_CLIPBOARD(("BadAtom\n"));          out_uint32_le(s, 4); // Remaining length
239                  break;          out_uint32_le(s, formatcode);
240            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;  
241    
242          default:          s_mark_end(s);
243                  DEBUG_CLIPBOARD(("Unknown X error code %d\n", res));  
244          }          sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
245  }  }
246    
247    
248  void  void
249  cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)  cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
250  {  {
251    
         Atom type_return;  
252          Atom *targets;          Atom *targets;
         int format_return;  
         long nitems_return;  
         long bytes_after_return;  
         char **prop_return;  
253          int res;          int res;
254    
255          XSelectionEvent xev;          XSelectionEvent xev;
256          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));          DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
257          DEBUG_CLIPBOARD(("Requestor window id 0x%x ", xevent->requestor));          DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
258                             (unsigned)xevent->requestor));
259          if (clipboard_atom == xevent->selection) {          if (clipboard_atom == xevent->selection) {
260                  DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));                  DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
261          }          }
# Line 120  cliprdr_handle_SelectionRequest(XSelecti Line 264  cliprdr_handle_SelectionRequest(XSelecti
264          }            }  
265          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",
266                           XGetAtomName(display, xevent->target),                           XGetAtomName(display, xevent->target),
267                           xevent->target,                           (unsigned)xevent->target,
268                           XGetAtomName(display, xevent->property),                           XGetAtomName(display, xevent->property),
269                           xevent->property));                           (unsigned)xevent->property));
270    
271          xev.type = SelectionNotify;          xev.type = SelectionNotify;
272          xev.serial = 0;          xev.serial = 0;
# Line 149  cliprdr_handle_SelectionRequest(XSelecti Line 293  cliprdr_handle_SelectionRequest(XSelecti
293                                        PropModeAppend,                                        PropModeAppend,
294                                        (unsigned char *)targets,                                        (unsigned char *)targets,
295                                        3);                                        3);
                 DEBUG_CLIPBOARD(("res after XChangeProperty is "));  
                 print_X_error(res);      
296    
297                  res = XSendEvent(display,                  res = XSendEvent(display,
298                                   xevent->requestor,                                   xevent->requestor,
# Line 161  cliprdr_handle_SelectionRequest(XSelecti Line 303  cliprdr_handle_SelectionRequest(XSelecti
303          } else if (timestamp_atom == xevent->target)          } else if (timestamp_atom == xevent->target)
304          {          {
305                  DEBUG_CLIPBOARD(("TIMESTAMP requested... sending 0x%x\n",                  DEBUG_CLIPBOARD(("TIMESTAMP requested... sending 0x%x\n",
306                                   last_keyrelease));                                   (unsigned)last_gesturetime));
307                  res = XChangeProperty(display,                  res = XChangeProperty(display,
308                                        xevent->requestor,                                        xevent->requestor,
309                                        xevent->property,                                        xevent->property,
310                                        XA_INTEGER,                                        XA_INTEGER,
311                                        32,                                        32,
312                                        PropModeAppend,                                        PropModeAppend,
313                                        (unsigned char *)&last_keyrelease,                                        (unsigned char *)&last_gesturetime,
314                                        1);                                        1);
315                  res = XSendEvent(display,                  res = XSendEvent(display,
316                                   xevent->requestor,                                   xevent->requestor,
# Line 177  cliprdr_handle_SelectionRequest(XSelecti Line 319  cliprdr_handle_SelectionRequest(XSelecti
319                                   (XEvent *)&xev);                                   (XEvent *)&xev);
320          } else /* Some other target */          } else /* Some other target */
321          {          {
322                  res = XChangeProperty(display,                  cliprdr_request_clipboard_data(CF_TEXT);
323                                        xevent->requestor,                  memcpy(&selection_event, &xev, sizeof(xev));
324                                        xevent->property,                  /* Return and wait for data, handled by
325                                        XInternAtom(display, "STRING", False),                     cliprdr_handle_server_data */
326                                        8,          }
327                                        PropModeAppend,  }
                                       "krattoflabkat",  
                                       13);  
328    
                 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;  
329    
330                  res = XSendEvent(display,  static void
331                                   xevent->requestor,  cliprdr_ack_format_list(void)
332                                   False,  {
333                                   NoEventMask,          STREAM s;
334                                   (XEvent *)&xev);          s = sec_init(encryption ? SEC_ENCRYPT : 0, 20);
335                    out_uint32_le(s, 12);
336                  DEBUG_CLIPBOARD(("res after XSendEvent is "));          out_uint32_le(s, 0x13);
337                  print_X_error(res);          out_uint16_le(s, 3);
338          }          out_uint16_le(s, 1);
339            out_uint32_le(s, 0);
340            out_uint32_le(s, 0x0000c0da);
341    
342            s_mark_end(s);
343    
344            sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
345  }  }
346    
347                    
348    
349    
350    
351  static void  static void
352  cliprdr_register_server_formats(STREAM s)  cliprdr_register_server_formats(STREAM s)
# Line 238  cliprdr_register_server_formats(STREAM s Line 376  cliprdr_register_server_formats(STREAM s
376          while (1 < num_formats) {          while (1 < num_formats) {
377                  in_uint32_le(s, this->identifier);                  in_uint32_le(s, this->identifier);
378                  in_uint8a(s, this->textual_description, 32);                  in_uint8a(s, this->textual_description, 32);
379                  DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));                  DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
380                                     this->identifier));
381                  this-> next = xmalloc(sizeof(cliprdr_dataformat));                  this-> next = xmalloc(sizeof(cliprdr_dataformat));
382                  this = this->next;                  this = this->next;
383                  num_formats--;                  num_formats--;
# Line 254  cliprdr_register_server_formats(STREAM s Line 393  cliprdr_register_server_formats(STREAM s
393  static void  static void
394  cliprdr_select_X_clipboards(void)  cliprdr_select_X_clipboards(void)
395  {  {
396          XSetSelectionOwner(display, primary_atom, wnd, last_keyrelease);          XSetSelectionOwner(display, primary_atom, wnd, last_gesturetime);
397          if (wnd != XGetSelectionOwner(display, primary_atom))          if (wnd != XGetSelectionOwner(display, primary_atom))
398          {          {
399                  warning("Failed to aquire ownership of PRIMARY clipboard\n");                  warning("Failed to aquire ownership of PRIMARY clipboard\n");
400          }          }
401          XSetSelectionOwner(display, clipboard_atom, wnd, CurrentTime);          XSetSelectionOwner(display, clipboard_atom, wnd, last_gesturetime);
402          if (wnd != XGetSelectionOwner(display, clipboard_atom))          if (wnd != XGetSelectionOwner(display, clipboard_atom))
403          {          {
404                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
# Line 267  cliprdr_select_X_clipboards(void) Line 406  cliprdr_select_X_clipboards(void)
406                    
407  }  }
408    
 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);  
409                    
         out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..  
         //      rdp_out_unistr(s, "", 16);  
         out_uint8s(s, 32);  
410    
         out_uint32_le(s, 0);  
411    
         s_mark_end(s);  
         sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!  
 }  
                   
412    
413  static void  static void
414  cliprdr_handle_first_handshake(STREAM s)  cliprdr_handle_first_handshake(STREAM s)
# Line 301  cliprdr_handle_first_handshake(STREAM s) Line 421  cliprdr_handle_first_handshake(STREAM s)
421          cliprdr_send_format_announce();          cliprdr_send_format_announce();
422  }  }
423    
424    void cliprdr_handle_server_data(uint32 length, STREAM s)
425    {
426            uint32 remaining_length;
427            char *data;
428            in_uint32_le(s, remaining_length);
429            data = s->p;
430            XChangeProperty(display,
431                            selection_event.requestor,
432                            selection_event.property,
433                            XInternAtom(display, "STRING", False),
434                            8,
435                            PropModeAppend,
436                            data,
437                            remaining_length);
438    
439            XSendEvent(display,
440                       selection_event.requestor,
441                       False,
442                       NoEventMask,
443                       (XEvent *)&selection_event);
444            
445    
446    }
447    
448    void cliprdr_handle_server_data_request(STREAM s)
449    {
450            Window selectionowner;
451            uint32 remaining_length;
452            uint32 wanted_formatcode, pad;
453    
454            in_uint32_le(s, remaining_length);
455            in_uint32_le(s, wanted_formatcode);
456            in_uint32_le(s, pad);
457    
458            /* FIXME: Check that we support this formatcode */
459    
460            DEBUG_CLIPBOARD(("Request from server for format %d\n",
461                             wanted_formatcode));
462    
463            selectionowner = XGetSelectionOwner(display, primary_atom);
464    
465            if (None != selectionowner)
466            {
467            
468                    /* FIXME: Perhaps we should check if we are the owner? */
469    
470                    XConvertSelection(display, primary_atom,
471                                      targets_atom,
472                                      rdesktop_clipboard_target_atom,
473                                      wnd, CurrentTime);
474    
475                    /* The rest of the transfer is handled in
476                       cliprdr_handle_SelectionNotify */
477    
478            } else
479            {
480                    DEBUG_CLIPBOARD(("There were no owner for PRIMARY, sending empty string\n")); // FIXME: Should we always send an empty string?
481    
482                    cliprdr_send_empty_datapacket();
483            }
484    
485    
486    }
487            
488    
489  void cliprdr_callback(STREAM s)  void cliprdr_callback(STREAM s)
490  {  {
491          uint32 length, flags;          uint32 length, flags;
# Line 329  void cliprdr_callback(STREAM s) Line 514  void cliprdr_callback(STREAM s)
514                          // but probably not.                          // but probably not.
515                          DEBUG_CLIPBOARD(("Received format announce ACK\n"));                          DEBUG_CLIPBOARD(("Received format announce ACK\n"));
516                          return;                          return;
517    
518                  } else if (2 == ptype0 && 0 == ptype1)                  } else if (2 == ptype0 && 0 == ptype1)
519                  {                  {
520                          cliprdr_register_server_formats(s);                          cliprdr_register_server_formats(s);
521                          cliprdr_select_X_clipboards();                          cliprdr_select_X_clipboards();
522                            cliprdr_ack_format_list();
523                          return;                          return;
524                    } else if (5 == ptype0 && 1 == ptype1)
525                    {
526                            cliprdr_handle_server_data(length, s);
527                    } else if (4 == ptype0 && 0 == ptype1)
528                    {
529                            cliprdr_handle_server_data_request(s);
530                  }                  }
531    
532                                    
533          }          }
534  }  }
535    
536    
537  void cliprdr_init(void)  void cliprdr_init(void)
538  {  {
539          primary_atom = XInternAtom(display, "PRIMARY", False);          primary_atom = XInternAtom(display, "PRIMARY", False);
540          clipboard_atom = XInternAtom(display, "CLIPBOARD", False);          clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
541          targets_atom = XInternAtom(display, "TARGETS", True);          targets_atom = XInternAtom(display, "TARGETS", False);
542          timestamp_atom = XInternAtom(display, "TIMESTAMP", True);          timestamp_atom = XInternAtom(display, "TIMESTAMP", False);
543            rdesktop_clipboard_target_atom = XInternAtom(display, "_RDESKTOP_CLIPBOARD_TARGET", False);
544  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26