/[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 1209 by ossman_, Mon Mar 27 11:10:09 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 385  xclip_handle_SelectionNotify(XSelectionE Line 404  xclip_handle_SelectionNotify(XSelectionE
404          Atom type;          Atom type;
405          Atom *supported_targets;          Atom *supported_targets;
406          int res, i, format;          int res, i, format;
407          uint8 *data;          uint8 *data = NULL;
408    
409          if (event->property == None)          if (event->property == None)
410                  goto fail;                  goto fail;
# 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          XFree(data);          if (data)
588                    XFree(data);
589          helper_cliprdr_send_empty_response();          helper_cliprdr_send_empty_response();
590  }  }
591    
# Line 739  ui_clip_handle_data(uint8 * data, uint32 Line 821  ui_clip_handle_data(uint8 * data, uint32
821  {  {
822          BOOL free_data = False;          BOOL free_data = False;
823    
824            if (length == 0)
825            {
826                    xclip_refuse_selection(&selection_request);
827                    has_selection_request = False;
828                    return;
829            }
830    
831          if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)          if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)
832          {          {
833                  /* We're expecting a CF_TEXT response */                  /* We're expecting a CF_TEXT response */
# Line 772  ui_clip_handle_data(uint8 * data, uint32 Line 861  ui_clip_handle_data(uint8 * data, uint32
861                                  iconv_close(cd);                                  iconv_close(cd);
862                                  return;                                  return;
863                          }                          }
864                          iconv(cd, &data_remaining, &length_remaining, &utf8_data_remaining,                          iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
865                                &utf8_length_remaining);                                &utf8_data_remaining, &utf8_length_remaining);
866                          iconv_close(cd);                          iconv_close(cd);
867                          free_data = True;                          free_data = True;
868                          data = (uint8 *) utf8_data;                          data = (uint8 *) utf8_data;
# Line 808  ui_clip_handle_data(uint8 * data, uint32 Line 897  ui_clip_handle_data(uint8 * data, uint32
897  void  void
898  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
899  {  {
900          Window selectionowner;          Window primary_owner, clipboard_owner;
901    
902          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
903          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
904    
905            xclip_clear_target_props();
906    
907          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
908          {          {
909                  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 914  ui_clip_request_data(uint32 format)
914                  return;                  return;
915          }          }
916    
917          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
918          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
919            else
920                    primary_owner = None;
921    
922            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
923    
924            /* Both available */
925            if ((primary_owner != None) && (clipboard_owner != None))
926            {
927                    primary_timestamp = 0;
928                    clipboard_timestamp = 0;
929                    XConvertSelection(g_display, primary_atom, timestamp_atom,
930                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
931                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
932                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
933                    return;
934            }
935    
936            /* Just PRIMARY */
937            if (primary_owner != None)
938          {          {
939                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
940                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
941                  return;                  return;
942          }          }
943    
944          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
945          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
946          {          {
947                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
948                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 841  ui_clip_request_data(uint32 format) Line 950  ui_clip_request_data(uint32 format)
950          }          }
951    
952          /* No data available */          /* No data available */
953          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
954  }  }
955    
956  void  void
# Line 850  ui_clip_sync(void) Line 959  ui_clip_sync(void)
959          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
960  }  }
961    
962    void
963    ui_clip_set_mode(const char *optarg)
964    {
965            g_rdpclip = True;
966    
967            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
968                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
969                    auto_mode = True;
970            else if (str_startswith(optarg, "CLIPBOARD"))
971                    auto_mode = False;
972            else
973            {
974                    warning("Invalid clipboard mode '%s'.\n", optarg);
975                    g_rdpclip = False;
976            }
977    }
978    
979  void  void
980  xclip_init(void)  xclip_init(void)
981  {  {
982            if (!g_rdpclip)
983                    return;
984    
985          if (!cliprdr_init())          if (!cliprdr_init())
986                  return;                  return;
987    
# Line 863  xclip_init(void) Line 991  xclip_init(void)
991          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
992          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
993                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
994            rdesktop_primary_timestamp_target_atom =
995                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
996            rdesktop_clipboard_timestamp_target_atom =
997                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
998          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
999          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
1000          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
1001          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
1002    
1003            /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
1004               Other interested rdesktops can use this to notify their server of the available formats. */
1005            rdesktop_clipboard_formats_atom =
1006                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1007            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
1008    
1009          num_targets = 0;          num_targets = 0;
1010          targets[num_targets++] = targets_atom;          targets[num_targets++] = targets_atom;
1011          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
1012          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
         targets[num_targets++] = format_string_atom;  
1013  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
1014          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1015  #endif  #endif
1016          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1017            targets[num_targets++] = format_string_atom;
1018          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);  
1019  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26