// 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_