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