/[rdesktop]/sourceforge.net/trunk/rdesktop/xclip.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/xclip.c

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

revision 1037 by forsberg, Mon Jan 2 15:55:59 2006 UTC revision 1214 by ossman_, Tue Mar 28 13:56:08 2006 UTC
# Line 48  Line 48 
48  #define RDP_CF_TEXT CF_TEXT  #define RDP_CF_TEXT CF_TEXT
49  #endif  #endif
50    
51  #define MAX_TARGETS 7  #define MAX_TARGETS 8
52    
53  extern Display *g_display;  extern Display *g_display;
54  extern Window g_wnd;  extern Window g_wnd;
55  extern Time g_last_gesturetime;  extern Time g_last_gesturetime;
56    extern BOOL g_rdpclip;
57    
58    /* Mode of operation.
59       - Auto: Look at both PRIMARY and CLIPBOARD and use the most recent.
60       - Non-auto: Look at just CLIPBOARD. */
61    static BOOL auto_mode = True;
62  /* Atoms of the two X selections we're dealing with: CLIPBOARD (explicit-copy) and PRIMARY (selection-copy) */  /* Atoms of the two X selections we're dealing with: CLIPBOARD (explicit-copy) and PRIMARY (selection-copy) */
63  static Atom clipboard_atom, primary_atom;  static Atom clipboard_atom, primary_atom;
64  /* Atom of the TARGETS clipboard target */  /* Atom of the TARGETS clipboard target */
65  static Atom targets_atom;  static Atom targets_atom;
66  /* Atom of the TIMESTAMP clipboard target */  /* Atom of the TIMESTAMP clipboard target */
67  static Atom timestamp_atom;  static Atom timestamp_atom;
68  /* Atom _RDESKTOP_CLIPBOARD_TARGET which has multiple uses:  /* Atom _RDESKTOP_CLIPBOARD_TARGET which is used as the 'property' argument in
69     - The 'property' argument in XConvertSelection calls: This is the property of our     XConvertSelection calls: This is the property of our window into which
70       window into which XConvertSelection will store the received clipboard data.     XConvertSelection will store the received clipboard data. */
    - In a clipboard request of target _RDESKTOP_CLIPBOARD_FORMATS, an XA_INTEGER-typed  
      property carrying the Windows native (CF_...) format desired by the requestor.  
      Requestor set this property (e.g. requestor_wnd[_RDESKTOP_CLIPBOARD_TARGET] = CF_TEXT)  
      before requesting clipboard data from a fellow rdesktop using  
      the _RDESKTOP_CLIPBOARD_FORMATS target. */  
71  static Atom rdesktop_clipboard_target_atom;  static Atom rdesktop_clipboard_target_atom;
72  /* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses:  /* Atoms _RDESKTOP_PRIMARY_TIMESTAMP_TARGET and _RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET
73     - The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange     are used to store the timestamps for when a window got ownership of the selections.
74       of Windows native clipboard data.     We use these to determine which is more recent and should be used. */
75       This target cannot be used standalone; the requestor must keep the  static Atom rdesktop_primary_timestamp_target_atom, rdesktop_clipboard_timestamp_target_atom;
76       _RDESKTOP_CLIPBOARD_TARGET property on his window denoting  /* Storage for timestamps since we get them in two separate notifications. */
77       the Windows native clipboard format being requested.  static Time primary_timestamp, clipboard_timestamp;
78     - The root window property set by rdesktop when it owns the clipboard,  /* Clipboard target for getting a list of native Windows clipboard formats. The
79       denoting all Windows native clipboard formats it offers via     presence of this target indicates that the selection owner is another rdesktop. */
      requests of the _RDESKTOP_CLIPBOARD_FORMATS target. */  
80  static Atom rdesktop_clipboard_formats_atom;  static Atom rdesktop_clipboard_formats_atom;
81    /* The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop
82       interchange of Windows native clipboard data. The requestor must supply the
83       desired native Windows clipboard format in the associated property. */
84    static Atom rdesktop_native_atom;
85    /* Local copy of the list of native Windows clipboard formats. */
86    static uint8 *formats_data = NULL;
87    static uint32 formats_data_length = 0;
88    /* We need to know when another rdesktop process gets or loses ownership of a
89       selection. Without XFixes we do this by touching a property on the root window
90       which will generate PropertyNotify notifications. */
91    static Atom rdesktop_selection_notify_atom;
92    /* State variables that indicate if we're currently probing the targets of the
93       selection owner. reprobe_selections indicate that the ownership changed in
94       the middle of the current probe so it should be restarted. */
95    static BOOL probing_selections, reprobe_selections;
96    /* Atoms _RDESKTOP_PRIMARY_OWNER and _RDESKTOP_CLIPBOARD_OWNER. Used as properties
97       on the root window to indicate which selections that are owned by rdesktop. */
98    static Atom rdesktop_primary_owner_atom, rdesktop_clipboard_owner_atom;
99  static Atom format_string_atom, format_utf8_string_atom, format_unicode_atom;  static Atom format_string_atom, format_utf8_string_atom, format_unicode_atom;
100  /* Atom of the INCR clipboard type (see ICCCM on "INCR Properties") */  /* Atom of the INCR clipboard type (see ICCCM on "INCR Properties") */
101  static Atom incr_atom;  static Atom incr_atom;
# Line 98  static int rdp_clipboard_request_format; Line 115  static int rdp_clipboard_request_format;
115  /* Array of offered clipboard targets that will be sent to fellow X clients upon a TARGETS request. */  /* Array of offered clipboard targets that will be sent to fellow X clients upon a TARGETS request. */
116  static Atom targets[MAX_TARGETS];  static Atom targets[MAX_TARGETS];
117  static int num_targets;  static int num_targets;
 /* Denotes that this client currently holds the PRIMARY selection. */  
 static int have_primary = 0;  
118  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,
119     allowing us to interchange Windows native clipboard data directly. */     allowing us to interchange Windows native clipboard data directly. */
120  static int rdesktop_is_selection_owner = 0;  static BOOL rdesktop_is_selection_owner = False;
121    /* Time when we acquired the selection. */
122    static Time acquire_time = 0;
123    
124  /* Denotes that an INCR ("chunked") transfer is in progress. */  /* Denotes that an INCR ("chunked") transfer is in progress. */
125  static int g_waiting_for_INCR = 0;  static int g_waiting_for_INCR = 0;
# Line 146  utf16_lf2crlf(uint8 * data, uint32 * siz Line 163  utf16_lf2crlf(uint8 * data, uint32 * siz
163          if (result == NULL)          if (result == NULL)
164                  return NULL;                  return NULL;
165    
166          inptr = (uint16*)data;          inptr = (uint16 *) data;
167          outptr = (uint16*)result;          outptr = (uint16 *) result;
168    
169          /* Check for a reversed BOM */          /* Check for a reversed BOM */
170          Bool swap_endianess = (*inptr == 0xfffe);          Bool swap_endianess = (*inptr == 0xfffe);
171    
172          while ((uint8*)inptr < data + *size)          while ((uint8 *) inptr < data + *size)
173          {          {
174                  uint16 uvalue = *inptr;                  uint16 uvalue = *inptr;
175                  if (swap_endianess)                  if (swap_endianess)
# Line 161  utf16_lf2crlf(uint8 * data, uint32 * siz Line 178  utf16_lf2crlf(uint8 * data, uint32 * siz
178                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;                          *outptr++ = swap_endianess ? 0x0d00 : 0x0d;
179                  *outptr++ = *inptr++;                  *outptr++ = *inptr++;
180          }          }
181          *outptr++ = 0; /* null termination */          *outptr++ = 0;          /* null termination */
182          *size = (uint8*)outptr - result;          *size = (uint8 *) outptr - result;
183    
184          return result;          return result;
185  }  }
# Line 201  xclip_provide_selection(XSelectionReques Line 218  xclip_provide_selection(XSelectionReques
218  {  {
219          XEvent xev;          XEvent xev;
220    
221            DEBUG_CLIPBOARD(("xclip_provide_selection: requestor=0x%08x, target=%s, property=%s, length=%u\n", (unsigned) req->requestor, XGetAtomName(g_display, req->target), XGetAtomName(g_display, req->property), (unsigned) length));
222    
223          XChangeProperty(g_display, req->requestor, req->property,          XChangeProperty(g_display, req->requestor, req->property,
224                          type, format, PropModeReplace, data, length);                          type, format, PropModeReplace, data, length);
225    
# Line 223  xclip_refuse_selection(XSelectionRequest Line 242  xclip_refuse_selection(XSelectionRequest
242  {  {
243          XEvent xev;          XEvent xev;
244    
245            DEBUG_CLIPBOARD(("xclip_refuse_selection: requestor=0x%08x, target=%s, property=%s\n",
246                             (unsigned) req->requestor, XGetAtomName(g_display, req->target),
247                             XGetAtomName(g_display, req->property)));
248    
249          xev.xselection.type = SelectionNotify;          xev.xselection.type = SelectionNotify;
250          xev.xselection.serial = 0;          xev.xselection.serial = 0;
251          xev.xselection.send_event = True;          xev.xselection.send_event = True;
# Line 260  helper_cliprdr_send_empty_response() Line 283  helper_cliprdr_send_empty_response()
283     to the expected RDP format as necessary. Returns true if data was sent.     to the expected RDP format as necessary. Returns true if data was sent.
284   */   */
285  static Bool  static Bool
286  xclip_send_data_with_convert(uint8* source, size_t source_size, Atom target)  xclip_send_data_with_convert(uint8 * source, size_t source_size, Atom target)
287  {  {
288          #ifdef USE_UNICODE_CLIPBOARD          DEBUG_CLIPBOARD(("xclip_send_data_with_convert: target=%s, size=%u\n",
289                             XGetAtomName(g_display, target), (unsigned) source_size));
290    
291    #ifdef USE_UNICODE_CLIPBOARD
292          if (target == format_string_atom ||          if (target == format_string_atom ||
293              target == format_unicode_atom ||              target == format_unicode_atom || target == format_utf8_string_atom)
             target == format_utf8_string_atom)  
294          {          {
295                  if (rdp_clipboard_request_format != RDP_CF_TEXT)                  if (rdp_clipboard_request_format != RDP_CF_TEXT)
296                          return False;                          return False;
# Line 276  xclip_send_data_with_convert(uint8* sour Line 301  xclip_send_data_with_convert(uint8* sour
301                     WinNT versions are Unicode-minded).                     WinNT versions are Unicode-minded).
302                   */                   */
303                  size_t unicode_buffer_size;                  size_t unicode_buffer_size;
304                  char* unicode_buffer;                  char *unicode_buffer;
305                  iconv_t cd;                  iconv_t cd;
306    
307                  if (target == format_string_atom)                  if (target == format_string_atom)
308                  {                  {
309                          char* locale_charset = nl_langinfo(CODESET);                          char *locale_charset = nl_langinfo(CODESET);
310                          cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);                          cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);
311                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
312                          {                          {
313                                  DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));                                  DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));
314                                  return False;                                  return False;
# Line 293  xclip_send_data_with_convert(uint8* sour Line 318  xclip_send_data_with_convert(uint8* sour
318                  else if (target == format_unicode_atom)                  else if (target == format_unicode_atom)
319                  {                  {
320                          cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");                          cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");
321                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
322                          {                          {
323                                  return False;                                  return False;
324                          }                          }
# Line 302  xclip_send_data_with_convert(uint8* sour Line 327  xclip_send_data_with_convert(uint8* sour
327                  else if (target == format_utf8_string_atom)                  else if (target == format_utf8_string_atom)
328                  {                  {
329                          cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");                          cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");
330                          if (cd == (iconv_t)-1)                          if (cd == (iconv_t) - 1)
331                          {                          {
332                                  return False;                                  return False;
333                          }                          }
# Line 318  xclip_send_data_with_convert(uint8* sour Line 343  xclip_send_data_with_convert(uint8* sour
343    
344                  unicode_buffer = xmalloc(unicode_buffer_size);                  unicode_buffer = xmalloc(unicode_buffer_size);
345                  size_t unicode_buffer_size_remaining = unicode_buffer_size;                  size_t unicode_buffer_size_remaining = unicode_buffer_size;
346                  char* unicode_buffer_remaining = unicode_buffer;                  char *unicode_buffer_remaining = unicode_buffer;
347                  char* data_remaining = (char*)source;                  char *data_remaining = (char *) source;
348                  size_t data_size_remaining = source_size;                  size_t data_size_remaining = source_size;
349                  iconv(cd, &data_remaining, &data_size_remaining, &unicode_buffer_remaining, &unicode_buffer_size_remaining);                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
350                          &unicode_buffer_remaining, &unicode_buffer_size_remaining);
351                  iconv_close(cd);                  iconv_close(cd);
352    
353                  /* translate linebreaks */                  /* translate linebreaks */
354                  uint32 translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;                  uint32 translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;
355                  uint8* translated_data = utf16_lf2crlf((uint8*)unicode_buffer, &translated_data_size);                  uint8 *translated_data =
356                            utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);
357                  if (translated_data != NULL)                  if (translated_data != NULL)
358                  {                  {
359                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n", translated_data_size));                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
360                          cliprdr_send_data(translated_data, translated_data_size);                                           translated_data_size));
361                            helper_cliprdr_send_response(translated_data, translated_data_size);
362                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
363                  }                  }
364    
# Line 338  xclip_send_data_with_convert(uint8* sour Line 366  xclip_send_data_with_convert(uint8* sour
366    
367                  return True;                  return True;
368          }          }
369          #else  #else
370          if (target == format_string_atom)          if (target == format_string_atom)
371          {          {
372                  uint8 *translated_data;                  uint8 *translated_data;
# Line 351  xclip_send_data_with_convert(uint8* sour Line 379  xclip_send_data_with_convert(uint8* sour
379                  translated_data = lf2crlf(source, &length);                  translated_data = lf2crlf(source, &length);
380                  if (translated_data != NULL)                  if (translated_data != NULL)
381                  {                  {
382                          cliprdr_send_data(translated_data, length);                          helper_cliprdr_send_response(translated_data, length);
383                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
384                  }                  }
385    
386                  return True;                  return True;
387          }          }
388          #endif  #endif
389          else if (target == rdesktop_clipboard_formats_atom)          else if (target == rdesktop_native_atom)
390          {          {
391                  helper_cliprdr_send_response(source, source_size + 1);                  helper_cliprdr_send_response(source, source_size + 1);
392    
# Line 370  xclip_send_data_with_convert(uint8* sour Line 398  xclip_send_data_with_convert(uint8* sour
398          }          }
399  }  }
400    
401    static void
402    xclip_clear_target_props()
403    {
404            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
405            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
406            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
407    }
408    
409    static void
410    xclip_notify_change()
411    {
412            XChangeProperty(g_display, DefaultRootWindow(g_display),
413                            rdesktop_selection_notify_atom, XA_INTEGER, 32, PropModeReplace, NULL, 0);
414    }
415    
416    static void
417    xclip_probe_selections()
418    {
419            Window primary_owner, clipboard_owner;
420    
421            if (probing_selections)
422            {
423                    DEBUG_CLIPBOARD(("Already probing selections. Scheduling reprobe.\n"));
424                    reprobe_selections = True;
425                    return;
426            }
427    
428            DEBUG_CLIPBOARD(("Probing selections.\n"));
429    
430            probing_selections = True;
431            reprobe_selections = False;
432    
433            xclip_clear_target_props();
434    
435            if (auto_mode)
436                    primary_owner = XGetSelectionOwner(g_display, primary_atom);
437            else
438                    primary_owner = None;
439    
440            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
441    
442            /* If we own all relevant selections then don't do anything. */
443            if (((primary_owner == g_wnd) || !auto_mode) && (clipboard_owner == g_wnd))
444                    goto end;
445    
446            /* Both available */
447            if ((primary_owner != None) && (clipboard_owner != None))
448            {
449                    primary_timestamp = 0;
450                    clipboard_timestamp = 0;
451                    XConvertSelection(g_display, primary_atom, timestamp_atom,
452                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
453                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
454                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
455                    return;
456            }
457    
458            /* Just PRIMARY */
459            if (primary_owner != None)
460            {
461                    XConvertSelection(g_display, primary_atom, targets_atom,
462                                      rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
463                    return;
464            }
465    
466            /* Just CLIPBOARD */
467            if (clipboard_owner != None)
468            {
469                    XConvertSelection(g_display, clipboard_atom, targets_atom,
470                                      rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
471                    return;
472            }
473    
474            DEBUG_CLIPBOARD(("No owner of any selection.\n"));
475    
476            /* FIXME:
477               Without XFIXES, we cannot reliably know the formats offered by an
478               upcoming selection owner, so we just lie about him offering
479               RDP_CF_TEXT. */
480            cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
481    
482          end:
483            probing_selections = False;
484    }
485    
486  /* This function is called for SelectionNotify events.  /* This function is called for SelectionNotify events.
487     The SelectionNotify event is sent from the clipboard owner to the requestor     The SelectionNotify event is sent from the clipboard owner to the requestor
488     after his request was satisfied.     after his request was satisfied.
# Line 383  xclip_handle_SelectionNotify(XSelectionE Line 496  xclip_handle_SelectionNotify(XSelectionE
496          Atom type;          Atom type;
497          Atom *supported_targets;          Atom *supported_targets;
498          int res, i, format;          int res, i, format;
499          uint8 *data;          uint8 *data = NULL;
500    
501          if (event->property == None)          if (event->property == None)
502                  goto fail;                  goto fail;
# Line 393  xclip_handle_SelectionNotify(XSelectionE Line 506  xclip_handle_SelectionNotify(XSelectionE
506                           XGetAtomName(g_display, event->target),                           XGetAtomName(g_display, event->target),
507                           XGetAtomName(g_display, event->property)));                           XGetAtomName(g_display, event->property)));
508    
509          if (event->property == None)          if (event->target == timestamp_atom)
510                  goto fail;          {
511                    if (event->selection == primary_atom)
512                    {
513                            res = XGetWindowProperty(g_display, g_wnd,
514                                                     rdesktop_primary_timestamp_target_atom, 0,
515                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
516                                                     &type, &format, &nitems, &bytes_left, &data);
517                    }
518                    else
519                    {
520                            res = XGetWindowProperty(g_display, g_wnd,
521                                                     rdesktop_clipboard_timestamp_target_atom, 0,
522                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
523                                                     &type, &format, &nitems, &bytes_left, &data);
524                    }
525    
526    
527                    if ((res != Success) || (nitems != 1))
528                    {
529                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
530                            goto fail;
531                    }
532    
533                    if (event->selection == primary_atom)
534                    {
535                            primary_timestamp = *(Time *) data;
536                            if (primary_timestamp == 0)
537                                    primary_timestamp++;
538                            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
539                            DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
540                                             (unsigned) primary_timestamp));
541                    }
542                    else
543                    {
544                            clipboard_timestamp = *(Time *) data;
545                            if (clipboard_timestamp == 0)
546                                    clipboard_timestamp++;
547                            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
548                            DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
549                                             (unsigned) clipboard_timestamp));
550                    }
551    
552                    XFree(data);
553    
554                    if (primary_timestamp && clipboard_timestamp)
555                    {
556                            if (primary_timestamp > clipboard_timestamp)
557                            {
558                                    DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
559                                    XConvertSelection(g_display, primary_atom, targets_atom,
560                                                      rdesktop_clipboard_target_atom, g_wnd,
561                                                      event->time);
562                            }
563                            else
564                            {
565                                    DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
566                                    XConvertSelection(g_display, clipboard_atom, targets_atom,
567                                                      rdesktop_clipboard_target_atom, g_wnd,
568                                                      event->time);
569                            }
570                    }
571    
572                    return;
573            }
574    
575            if (probing_selections && reprobe_selections)
576            {
577                    probing_selections = False;
578                    xclip_probe_selections();
579                    return;
580            }
581    
582          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
583                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,
584                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
585    
586            xclip_clear_target_props();
587    
588          if (res != Success)          if (res != Success)
589          {          {
590                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
# Line 415  xclip_handle_SelectionNotify(XSelectionE Line 600  xclip_handle_SelectionNotify(XSelectionE
600                  {                  {
601                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
602                  }                  }
                 XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
603                  XFree(data);                  XFree(data);
604                  g_incr_target = event->target;                  g_incr_target = event->target;
605                  g_waiting_for_INCR = 1;                  g_waiting_for_INCR = 1;
606                  return;                  goto end;
607          }          }
608    
         XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
   
609          /* Negotiate target format */          /* Negotiate target format */
610          if (event->target == targets_atom)          if (event->target == targets_atom)
611          {          {
# Line 432  xclip_handle_SelectionNotify(XSelectionE Line 614  xclip_handle_SelectionNotify(XSelectionE
614                     (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)                     (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)
615                   */                   */
616                  int text_target_satisfaction = 0;                  int text_target_satisfaction = 0;
617                  Atom best_text_target = 0; /* measures how much we're satisfied with what we found */                  Atom best_text_target = 0;      /* measures how much we're satisfied with what we found */
618                  if (type != None)                  if (type != None)
619                  {                  {
620                          supported_targets = (Atom *) data;                          supported_targets = (Atom *) data;
# Line 449  xclip_handle_SelectionNotify(XSelectionE Line 631  xclip_handle_SelectionNotify(XSelectionE
631                                                  text_target_satisfaction = 1;                                                  text_target_satisfaction = 1;
632                                          }                                          }
633                                  }                                  }
634                                  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
635                                  else if (supported_targets[i] == format_unicode_atom)                                  else if (supported_targets[i] == format_unicode_atom)
636                                  {                                  {
637                                          if (text_target_satisfaction < 2)                                          if (text_target_satisfaction < 2)
# Line 468  xclip_handle_SelectionNotify(XSelectionE Line 650  xclip_handle_SelectionNotify(XSelectionE
650                                                  text_target_satisfaction = 3;                                                  text_target_satisfaction = 3;
651                                          }                                          }
652                                  }                                  }
653                                  #endif  #endif
654                                    else if (supported_targets[i] == rdesktop_clipboard_formats_atom)
655                                    {
656                                            if (probing_selections && (text_target_satisfaction < 4))
657                                            {
658                                                    DEBUG_CLIPBOARD(("Other party supports native formats, choosing that as best_target\n"));
659                                                    best_text_target = supported_targets[i];
660                                                    text_target_satisfaction = 4;
661                                            }
662                                    }
663                          }                          }
664                  }                  }
665    
666                  /* Kickstarting the next step in the process of satisfying RDP's                  /* Kickstarting the next step in the process of satisfying RDP's
667                     clipboard request -- specifically, requesting the actual clipboard data.                     clipboard request -- specifically, requesting the actual clipboard data.
668                   */                   */
669                  if (best_text_target != 0)                  if ((best_text_target != 0)
670                        && (!probing_selections
671                            || (best_text_target == rdesktop_clipboard_formats_atom)))
672                  {                  {
673                          XConvertSelection(g_display, clipboard_atom, best_text_target, rdesktop_clipboard_target_atom, g_wnd, event->time);                          XConvertSelection(g_display, event->selection, best_text_target,
674                          return;                                            rdesktop_clipboard_target_atom, g_wnd, event->time);
675                            goto end;
676                  }                  }
677                  else                  else
678                  {                  {
# Line 488  xclip_handle_SelectionNotify(XSelectionE Line 682  xclip_handle_SelectionNotify(XSelectionE
682          }          }
683          else          else
684          {          {
685                  if (!xclip_send_data_with_convert(data, nitems, event->target))                  if (probing_selections)
686                    {
687                            Window primary_owner, clipboard_owner;
688    
689                            /* FIXME:
690                               Without XFIXES, we must make sure that the other
691                               rdesktop owns all relevant selections or we might try
692                               to get a native format from non-rdesktop window later
693                               on. */
694    
695                            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
696    
697                            if (auto_mode)
698                                    primary_owner = XGetSelectionOwner(g_display, primary_atom);
699                            else
700                                    primary_owner = clipboard_owner;
701    
702                            if (primary_owner != clipboard_owner)
703                                    goto fail;
704    
705                            DEBUG_CLIPBOARD(("Got fellow rdesktop formats\n"));
706                            probing_selections = False;
707                            rdesktop_is_selection_owner = True;
708                            cliprdr_send_native_format_announce(data, nitems);
709                    }
710                    else if (!xclip_send_data_with_convert(data, nitems, event->target))
711                  {                  {
712                          goto fail;                          goto fail;
713                  }                  }
714          }          }
715    
716          XFree(data);        end:
717            if (data)
718                    XFree(data);
719    
720          return;          return;
721    
722        fail:        fail:
723          XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);          xclip_clear_target_props();
724          XFree(data);          if (probing_selections)
725          helper_cliprdr_send_empty_response();          {
726                    DEBUG_CLIPBOARD(("Unable to find suitable target. Using default text format.\n"));
727                    probing_selections = False;
728                    rdesktop_is_selection_owner = False;
729    
730                    /* FIXME:
731                       Without XFIXES, we cannot reliably know the formats offered by an
732                       upcoming selection owner, so we just lie about him offering
733                       RDP_CF_TEXT. */
734                    cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
735            }
736            else
737            {
738                    helper_cliprdr_send_empty_response();
739            }
740            goto end;
741  }  }
742    
743  /* This function is called for SelectionRequest events.  /* This function is called for SelectionRequest events.
# Line 513  xclip_handle_SelectionRequest(XSelection Line 749  xclip_handle_SelectionRequest(XSelection
749  {  {
750          unsigned long nitems, bytes_left;          unsigned long nitems, bytes_left;
751          unsigned char *prop_return;          unsigned char *prop_return;
         uint32 *wanted_format;  
752          int format, res;          int format, res;
753          Atom type;          Atom type;
754    
# Line 529  xclip_handle_SelectionRequest(XSelection Line 764  xclip_handle_SelectionRequest(XSelection
764          }          }
765          else if (event->target == timestamp_atom)          else if (event->target == timestamp_atom)
766          {          {
767                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & acquire_time, 1);
768                  return;                  return;
769          }          }
770            else if (event->target == rdesktop_clipboard_formats_atom)
771            {
772                    xclip_provide_selection(event, XA_STRING, 8, formats_data, formats_data_length);
773            }
774          else          else
775          {          {
776                  /* All the following targets require an async operation with the RDP server                  /* All the following targets require an async operation with the RDP server
# Line 543  xclip_handle_SelectionRequest(XSelection Line 782  xclip_handle_SelectionRequest(XSelection
782                          xclip_refuse_selection(event);                          xclip_refuse_selection(event);
783                          return;                          return;
784                  }                  }
785                  if (event->target == rdesktop_clipboard_formats_atom)                  if (event->target == rdesktop_native_atom)
786                  {                  {
787                          /* Before the requestor makes a request for the _RDESKTOP_CLIPBOARD_FORMATS target,                          /* Before the requestor makes a request for the _RDESKTOP_NATIVE target,
788                             he should declare requestor[_RDESKTOP_CLIPBOARD_TARGET] = CF_SOMETHING.                             he should declare requestor[property] = CF_SOMETHING. */
                            Otherwise, we default to RDP_CF_TEXT.  
                          */  
789                          res = XGetWindowProperty(g_display, event->requestor,                          res = XGetWindowProperty(g_display, event->requestor,
790                                                   rdesktop_clipboard_target_atom, 0, 1, True, XA_INTEGER,                                                   event->property, 0, 1, True,
791                                                   &type, &format, &nitems, &bytes_left, &prop_return);                                                   XA_INTEGER, &type, &format, &nitems, &bytes_left,
792                          wanted_format = (uint32 *) prop_return;                                                   &prop_return);
793                          format = (res == Success) ? *wanted_format : RDP_CF_TEXT;                          if (res != Success)
794                            {
795                                    DEBUG_CLIPBOARD(("Requested native format but didn't specifiy which.\n"));
796                                    xclip_refuse_selection(event);
797                                    return;
798                            }
799    
800                            format = *(uint32 *) prop_return;
801                          XFree(prop_return);                          XFree(prop_return);
802                  }                  }
803                  else if (event->target == format_string_atom ||                  else if (event->target == format_string_atom || event->target == XA_STRING)
                          event->target == XA_STRING)  
804                  {                  {
805                          /* STRING and XA_STRING are defined to be ISO8859-1 */                          /* STRING and XA_STRING are defined to be ISO8859-1 */
806                          format = CF_TEXT;                          format = CF_TEXT;
807                  }                  }
808                  else if (event->target == format_utf8_string_atom)                  else if (event->target == format_utf8_string_atom)
809                  {                  {
810                          #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
811                          format = CF_UNICODETEXT;                          format = CF_UNICODETEXT;
812                          #else  #else
813                          DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));                          DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));
814                          xclip_refuse_selection(event);                          xclip_refuse_selection(event);
815                          return;                          return;
816                          #endif  #endif
817                  }                  }
818                  else if (event->target == format_unicode_atom)                  else if (event->target == format_unicode_atom)
819                  {                  {
# Line 587  xclip_handle_SelectionRequest(XSelection Line 830  xclip_handle_SelectionRequest(XSelection
830                  cliprdr_send_data_request(format);                  cliprdr_send_data_request(format);
831                  selection_request = *event;                  selection_request = *event;
832                  has_selection_request = True;                  has_selection_request = True;
833                  return; /* wait for data */                  return;         /* wait for data */
834          }          }
835  }  }
836    
# Line 602  void Line 845  void
845  xclip_handle_SelectionClear(void)  xclip_handle_SelectionClear(void)
846  {  {
847          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));          DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
848          have_primary = 0;          xclip_notify_change();
849          XDeleteProperty(g_display, DefaultRootWindow(g_display), rdesktop_clipboard_formats_atom);          xclip_probe_selections();
         /* FIXME:  
            Without XFIXES, we cannot reliably know the formats offered by the  
            new owner of the X11 clipboard, so we just lie about him  
            offering RDP_CF_TEXT. */  
         cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);  
850  }  }
851    
852  /* Called when any property changes in our window or the root window. */  /* Called when any property changes in our window or the root window. */
# Line 618  xclip_handle_PropertyNotify(XPropertyEve Line 856  xclip_handle_PropertyNotify(XPropertyEve
856          unsigned long nitems;          unsigned long nitems;
857          unsigned long offset = 0;          unsigned long offset = 0;
858          unsigned long bytes_left = 1;          unsigned long bytes_left = 1;
859          int format, res;          int format;
860          XWindowAttributes wa;          XWindowAttributes wa;
861          uint8 *data;          uint8 *data;
862          Atom type;          Atom type;
# Line 651  xclip_handle_PropertyNotify(XPropertyEve Line 889  xclip_handle_PropertyNotify(XPropertyEve
889    
890                                  if (g_clip_buflen > 0)                                  if (g_clip_buflen > 0)
891                                  {                                  {
892                                          if (!xclip_send_data_with_convert(g_clip_buffer, g_clip_buflen, g_incr_target))                                          if (!xclip_send_data_with_convert
893                                                (g_clip_buffer, g_clip_buflen, g_incr_target))
894                                          {                                          {
895                                                  helper_cliprdr_send_empty_response();                                                  helper_cliprdr_send_empty_response();
896                                          }                                          }
# Line 663  xclip_handle_PropertyNotify(XPropertyEve Line 902  xclip_handle_PropertyNotify(XPropertyEve
902                          else                          else
903                          {                          {
904                                  /* Another chunk in the INCR transfer */                                  /* Another chunk in the INCR transfer */
905                                  offset += (nitems / 4); /* offset at which to begin the next slurp */                                  offset += (nitems / 4); /* offset at which to begin the next slurp */
906                                  g_clip_buffer = xrealloc(g_clip_buffer, g_clip_buflen + nitems);                                  g_clip_buffer = xrealloc(g_clip_buffer, g_clip_buflen + nitems);
907                                  memcpy(g_clip_buffer + g_clip_buflen, data, nitems);                                  memcpy(g_clip_buffer + g_clip_buflen, data, nitems);
908                                  g_clip_buflen += nitems;                                  g_clip_buflen += nitems;
# Line 675  xclip_handle_PropertyNotify(XPropertyEve Line 914  xclip_handle_PropertyNotify(XPropertyEve
914                  return;                  return;
915          }          }
916    
917          if ((event->atom == rdesktop_clipboard_formats_atom) &&          if ((event->atom == rdesktop_selection_notify_atom) &&
918              (event->window == DefaultRootWindow(g_display)) &&              (event->window == DefaultRootWindow(g_display)))
919              !have_primary /* not interested in our own events */)                  xclip_probe_selections();
         {  
                 if (event->state == PropertyNewValue)  
                 {  
                         DEBUG_CLIPBOARD(("xclip_handle_PropertyNotify: getting fellow rdesktop formats\n"));  
   
                         res = XGetWindowProperty(g_display, DefaultRootWindow(g_display),  
                                                  rdesktop_clipboard_formats_atom, 0,  
                                                  XMaxRequestSize(g_display), False, XA_STRING, &type,  
                                                  &format, &nitems, &bytes_left, &data);  
   
                         if ((res == Success) && (nitems > 0))  
                         {  
                                 cliprdr_send_native_format_announce(data, nitems);  
                                 rdesktop_is_selection_owner = 1;  
                                 return;  
                         }  
                 }  
   
                 /* For some reason, we couldn't announce the native formats */  
                 cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);  
                 rdesktop_is_selection_owner = 0;  
         }  
920  }  }
921  #endif  #endif
922    
# Line 712  xclip_handle_PropertyNotify(XPropertyEve Line 929  xclip_handle_PropertyNotify(XPropertyEve
929  void  void
930  ui_clip_format_announce(uint8 * data, uint32 length)  ui_clip_format_announce(uint8 * data, uint32 length)
931  {  {
932          XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);          acquire_time = g_last_gesturetime;
933    
934            XSetSelectionOwner(g_display, primary_atom, g_wnd, acquire_time);
935          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
         {  
936                  warning("Failed to aquire ownership of PRIMARY clipboard\n");                  warning("Failed to aquire ownership of PRIMARY clipboard\n");
                 return;  
         }  
937    
938          have_primary = 1;          XSetSelectionOwner(g_display, clipboard_atom, g_wnd, acquire_time);
         XChangeProperty(g_display, DefaultRootWindow(g_display),  
                         rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,  
                         length);  
   
         XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);  
939          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
940                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
941    
942            if (formats_data)
943                    xfree(formats_data);
944            formats_data = xmalloc(length);
945            memcpy(formats_data, data, length);
946            formats_data_length = length;
947    
948            xclip_notify_change();
949  }  }
950    
951  /* Called when the RDP server responds with clipboard data (after we've requested it). */  /* Called when the RDP server responds with clipboard data (after we've requested it). */
# Line 735  ui_clip_handle_data(uint8 * data, uint32 Line 954  ui_clip_handle_data(uint8 * data, uint32
954  {  {
955          BOOL free_data = False;          BOOL free_data = False;
956    
957          if (selection_request.target == format_string_atom ||          if (length == 0)
958              selection_request.target == XA_STRING)          {
959          {                  xclip_refuse_selection(&selection_request);
960                    has_selection_request = False;
961                    return;
962            }
963    
964            if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)
965            {
966                  /* We're expecting a CF_TEXT response */                  /* We're expecting a CF_TEXT response */
967                  uint8 *firstnull;                  uint8 *firstnull;
968    
969                  /* translate linebreaks */                  /* translate linebreaks */
970                  crlf2lf(data, &length);                  crlf2lf(data, &length);
971    
972                  /* Only send data up to null byte, if any */                  /* Only send data up to null byte, if any */
973                  firstnull = (uint8 *) strchr((char *) data, '\0');                  firstnull = (uint8 *) strchr((char *) data, '\0');
974                  if (firstnull)                  if (firstnull)
975                  {                  {
976                          length = firstnull - data + 1;                          length = firstnull - data + 1;
977                  }                  }
978          }          }
979  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
980          else if (selection_request.target == format_utf8_string_atom)          else if (selection_request.target == format_utf8_string_atom)
981          {          {
982                  /* We're expecting a CF_UNICODETEXT response */                  /* We're expecting a CF_UNICODETEXT response */
983                  iconv_t cd = iconv_open("UTF-8", WINDOWS_CODEPAGE);                  iconv_t cd = iconv_open("UTF-8", WINDOWS_CODEPAGE);
984                  if (cd != (iconv_t)-1)                  if (cd != (iconv_t) - 1)
985                  {                  {
986                          size_t utf8_length = length * 2;                          size_t utf8_length = length * 2;
987                          char* utf8_data = malloc(utf8_length);                          char *utf8_data = malloc(utf8_length);
988                          size_t utf8_length_remaining = utf8_length;                          size_t utf8_length_remaining = utf8_length;
989                          char* utf8_data_remaining = utf8_data;                          char *utf8_data_remaining = utf8_data;
990                          char* data_remaining = (char*)data;                          char *data_remaining = (char *) data;
991                          size_t length_remaining = (size_t)length;                          size_t length_remaining = (size_t) length;
992                          if (utf8_data == NULL)                          if (utf8_data == NULL)
993                          {                          {
994                                  iconv_close(cd);                                  iconv_close(cd);
995                                  return;                                  return;
996                          }                          }
997                          iconv(cd, &data_remaining, &length_remaining, &utf8_data_remaining, &utf8_length_remaining);                          iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
998                                  &utf8_data_remaining, &utf8_length_remaining);
999                          iconv_close(cd);                          iconv_close(cd);
1000                          free_data = True;                          free_data = True;
1001                          data = (uint8*)utf8_data;                          data = (uint8 *) utf8_data;
1002                          length = utf8_length - utf8_length_remaining;                          length = utf8_length - utf8_length_remaining;
1003                  }                  }
1004          }          }
# Line 783  ui_clip_handle_data(uint8 * data, uint32 Line 1009  ui_clip_handle_data(uint8 * data, uint32
1009                     for further conversions. */                     for further conversions. */
1010          }          }
1011  #endif  #endif
1012          else if (selection_request.target == rdesktop_clipboard_formats_atom)          else if (selection_request.target == rdesktop_native_atom)
1013          {          {
1014                  /* Pass as-is */                  /* Pass as-is */
1015          }          }
1016          else          else
1017          {          {
1018                    DEBUG_CLIPBOARD(("ui_clip_handle_data: BUG! I don't know how to convert selection target %s!\n", XGetAtomName(g_display, selection_request.target)));
1019                  xclip_refuse_selection(&selection_request);                  xclip_refuse_selection(&selection_request);
1020                  has_selection_request = False;                  has_selection_request = False;
1021                  return;                  return;
# Line 802  ui_clip_handle_data(uint8 * data, uint32 Line 1029  ui_clip_handle_data(uint8 * data, uint32
1029  }  }
1030    
1031  void  void
1032    ui_clip_request_failed()
1033    {
1034            xclip_refuse_selection(&selection_request);
1035            has_selection_request = False;
1036    }
1037    
1038    void
1039  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
1040  {  {
1041          Window selectionowner;          Window primary_owner, clipboard_owner;
1042    
1043          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
1044          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
1045    
1046            if (probing_selections)
1047            {
1048                    DEBUG_CLIPBOARD(("ui_clip_request_data: Selection probe in progress. Cannot handle request.\n"));
1049                    helper_cliprdr_send_empty_response();
1050                    return;
1051            }
1052    
1053            xclip_clear_target_props();
1054    
1055          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
1056          {          {
1057                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
1058                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);                                  XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
1059    
1060                  XConvertSelection(g_display, primary_atom, rdesktop_clipboard_formats_atom,                  XConvertSelection(g_display, primary_atom, rdesktop_native_atom,
1061                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
1062                  return;                  return;
1063          }          }
1064    
1065          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
1066          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
1067            else
1068                    primary_owner = None;
1069    
1070            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
1071    
1072            /* Both available */
1073            if ((primary_owner != None) && (clipboard_owner != None))
1074            {
1075                    primary_timestamp = 0;
1076                    clipboard_timestamp = 0;
1077                    XConvertSelection(g_display, primary_atom, timestamp_atom,
1078                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
1079                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
1080                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
1081                    return;
1082            }
1083    
1084            /* Just PRIMARY */
1085            if (primary_owner != None)
1086          {          {
1087                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
1088                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
1089                  return;                  return;
1090          }          }
1091    
1092          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
1093          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
1094          {          {
1095                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
1096                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 837  ui_clip_request_data(uint32 format) Line 1098  ui_clip_request_data(uint32 format)
1098          }          }
1099    
1100          /* No data available */          /* No data available */
1101          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
1102  }  }
1103    
1104  void  void
1105  ui_clip_sync(void)  ui_clip_sync(void)
1106  {  {
1107          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          xclip_probe_selections();
1108  }  }
1109    
1110    void
1111    ui_clip_set_mode(const char *optarg)
1112    {
1113            g_rdpclip = True;
1114    
1115            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
1116                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
1117                    auto_mode = True;
1118            else if (str_startswith(optarg, "CLIPBOARD"))
1119                    auto_mode = False;
1120            else
1121            {
1122                    warning("Invalid clipboard mode '%s'.\n", optarg);
1123                    g_rdpclip = False;
1124            }
1125    }
1126    
1127  void  void
1128  xclip_init(void)  xclip_init(void)
1129  {  {
1130            if (!g_rdpclip)
1131                    return;
1132    
1133          if (!cliprdr_init())          if (!cliprdr_init())
1134                  return;                  return;
1135    
# Line 859  xclip_init(void) Line 1139  xclip_init(void)
1139          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
1140          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
1141                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
1142            rdesktop_primary_timestamp_target_atom =
1143                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
1144            rdesktop_clipboard_timestamp_target_atom =
1145                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
1146          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
1147          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
1148          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
1149          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
1150    
1151            /* rdesktop sets _RDESKTOP_SELECTION_NOTIFY on the root window when acquiring the clipboard.
1152               Other interested rdesktops can use this to notify their server of the available formats. */
1153            rdesktop_selection_notify_atom =
1154                    XInternAtom(g_display, "_RDESKTOP_SELECTION_NOTIFY", False);
1155            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
1156            probing_selections = False;
1157    
1158            rdesktop_native_atom = XInternAtom(g_display, "_RDESKTOP_NATIVE", False);
1159            rdesktop_clipboard_formats_atom =
1160                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1161            rdesktop_primary_owner_atom = XInternAtom(g_display, "_RDESKTOP_PRIMARY_OWNER", False);
1162            rdesktop_clipboard_owner_atom = XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_OWNER", False);
1163    
1164          num_targets = 0;          num_targets = 0;
1165          targets[num_targets++] = targets_atom;          targets[num_targets++] = targets_atom;
1166          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
1167            targets[num_targets++] = rdesktop_native_atom;
1168          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
1169          targets[num_targets++] = format_string_atom;  #ifdef USE_UNICODE_CLIPBOARD
         #ifdef USE_UNICODE_CLIPBOARD  
1170          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1171          #endif  #endif
1172          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1173            targets[num_targets++] = format_string_atom;
1174          targets[num_targets++] = XA_STRING;          targets[num_targets++] = XA_STRING;
1175    }
1176    
1177          /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.  void
1178             Other interested rdesktops can use this to notify their server of the available formats. */  xclip_deinit(void)
1179          rdesktop_clipboard_formats_atom =  {
1180                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);          if (XGetSelectionOwner(g_display, primary_atom) == g_wnd)
1181          XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);                  XSetSelectionOwner(g_display, primary_atom, None, acquire_time);
1182            if (XGetSelectionOwner(g_display, clipboard_atom) == g_wnd)
1183                    XSetSelectionOwner(g_display, clipboard_atom, None, acquire_time);
1184            xclip_notify_change();
1185  }  }

Legend:
Removed from v.1037  
changed lines
  Added in v.1214

  ViewVC Help
Powered by ViewVC 1.1.26