// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Don't include this file from any .h files because it pulls in some X headers. #ifndef REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_ #define REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_ #include <X11/Xatom.h> #include <X11/Xlib.h> #include <set> #include <string> #include "base/basictypes.h" #include "base/callback_forward.h" #include "base/timer/timer.h" namespace remoting { // A class to allow manipulation of the X clipboard, using only X API calls. // This class is not thread-safe, so all its methods must be called on the // application's main event-processing thread. class XServerClipboard { public: // Called when new clipboard data has been received from the owner of the X // selection (primary or clipboard). // |mime_type| is the MIME type associated with the data. This will be one of // the types listed in remoting/base/constants.h. // |data| is the clipboard data from the associated X event, encoded with the // specified MIME-type. typedef base::Callback<void(const std::string& mime_type, const std::string& data)> ClipboardChangedCallback; XServerClipboard(); ~XServerClipboard(); // Start monitoring |display|'s selections, and invoke |callback| whenever // their content changes. The caller must ensure |display| is still valid // whenever any other methods are called on this object. void Init(Display* display, const ClipboardChangedCallback& callback); // Copy data to the X Clipboard. This acquires ownership of the // PRIMARY and CLIPBOARD selections. void SetClipboard(const std::string& mime_type, const std::string& data); // Process |event| if it is an X selection notification. The caller should // invoke this for every event it receives from |display|. void ProcessXEvent(XEvent* event); private: // Handlers called by ProcessXEvent() for each event type. void OnSetSelectionOwnerNotify(Atom selection, Time timestamp); void OnPropertyNotify(XEvent* event); void OnSelectionNotify(XEvent* event); void OnSelectionRequest(XEvent* event); void OnSelectionClear(XEvent* event); // Used by OnSelectionRequest() to respond to requests for details of our // clipboard content. This is done by changing the property |property| of the // |requestor| window (these values come from the XSelectionRequestEvent). // |target| must be a string type (STRING or UTF8_STRING). void SendTargetsResponse(Window requestor, Atom property); void SendTimestampResponse(Window requestor, Atom property); void SendStringResponse(Window requestor, Atom property, Atom target); // Called by OnSelectionNotify() when the selection owner has replied to a // request for information about a selection. // |event| is the raw X event from the notification. // |type|, |format| etc are the results from XGetWindowProperty(), or 0 if // there is no associated data. void HandleSelectionNotify(XSelectionEvent* event, Atom type, int format, int item_count, void* data); // These methods return true if selection processing is complete, false // otherwise. They are called from HandleSelectionNotify(), and take the same // arguments. bool HandleSelectionTargetsEvent(XSelectionEvent* event, int format, int item_count, void* data); bool HandleSelectionStringEvent(XSelectionEvent* event, int format, int item_count, void* data); // Notify the registered callback of new clipboard text. void NotifyClipboardText(const std::string& text); // These methods trigger the X server or selection owner to send back an // event containing the requested information. void RequestSelectionTargets(Atom selection); void RequestSelectionString(Atom selection, Atom target); // Assert ownership of the specified |selection|. void AssertSelectionOwnership(Atom selection); bool IsSelectionOwner(Atom selection); // Stores the Display* supplied to Init(). Display* display_; // Window through which clipboard events are received, or BadValue if the // window could not be created. Window clipboard_window_; // The event base returned by XFixesQueryExtension(). If XFixes is // unavailable, the clipboard window will not be created, and no // event-processing will take place. int xfixes_event_base_; // Cached atoms for various strings, initialized during Init(). Atom clipboard_atom_; Atom large_selection_atom_; Atom selection_string_atom_; Atom targets_atom_; Atom timestamp_atom_; Atom utf8_string_atom_; // The set of X selections owned by |clipboard_window_| (can be Primary or // Clipboard or both). std::set<Atom> selections_owned_; // Clipboard content to return to other applications when |clipboard_window_| // owns a selection. std::string data_; // Stores the property to use for large transfers, or None if a large // transfer is not currently in-progress. Atom large_selection_property_; // Remembers the start time of selection processing, and is set to null when // processing is complete. This is used to decide whether to begin processing // a new selection or continue with the current selection. base::TimeTicks get_selections_time_; // |callback| argument supplied to Init(). ClipboardChangedCallback callback_; DISALLOW_COPY_AND_ASSIGN(XServerClipboard); }; } // namespace remoting #endif // REMOTING_HOST_LINUX_X_SERVER_CLIPBOARD_H_