/[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 1038 by astrand, Thu Jan 5 11:56:57 2006 UTC revision 1210 by ossman_, Mon Mar 27 11:31:10 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 103  static int have_primary = 0; Line 114  static int have_primary = 0;
114  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,  /* Denotes that an rdesktop (not this rdesktop) is owning the selection,
115     allowing us to interchange Windows native clipboard data directly. */     allowing us to interchange Windows native clipboard data directly. */
116  static int rdesktop_is_selection_owner = 0;  static int rdesktop_is_selection_owner = 0;
117    /* Time when we acquired the selection. */
118    static Time acquire_time = 0;
119    
120  /* Denotes that an INCR ("chunked") transfer is in progress. */  /* Denotes that an INCR ("chunked") transfer is in progress. */
121  static int g_waiting_for_INCR = 0;  static int g_waiting_for_INCR = 0;
# Line 320  xclip_send_data_with_convert(uint8 * sou Line 333  xclip_send_data_with_convert(uint8 * sou
333                  char *unicode_buffer_remaining = unicode_buffer;                  char *unicode_buffer_remaining = unicode_buffer;
334                  char *data_remaining = (char *) source;                  char *data_remaining = (char *) source;
335                  size_t data_size_remaining = source_size;                  size_t data_size_remaining = source_size;
336                  iconv(cd, &data_remaining, &data_size_remaining, &unicode_buffer_remaining,                  iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
337                        &unicode_buffer_size_remaining);                        &unicode_buffer_remaining, &unicode_buffer_size_remaining);
338                  iconv_close(cd);                  iconv_close(cd);
339    
340                  /* translate linebreaks */                  /* translate linebreaks */
# Line 332  xclip_send_data_with_convert(uint8 * sou Line 345  xclip_send_data_with_convert(uint8 * sou
345                  {                  {
346                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",                          DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
347                                           translated_data_size));                                           translated_data_size));
348                          cliprdr_send_data(translated_data, translated_data_size);                          helper_cliprdr_send_response(translated_data, translated_data_size);
349                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
350                  }                  }
351    
# Line 353  xclip_send_data_with_convert(uint8 * sou Line 366  xclip_send_data_with_convert(uint8 * sou
366                  translated_data = lf2crlf(source, &length);                  translated_data = lf2crlf(source, &length);
367                  if (translated_data != NULL)                  if (translated_data != NULL)
368                  {                  {
369                          cliprdr_send_data(translated_data, length);                          helper_cliprdr_send_response(translated_data, length);
370                          xfree(translated_data); /* Not the same thing as XFree! */                          xfree(translated_data); /* Not the same thing as XFree! */
371                  }                  }
372    
# Line 372  xclip_send_data_with_convert(uint8 * sou Line 385  xclip_send_data_with_convert(uint8 * sou
385          }          }
386  }  }
387    
388    static void
389    xclip_clear_target_props()
390    {
391            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
392            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
393            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
394    }
395    
396  /* This function is called for SelectionNotify events.  /* This function is called for SelectionNotify events.
397     The SelectionNotify event is sent from the clipboard owner to the requestor     The SelectionNotify event is sent from the clipboard owner to the requestor
398     after his request was satisfied.     after his request was satisfied.
# Line 385  xclip_handle_SelectionNotify(XSelectionE Line 406  xclip_handle_SelectionNotify(XSelectionE
406          Atom type;          Atom type;
407          Atom *supported_targets;          Atom *supported_targets;
408          int res, i, format;          int res, i, format;
409          uint8 *data;          uint8 *data = NULL;
410    
411          if (event->property == None)          if (event->property == None)
412                  goto fail;                  goto fail;
# Line 395  xclip_handle_SelectionNotify(XSelectionE Line 416  xclip_handle_SelectionNotify(XSelectionE
416                           XGetAtomName(g_display, event->target),                           XGetAtomName(g_display, event->target),
417                           XGetAtomName(g_display, event->property)));                           XGetAtomName(g_display, event->property)));
418    
419          if (event->property == None)          if (event->target == timestamp_atom)
420                  goto fail;          {
421                    if (event->selection == primary_atom)
422                    {
423                            res = XGetWindowProperty(g_display, g_wnd,
424                                                     rdesktop_primary_timestamp_target_atom, 0,
425                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
426                                                     &type, &format, &nitems, &bytes_left, &data);
427                    }
428                    else
429                    {
430                            res = XGetWindowProperty(g_display, g_wnd,
431                                                     rdesktop_clipboard_timestamp_target_atom, 0,
432                                                     XMaxRequestSize(g_display), False, XA_INTEGER,
433                                                     &type, &format, &nitems, &bytes_left, &data);
434                    }
435    
436    
437                    if ((res != Success) || (nitems != 1))
438                    {
439                            DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
440                            goto fail;
441                    }
442    
443                    if (event->selection == primary_atom)
444                    {
445                            primary_timestamp = *(Time *) data;
446                            if (primary_timestamp == 0)
447                                    primary_timestamp++;
448                            XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
449                            DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
450                                             (unsigned) primary_timestamp));
451                    }
452                    else
453                    {
454                            clipboard_timestamp = *(Time *) data;
455                            if (clipboard_timestamp == 0)
456                                    clipboard_timestamp++;
457                            XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
458                            DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
459                                             (unsigned) clipboard_timestamp));
460                    }
461    
462                    XFree(data);
463    
464                    if (primary_timestamp && clipboard_timestamp)
465                    {
466                            if (primary_timestamp > clipboard_timestamp)
467                            {
468                                    DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
469                                    XConvertSelection(g_display, primary_atom, targets_atom,
470                                                      rdesktop_clipboard_target_atom, g_wnd,
471                                                      event->time);
472                            }
473                            else
474                            {
475                                    DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
476                                    XConvertSelection(g_display, clipboard_atom, targets_atom,
477                                                      rdesktop_clipboard_target_atom, g_wnd,
478                                                      event->time);
479                            }
480                    }
481    
482                    return;
483            }
484    
485          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,          res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
486                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,                                   0, XMaxRequestSize(g_display), False, AnyPropertyType,
487                                   &type, &format, &nitems, &bytes_left, &data);                                   &type, &format, &nitems, &bytes_left, &data);
488    
489            xclip_clear_target_props();
490    
491          if (res != Success)          if (res != Success)
492          {          {
493                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));                  DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
# Line 417  xclip_handle_SelectionNotify(XSelectionE Line 503  xclip_handle_SelectionNotify(XSelectionE
503                  {                  {
504                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));                          XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
505                  }                  }
                 XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
506                  XFree(data);                  XFree(data);
507                  g_incr_target = event->target;                  g_incr_target = event->target;
508                  g_waiting_for_INCR = 1;                  g_waiting_for_INCR = 1;
509                  return;                  return;
510          }          }
511    
         XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);  
   
512          /* Negotiate target format */          /* Negotiate target format */
513          if (event->target == targets_atom)          if (event->target == targets_atom)
514          {          {
# Line 479  xclip_handle_SelectionNotify(XSelectionE Line 562  xclip_handle_SelectionNotify(XSelectionE
562                   */                   */
563                  if (best_text_target != 0)                  if (best_text_target != 0)
564                  {                  {
565                          XConvertSelection(g_display, clipboard_atom, best_text_target,                          XConvertSelection(g_display, event->selection, best_text_target,
566                                            rdesktop_clipboard_target_atom, g_wnd, event->time);                                            rdesktop_clipboard_target_atom, g_wnd, event->time);
567                          return;                          return;
568                  }                  }
# Line 502  xclip_handle_SelectionNotify(XSelectionE Line 585  xclip_handle_SelectionNotify(XSelectionE
585          return;          return;
586    
587        fail:        fail:
588          XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);          xclip_clear_target_props();
589          XFree(data);          if (data)
590                    XFree(data);
591          helper_cliprdr_send_empty_response();          helper_cliprdr_send_empty_response();
592  }  }
593    
# Line 532  xclip_handle_SelectionRequest(XSelection Line 616  xclip_handle_SelectionRequest(XSelection
616          }          }
617          else if (event->target == timestamp_atom)          else if (event->target == timestamp_atom)
618          {          {
619                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & g_last_gesturetime, 1);                  xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & acquire_time, 1);
620                  return;                  return;
621          }          }
622          else          else
# Line 716  xclip_handle_PropertyNotify(XPropertyEve Line 800  xclip_handle_PropertyNotify(XPropertyEve
800  void  void
801  ui_clip_format_announce(uint8 * data, uint32 length)  ui_clip_format_announce(uint8 * data, uint32 length)
802  {  {
803          XSetSelectionOwner(g_display, primary_atom, g_wnd, g_last_gesturetime);          acquire_time = g_last_gesturetime;
804    
805            XSetSelectionOwner(g_display, primary_atom, g_wnd, acquire_time);
806          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)          if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
807          {          {
808                  warning("Failed to aquire ownership of PRIMARY clipboard\n");                  warning("Failed to aquire ownership of PRIMARY clipboard\n");
# Line 728  ui_clip_format_announce(uint8 * data, ui Line 814  ui_clip_format_announce(uint8 * data, ui
814                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,                          rdesktop_clipboard_formats_atom, XA_STRING, 8, PropModeReplace, data,
815                          length);                          length);
816    
817          XSetSelectionOwner(g_display, clipboard_atom, g_wnd, g_last_gesturetime);          XSetSelectionOwner(g_display, clipboard_atom, g_wnd, acquire_time);
818          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)          if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
819                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");                  warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
820  }  }
# Line 739  ui_clip_handle_data(uint8 * data, uint32 Line 825  ui_clip_handle_data(uint8 * data, uint32
825  {  {
826          BOOL free_data = False;          BOOL free_data = False;
827    
828            if (length == 0)
829            {
830                    xclip_refuse_selection(&selection_request);
831                    has_selection_request = False;
832                    return;
833            }
834    
835          if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)          if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)
836          {          {
837                  /* We're expecting a CF_TEXT response */                  /* We're expecting a CF_TEXT response */
# Line 772  ui_clip_handle_data(uint8 * data, uint32 Line 865  ui_clip_handle_data(uint8 * data, uint32
865                                  iconv_close(cd);                                  iconv_close(cd);
866                                  return;                                  return;
867                          }                          }
868                          iconv(cd, &data_remaining, &length_remaining, &utf8_data_remaining,                          iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
869                                &utf8_length_remaining);                                &utf8_data_remaining, &utf8_length_remaining);
870                          iconv_close(cd);                          iconv_close(cd);
871                          free_data = True;                          free_data = True;
872                          data = (uint8 *) utf8_data;                          data = (uint8 *) utf8_data;
# Line 808  ui_clip_handle_data(uint8 * data, uint32 Line 901  ui_clip_handle_data(uint8 * data, uint32
901  void  void
902  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
903  {  {
904          Window selectionowner;          Window primary_owner, clipboard_owner;
905    
906          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
907          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
908    
909            xclip_clear_target_props();
910    
911          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
912          {          {
913                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,                  XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
# Line 823  ui_clip_request_data(uint32 format) Line 918  ui_clip_request_data(uint32 format)
918                  return;                  return;
919          }          }
920    
921          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
922          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
923            else
924                    primary_owner = None;
925    
926            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
927    
928            /* Both available */
929            if ((primary_owner != None) && (clipboard_owner != None))
930            {
931                    primary_timestamp = 0;
932                    clipboard_timestamp = 0;
933                    XConvertSelection(g_display, primary_atom, timestamp_atom,
934                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
935                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
936                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
937                    return;
938            }
939    
940            /* Just PRIMARY */
941            if (primary_owner != None)
942          {          {
943                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
944                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
945                  return;                  return;
946          }          }
947    
948          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
949          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
950          {          {
951                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
952                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 841  ui_clip_request_data(uint32 format) Line 954  ui_clip_request_data(uint32 format)
954          }          }
955    
956          /* No data available */          /* No data available */
957          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
958  }  }
959    
960  void  void
# Line 850  ui_clip_sync(void) Line 963  ui_clip_sync(void)
963          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
964  }  }
965    
966    void
967    ui_clip_set_mode(const char *optarg)
968    {
969            g_rdpclip = True;
970    
971            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
972                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
973                    auto_mode = True;
974            else if (str_startswith(optarg, "CLIPBOARD"))
975                    auto_mode = False;
976            else
977            {
978                    warning("Invalid clipboard mode '%s'.\n", optarg);
979                    g_rdpclip = False;
980            }
981    }
982    
983  void  void
984  xclip_init(void)  xclip_init(void)
985  {  {
986            if (!g_rdpclip)
987                    return;
988    
989          if (!cliprdr_init())          if (!cliprdr_init())
990                  return;                  return;
991    
# Line 863  xclip_init(void) Line 995  xclip_init(void)
995          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
996          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
997                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
998            rdesktop_primary_timestamp_target_atom =
999                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
1000            rdesktop_clipboard_timestamp_target_atom =
1001                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
1002          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
1003          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
1004          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
1005          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
1006    
1007            /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
1008               Other interested rdesktops can use this to notify their server of the available formats. */
1009            rdesktop_clipboard_formats_atom =
1010                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1011            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
1012    
1013          num_targets = 0;          num_targets = 0;
1014          targets[num_targets++] = targets_atom;          targets[num_targets++] = targets_atom;
1015          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
1016          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
         targets[num_targets++] = format_string_atom;  
1017  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
1018          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1019  #endif  #endif
1020          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1021            targets[num_targets++] = format_string_atom;
1022          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);  
1023  }  }

Legend:
Removed from v.1038  
changed lines
  Added in v.1210

  ViewVC Help
Powered by ViewVC 1.1.26