/[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 1048 by astrand, Tue Feb 28 08:09:41 2006 UTC revision 1208 by ossman_, Mon Mar 27 10:41:22 2006 UTC
# Line 53  Line 53 
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 */
# Line 69  static Atom timestamp_atom; Line 74  static Atom timestamp_atom;
74       before requesting clipboard data from a fellow rdesktop using       before requesting clipboard data from a fellow rdesktop using
75       the _RDESKTOP_CLIPBOARD_FORMATS target. */       the _RDESKTOP_CLIPBOARD_FORMATS target. */
76  static Atom rdesktop_clipboard_target_atom;  static Atom rdesktop_clipboard_target_atom;
77    /* Atoms _RDESKTOP_PRIMARY_TIMESTAMP_TARGET and _RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET
78       are used to store the timestamps for when a window got ownership of the selections.
79       We use these to determine which is more recent and should be used. */
80    static Atom rdesktop_primary_timestamp_target_atom, rdesktop_clipboard_timestamp_target_atom;
81    /* Storage for timestamps since we get them in two separate notifications. */
82    static Time primary_timestamp, clipboard_timestamp;
83  /* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses:  /* Atom _RDESKTOP_CLIPBOARD_FORMATS which has multiple uses:
84     - The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange     - The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop interchange
85       of Windows native clipboard data.       of Windows native clipboard data.
# Line 320  xclip_send_data_with_convert(uint8 * sou Line 331  xclip_send_data_with_convert(uint8 * sou
331                  char *unicode_buffer_remaining = unicode_buffer;                  char *unicode_buffer_remaining = unicode_buffer;
332                  char *data_remaining = (char *) source;                  char *data_remaining = (char *) source;
333                  size_t data_size_remaining = source_size;                  size_t data_size_remaining = source_size;
334                  iconv(cd, &data_remaining, &data_size_remaining, &unicode_buffer_remaining,                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
335                        &unicode_buffer_size_remaining);                        &unicode_buffer_remaining, &unicode_buffer_size_remaining);
336                  iconv_close(cd);                  iconv_close(cd);
337    
338                  /* translate linebreaks */                  /* translate linebreaks */
# Line 332  xclip_send_data_with_convert(uint8 * sou Line 343  xclip_send_data_with_convert(uint8 * sou
343                  {                  {
344                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
345                                           translated_data_size));                                           translated_data_size));
346                          cliprdr_send_data(translated_data, translated_data_size);                          helper_cliprdr_send_response(translated_data, translated_data_size);
347                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
348                  }                  }
349    
# Line 353  xclip_send_data_with_convert(uint8 * sou Line 364  xclip_send_data_with_convert(uint8 * sou
364                  translated_data = lf2crlf(source, &length);                  translated_data = lf2crlf(source, &length);
365                  if (translated_data != NULL)                  if (translated_data != NULL)
366                  {                  {
367                          cliprdr_send_data(translated_data, length);                          helper_cliprdr_send_response(translated_data, length);
368                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
369                  }                  }
370    
# Line 372  xclip_send_data_with_convert(uint8 * sou Line 383  xclip_send_data_with_convert(uint8 * sou
383          }          }
384  }  }
385    
386    static void
387    xclip_clear_target_props()
388    {
389            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
390            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
391            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
392    }
393    
394  /* This function is called for SelectionNotify events.  /* This function is called for SelectionNotify events.
395     The SelectionNotify event is sent from the clipboard owner to the requestor     The SelectionNotify event is sent from the clipboard owner to the requestor
396     after his request was satisfied.     after his request was satisfied.
# Line 395  xclip_handle_SelectionNotify(XSelectionE Line 414  xclip_handle_SelectionNotify(XSelectionE
414                           XGetAtomName(g_display, event->target),                           XGetAtomName(g_display, event->target),
415                           XGetAtomName(g_display, event->property)));                           XGetAtomName(g_display, event->property)));
416    
417          if (event->property == None)          if (event->target == timestamp_atom)
418                  goto fail;          {
419                    if (event->selection == primary_atom)
420                    {
421                            res = XGetWindowProperty(g_display, g_wnd,
422                                                     rdesktop_primary_timestamp_target_atom, 0,
423                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
424                                                     &type, &format, &nitems, &bytes_left, &data);
425                    }
426                    else
427                    {
428                            res = XGetWindowProperty(g_display, g_wnd,
429                                                     rdesktop_clipboard_timestamp_target_atom, 0,
430                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
431                                                     &type, &format, &nitems, &bytes_left, &data);
432                    }
433    
434    
435                    if ((res != Success) || (nitems != 1))
436                    {
437                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
438                            goto fail;
439                    }
440    
441                    if (event->selection == primary_atom)
442                    {
443                            primary_timestamp = *(Time *) data;
444                            if (primary_timestamp == 0)
445                                    primary_timestamp++;
446                            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
447                            DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
448                                             (unsigned) primary_timestamp));
449                    }
450                    else
451                    {
452                            clipboard_timestamp = *(Time *) data;
453                            if (clipboard_timestamp == 0)
454                                    clipboard_timestamp++;
455                            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
456                            DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
457                                             (unsigned) clipboard_timestamp));
458                    }
459    
460                    XFree(data);
461    
462                    if (primary_timestamp && clipboard_timestamp)
463                    {
464                            if (primary_timestamp > clipboard_timestamp)
465                            {
466                                    DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
467                                    XConvertSelection(g_display, primary_atom, targets_atom,
468                                                      rdesktop_clipboard_target_atom, g_wnd,
469                                                      event->time);
470                            }
471                            else
472                            {
473                                    DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
474                                    XConvertSelection(g_display, clipboard_atom, targets_atom,
475                                                      rdesktop_clipboard_target_atom, g_wnd,
476                                                      event->time);
477                            }
478                    }
479    
480                    return;
481            }
482    
483          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
484                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,
485                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
486    
487            xclip_clear_target_props();
488    
489          if (res != Success)          if (res != Success)
490          {          {
491                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
# Line 417  xclip_handle_SelectionNotify(XSelectionE Line 501  xclip_handle_SelectionNotify(XSelectionE
501                  {                  {
502                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
503                  }                  }
                 XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
504                  XFree(data);                  XFree(data);
505                  g_incr_target = event->target;                  g_incr_target = event->target;
506                  g_waiting_for_INCR = 1;                  g_waiting_for_INCR = 1;
507                  return;                  return;
508          }          }
509    
         XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
   
510          /* Negotiate target format */          /* Negotiate target format */
511          if (event->target == targets_atom)          if (event->target == targets_atom)
512          {          {
# Line 479  xclip_handle_SelectionNotify(XSelectionE Line 560  xclip_handle_SelectionNotify(XSelectionE
560                   */                   */
561                  if (best_text_target != 0)                  if (best_text_target != 0)
562                  {                  {
563                          XConvertSelection(g_display, clipboard_atom, best_text_target,                          XConvertSelection(g_display, event->selection, best_text_target,
564                                            rdesktop_clipboard_target_atom, g_wnd, event->time);                                            rdesktop_clipboard_target_atom, g_wnd, event->time);
565                          return;                          return;
566                  }                  }
# Line 502  xclip_handle_SelectionNotify(XSelectionE Line 583  xclip_handle_SelectionNotify(XSelectionE
583          return;          return;
584    
585        fail:        fail:
586          XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);          xclip_clear_target_props();
587          if (data)          if (data)
588                  XFree(data);                  XFree(data);
589          helper_cliprdr_send_empty_response();          helper_cliprdr_send_empty_response();
# Line 773  ui_clip_handle_data(uint8 * data, uint32 Line 854  ui_clip_handle_data(uint8 * data, uint32
854                                  iconv_close(cd);                                  iconv_close(cd);
855                                  return;                                  return;
856                          }                          }
857                          iconv(cd, &data_remaining, &length_remaining, &utf8_data_remaining,                          iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
858                                &utf8_length_remaining);                                &utf8_data_remaining, &utf8_length_remaining);
859                          iconv_close(cd);                          iconv_close(cd);
860                          free_data = True;                          free_data = True;
861                          data = (uint8 *) utf8_data;                          data = (uint8 *) utf8_data;
# Line 809  ui_clip_handle_data(uint8 * data, uint32 Line 890  ui_clip_handle_data(uint8 * data, uint32
890  void  void
891  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
892  {  {
893          Window selectionowner;          Window primary_owner, clipboard_owner;
894    
895          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
896          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
897    
898            xclip_clear_target_props();
899    
900          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
901          {          {
902                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
# Line 824  ui_clip_request_data(uint32 format) Line 907  ui_clip_request_data(uint32 format)
907                  return;                  return;
908          }          }
909    
910          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
911          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
912            else
913                    primary_owner = None;
914    
915            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
916    
917            /* Both available */
918            if ((primary_owner != None) && (clipboard_owner != None))
919            {
920                    primary_timestamp = 0;
921                    clipboard_timestamp = 0;
922                    XConvertSelection(g_display, primary_atom, timestamp_atom,
923                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
924                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
925                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
926                    return;
927            }
928    
929            /* Just PRIMARY */
930            if (primary_owner != None)
931          {          {
932                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
933                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
934                  return;                  return;
935          }          }
936    
937          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
938          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
939          {          {
940                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
941                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 842  ui_clip_request_data(uint32 format) Line 943  ui_clip_request_data(uint32 format)
943          }          }
944    
945          /* No data available */          /* No data available */
946          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
947  }  }
948    
949  void  void
# Line 851  ui_clip_sync(void) Line 952  ui_clip_sync(void)
952          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
953  }  }
954    
955    void
956    ui_clip_set_mode(const char *optarg)
957    {
958            g_rdpclip = True;
959    
960            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
961                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
962                    auto_mode = True;
963            else if (str_startswith(optarg, "CLIPBOARD"))
964                    auto_mode = False;
965            else
966            {
967                    warning("Invalid clipboard mode '%s'.\n", optarg);
968                    g_rdpclip = False;
969            }
970    }
971    
972  void  void
973  xclip_init(void)  xclip_init(void)
974  {  {
975            if (!g_rdpclip)
976                    return;
977    
978          if (!cliprdr_init())          if (!cliprdr_init())
979                  return;                  return;
980    
# Line 864  xclip_init(void) Line 984  xclip_init(void)
984          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
985          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
986                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
987            rdesktop_primary_timestamp_target_atom =
988                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
989            rdesktop_clipboard_timestamp_target_atom =
990                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
991          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
992          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
993          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
994          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
995    
996            /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
997               Other interested rdesktops can use this to notify their server of the available formats. */
998            rdesktop_clipboard_formats_atom =
999                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1000            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
1001    
1002          num_targets = 0;          num_targets = 0;
1003          targets[num_targets++] = targets_atom;          targets[num_targets++] = targets_atom;
1004          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
1005          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
         targets[num_targets++] = format_string_atom;  
1006  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
1007          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1008  #endif  #endif
1009          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1010            targets[num_targets++] = format_string_atom;
1011          targets[num_targets++] = XA_STRING;          targets[num_targets++] = XA_STRING;
   
         /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.  
            Other interested rdesktops can use this to notify their server of the available formats. */  
         rdesktop_clipboard_formats_atom =  
                 XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);  
         XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);  
1012  }  }

Legend:
Removed from v.1048  
changed lines
  Added in v.1208

  ViewVC Help
Powered by ViewVC 1.1.26