/[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 1050 by stargo, Wed Mar 1 14:16:41 2006 UTC revision 1211 by ossman_, Mon Mar 27 12:29:29 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 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 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          if (data)          if (data)
590                  XFree(data);                  XFree(data);
591          helper_cliprdr_send_empty_response();          helper_cliprdr_send_empty_response();
# Line 533  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 717  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 729  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 740  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 807  ui_clip_handle_data(uint8 * data, uint32 Line 899  ui_clip_handle_data(uint8 * data, uint32
899  }  }
900    
901  void  void
902    ui_clip_request_failed()
903    {
904            xclip_refuse_selection(&selection_request);
905            has_selection_request = False;
906    }
907    
908    void
909  ui_clip_request_data(uint32 format)  ui_clip_request_data(uint32 format)
910  {  {
911          Window selectionowner;          Window primary_owner, clipboard_owner;
912    
913          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));          DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
914          rdp_clipboard_request_format = format;          rdp_clipboard_request_format = format;
915    
916            xclip_clear_target_props();
917    
918          if (rdesktop_is_selection_owner)          if (rdesktop_is_selection_owner)
919          {          {
920                  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 925  ui_clip_request_data(uint32 format)
925                  return;                  return;
926          }          }
927    
928          selectionowner = XGetSelectionOwner(g_display, primary_atom);          if (auto_mode)
929          if (selectionowner != None)                  primary_owner = XGetSelectionOwner(g_display, primary_atom);
930            else
931                    primary_owner = None;
932    
933            clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
934    
935            /* Both available */
936            if ((primary_owner != None) && (clipboard_owner != None))
937            {
938                    primary_timestamp = 0;
939                    clipboard_timestamp = 0;
940                    XConvertSelection(g_display, primary_atom, timestamp_atom,
941                                      rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
942                    XConvertSelection(g_display, clipboard_atom, timestamp_atom,
943                                      rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
944                    return;
945            }
946    
947            /* Just PRIMARY */
948            if (primary_owner != None)
949          {          {
950                  XConvertSelection(g_display, primary_atom, targets_atom,                  XConvertSelection(g_display, primary_atom, targets_atom,
951                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
952                  return;                  return;
953          }          }
954    
955          /* No PRIMARY, try CLIPBOARD */          /* Just CLIPBOARD */
956          selectionowner = XGetSelectionOwner(g_display, clipboard_atom);          if (clipboard_owner != None)
         if (selectionowner != None)  
957          {          {
958                  XConvertSelection(g_display, clipboard_atom, targets_atom,                  XConvertSelection(g_display, clipboard_atom, targets_atom,
959                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);                                    rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
# Line 842  ui_clip_request_data(uint32 format) Line 961  ui_clip_request_data(uint32 format)
961          }          }
962    
963          /* No data available */          /* No data available */
964          cliprdr_send_data(NULL, 0);          helper_cliprdr_send_empty_response();
965  }  }
966    
967  void  void
# Line 851  ui_clip_sync(void) Line 970  ui_clip_sync(void)
970          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);          cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
971  }  }
972    
973    void
974    ui_clip_set_mode(const char *optarg)
975    {
976            g_rdpclip = True;
977    
978            if (str_startswith(optarg, "auto") || str_startswith(optarg, "on")
979                || str_startswith(optarg, "PRIMARYCLIPBOARD"))
980                    auto_mode = True;
981            else if (str_startswith(optarg, "CLIPBOARD"))
982                    auto_mode = False;
983            else
984            {
985                    warning("Invalid clipboard mode '%s'.\n", optarg);
986                    g_rdpclip = False;
987            }
988    }
989    
990  void  void
991  xclip_init(void)  xclip_init(void)
992  {  {
993            if (!g_rdpclip)
994                    return;
995    
996          if (!cliprdr_init())          if (!cliprdr_init())
997                  return;                  return;
998    
# Line 864  xclip_init(void) Line 1002  xclip_init(void)
1002          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);          timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
1003          rdesktop_clipboard_target_atom =          rdesktop_clipboard_target_atom =
1004                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);                  XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
1005            rdesktop_primary_timestamp_target_atom =
1006                    XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
1007            rdesktop_clipboard_timestamp_target_atom =
1008                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
1009          incr_atom = XInternAtom(g_display, "INCR", False);          incr_atom = XInternAtom(g_display, "INCR", False);
1010          format_string_atom = XInternAtom(g_display, "STRING", False);          format_string_atom = XInternAtom(g_display, "STRING", False);
1011          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);          format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
1012          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);          format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
1013    
1014            /* rdesktop sets _RDESKTOP_CLIPBOARD_FORMATS on the root window when acquiring the clipboard.
1015               Other interested rdesktops can use this to notify their server of the available formats. */
1016            rdesktop_clipboard_formats_atom =
1017                    XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
1018            XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
1019    
1020          num_targets = 0;          num_targets = 0;
1021          targets[num_targets++] = targets_atom;          targets[num_targets++] = targets_atom;
1022          targets[num_targets++] = timestamp_atom;          targets[num_targets++] = timestamp_atom;
1023          targets[num_targets++] = rdesktop_clipboard_formats_atom;          targets[num_targets++] = rdesktop_clipboard_formats_atom;
         targets[num_targets++] = format_string_atom;  
1024  #ifdef USE_UNICODE_CLIPBOARD  #ifdef USE_UNICODE_CLIPBOARD
1025          targets[num_targets++] = format_utf8_string_atom;          targets[num_targets++] = format_utf8_string_atom;
1026  #endif  #endif
1027          targets[num_targets++] = format_unicode_atom;          targets[num_targets++] = format_unicode_atom;
1028            targets[num_targets++] = format_string_atom;
1029          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);  
1030  }  }

Legend:
Removed from v.1050  
changed lines
  Added in v.1211

  ViewVC Help
Powered by ViewVC 1.1.26