Home | History | Annotate | Download | only in linux
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Don't include this file from any .h files because it pulls in some X headers.
      6 
      7 #ifndef REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_
      8 #define REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_
      9 
     10 #include <X11/Xatom.h>
     11 #include <X11/Xlib.h>
     12 
     13 #include <set>
     14 #include <string>
     15 
     16 #include "base/basictypes.h"
     17 #include "base/callback_forward.h"
     18 #include "base/timer/timer.h"
     19 
     20 namespace remoting {
     21 
     22 // A class to allow manipulation of the X clipboard, using only X API calls.
     23 // This class is not thread-safe, so all its methods must be called on the
     24 // application's main event-processing thread.
     25 class XServerClipboard {
     26  public:
     27   // Called when new clipboard data has been received from the owner of the X
     28   // selection (primary or clipboard).
     29   // |mime_type| is the MIME type associated with the data. This will be one of
     30   // the types listed in remoting/base/constants.h.
     31   // |data| is the clipboard data from the associated X event, encoded with the
     32   // specified MIME-type.
     33   typedef base::Callback<void(const std::string& mime_type,
     34                               const std::string& data)>
     35       ClipboardChangedCallback;
     36 
     37   XServerClipboard();
     38   ~XServerClipboard();
     39 
     40   // Start monitoring |display|'s selections, and invoke |callback| whenever
     41   // their content changes. The caller must ensure |display| is still valid
     42   // whenever any other methods are called on this object.
     43   void Init(Display* display, const ClipboardChangedCallback& callback);
     44 
     45   // Copy data to the X Clipboard.  This acquires ownership of the
     46   // PRIMARY and CLIPBOARD selections.
     47   void SetClipboard(const std::string& mime_type, const std::string& data);
     48 
     49   // Process |event| if it is an X selection notification. The caller should
     50   // invoke this for every event it receives from |display|.
     51   void ProcessXEvent(XEvent* event);
     52 
     53  private:
     54   // Handlers called by ProcessXEvent() for each event type.
     55   void OnSetSelectionOwnerNotify(Atom selection, Time timestamp);
     56   void OnPropertyNotify(XEvent* event);
     57   void OnSelectionNotify(XEvent* event);
     58   void OnSelectionRequest(XEvent* event);
     59   void OnSelectionClear(XEvent* event);
     60 
     61   // Used by OnSelectionRequest() to respond to requests for details of our
     62   // clipboard content. This is done by changing the property |property| of the
     63   // |requestor| window (these values come from the XSelectionRequestEvent).
     64   // |target| must be a string type (STRING or UTF8_STRING).
     65   void SendTargetsResponse(Window requestor, Atom property);
     66   void SendTimestampResponse(Window requestor, Atom property);
     67   void SendStringResponse(Window requestor, Atom property, Atom target);
     68 
     69   // Called by OnSelectionNotify() when the selection owner has replied to a
     70   // request for information about a selection.
     71   // |event| is the raw X event from the notification.
     72   // |type|, |format| etc are the results from XGetWindowProperty(), or 0 if
     73   // there is no associated data.
     74   void HandleSelectionNotify(XSelectionEvent* event,
     75                              Atom type,
     76                              int format,
     77                              int item_count,
     78                              void* data);
     79 
     80   // These methods return true if selection processing is complete, false
     81   // otherwise. They are called from HandleSelectionNotify(), and take the same
     82   // arguments.
     83   bool HandleSelectionTargetsEvent(XSelectionEvent* event,
     84                                    int format,
     85                                    int item_count,
     86                                    void* data);
     87   bool HandleSelectionStringEvent(XSelectionEvent* event,
     88                                   int format,
     89                                   int item_count,
     90                                   void* data);
     91 
     92   // Notify the registered callback of new clipboard text.
     93   void NotifyClipboardText(const std::string& text);
     94 
     95   // These methods trigger the X server or selection owner to send back an
     96   // event containing the requested information.
     97   void RequestSelectionTargets(Atom selection);
     98   void RequestSelectionString(Atom selection, Atom target);
     99 
    100   // Assert ownership of the specified |selection|.
    101   void AssertSelectionOwnership(Atom selection);
    102   bool IsSelectionOwner(Atom selection);
    103 
    104   // Stores the Display* supplied to Init().
    105   Display* display_;
    106 
    107   // Window through which clipboard events are received, or BadValue if the
    108   // window could not be created.
    109   Window clipboard_window_;
    110 
    111   // The event base returned by XFixesQueryExtension(). If XFixes is
    112   // unavailable, the clipboard window will not be created, and no
    113   // event-processing will take place.
    114   int xfixes_event_base_;
    115 
    116   // Cached atoms for various strings, initialized during Init().
    117   Atom clipboard_atom_;
    118   Atom large_selection_atom_;
    119   Atom selection_string_atom_;
    120   Atom targets_atom_;
    121   Atom timestamp_atom_;
    122   Atom utf8_string_atom_;
    123 
    124   // The set of X selections owned by |clipboard_window_| (can be Primary or
    125   // Clipboard or both).
    126   std::set<Atom> selections_owned_;
    127 
    128   // Clipboard content to return to other applications when |clipboard_window_|
    129   // owns a selection.
    130   std::string data_;
    131 
    132   // Stores the property to use for large transfers, or None if a large
    133   // transfer is not currently in-progress.
    134   Atom large_selection_property_;
    135 
    136   // Remembers the start time of selection processing, and is set to null when
    137   // processing is complete. This is used to decide whether to begin processing
    138   // a new selection or continue with the current selection.
    139   base::TimeTicks get_selections_time_;
    140 
    141   // |callback| argument supplied to Init().
    142   ClipboardChangedCallback callback_;
    143 
    144   DISALLOW_COPY_AND_ASSIGN(XServerClipboard);
    145 };
    146 
    147 }  // namespace remoting
    148 
    149 #endif  // REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_
    150