2012-06-10 16:50:54 +00:00
|
|
|
/*
|
|
|
|
* synergy -- mouse and keyboard sharing utility
|
2012-09-04 02:09:56 +00:00
|
|
|
* Copyright (C) 2012 Bolton Software Ltd.
|
|
|
|
* Copyright (C) 2002 Chris Schoeneman
|
2012-06-10 16:50:54 +00:00
|
|
|
*
|
|
|
|
* This package is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* found in the file COPYING that should have accompanied this file.
|
|
|
|
*
|
|
|
|
* This package is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef CXWINDOWSCLIPBOARD_H
|
|
|
|
#define CXWINDOWSCLIPBOARD_H
|
|
|
|
|
|
|
|
#include "IClipboard.h"
|
|
|
|
#include "ClipboardTypes.h"
|
|
|
|
#include "stdmap.h"
|
|
|
|
#include "stdlist.h"
|
|
|
|
#include "stdvector.h"
|
|
|
|
#if X_DISPLAY_MISSING
|
|
|
|
# error X11 is required to build synergy
|
|
|
|
#else
|
|
|
|
# include <X11/Xlib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class IXWindowsClipboardConverter;
|
|
|
|
|
|
|
|
//! X11 clipboard implementation
|
|
|
|
class CXWindowsClipboard : public IClipboard {
|
|
|
|
public:
|
|
|
|
/*!
|
|
|
|
Use \c window as the window that owns or interacts with the
|
|
|
|
clipboard identified by \c id.
|
|
|
|
*/
|
|
|
|
CXWindowsClipboard(Display*, Window window, ClipboardID id);
|
|
|
|
virtual ~CXWindowsClipboard();
|
|
|
|
|
|
|
|
//! Notify clipboard was lost
|
|
|
|
/*!
|
|
|
|
Tells clipboard it lost ownership at the given time.
|
|
|
|
*/
|
|
|
|
void lost(Time);
|
|
|
|
|
|
|
|
//! Add clipboard request
|
|
|
|
/*!
|
|
|
|
Adds a selection request to the request list. If the given
|
|
|
|
owner window isn't this clipboard's window then this simply
|
|
|
|
sends a failure event to the requestor.
|
|
|
|
*/
|
|
|
|
void addRequest(Window owner,
|
|
|
|
Window requestor, Atom target,
|
|
|
|
::Time time, Atom property);
|
|
|
|
|
|
|
|
//! Process clipboard request
|
|
|
|
/*!
|
|
|
|
Continues processing a selection request. Returns true if the
|
|
|
|
request was handled, false if the request was unknown.
|
|
|
|
*/
|
|
|
|
bool processRequest(Window requestor,
|
|
|
|
::Time time, Atom property);
|
|
|
|
|
|
|
|
//! Cancel clipboard request
|
|
|
|
/*!
|
|
|
|
Terminate a selection request. Returns true iff the request
|
|
|
|
was known and handled.
|
|
|
|
*/
|
|
|
|
bool destroyRequest(Window requestor);
|
|
|
|
|
|
|
|
//! Get window
|
|
|
|
/*!
|
|
|
|
Returns the clipboard's window (passed the c'tor).
|
|
|
|
*/
|
|
|
|
Window getWindow() const;
|
|
|
|
|
|
|
|
//! Get selection atom
|
|
|
|
/*!
|
|
|
|
Returns the selection atom that identifies the clipboard to X11
|
|
|
|
(e.g. XA_PRIMARY).
|
|
|
|
*/
|
|
|
|
Atom getSelection() const;
|
|
|
|
|
|
|
|
// IClipboard overrides
|
|
|
|
virtual bool empty();
|
|
|
|
virtual void add(EFormat, const CString& data);
|
|
|
|
virtual bool open(Time) const;
|
|
|
|
virtual void close() const;
|
|
|
|
virtual Time getTime() const;
|
|
|
|
virtual bool has(EFormat) const;
|
|
|
|
virtual CString get(EFormat) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// remove all converters from our list
|
|
|
|
void clearConverters();
|
|
|
|
|
|
|
|
// get the converter for a clipboard format. returns NULL if no
|
|
|
|
// suitable converter. iff onlyIfNotAdded is true then also
|
|
|
|
// return NULL if a suitable converter was found but we already
|
|
|
|
// have data of the converter's clipboard format.
|
|
|
|
IXWindowsClipboardConverter*
|
|
|
|
getConverter(Atom target,
|
|
|
|
bool onlyIfNotAdded = false) const;
|
|
|
|
|
|
|
|
// convert target atom to clipboard format
|
|
|
|
EFormat getFormat(Atom target) const;
|
|
|
|
|
|
|
|
// add a non-MULTIPLE request. does not verify that the selection
|
|
|
|
// was owned at the given time. returns true if the conversion
|
|
|
|
// could be performed, false otherwise. in either case, the
|
|
|
|
// reply is inserted.
|
|
|
|
bool addSimpleRequest(
|
|
|
|
Window requestor, Atom target,
|
|
|
|
::Time time, Atom property);
|
|
|
|
|
|
|
|
// if not already checked then see if the cache is stale and, if so,
|
|
|
|
// clear it. this has the side effect of updating m_timeOwned.
|
|
|
|
void checkCache() const;
|
|
|
|
|
|
|
|
// clear the cache, resetting the cached flag and the added flag for
|
|
|
|
// each format.
|
|
|
|
void clearCache() const;
|
|
|
|
void doClearCache();
|
|
|
|
|
|
|
|
// cache all formats of the selection
|
|
|
|
void fillCache() const;
|
|
|
|
void doFillCache();
|
|
|
|
|
|
|
|
//
|
|
|
|
// helper classes
|
|
|
|
//
|
|
|
|
|
|
|
|
// read an ICCCM conforming selection
|
|
|
|
class CICCCMGetClipboard {
|
|
|
|
public:
|
|
|
|
CICCCMGetClipboard(Window requestor, Time time, Atom property);
|
|
|
|
~CICCCMGetClipboard();
|
|
|
|
|
|
|
|
// convert the given selection to the given type. returns
|
|
|
|
// true iff the conversion was successful or the conversion
|
|
|
|
// cannot be performed (in which case *actualTarget == None).
|
|
|
|
bool readClipboard(Display* display,
|
|
|
|
Atom selection, Atom target,
|
|
|
|
Atom* actualTarget, CString* data);
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool processEvent(Display* display, XEvent* event);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Window m_requestor;
|
|
|
|
Time m_time;
|
|
|
|
Atom m_property;
|
|
|
|
bool m_incr;
|
|
|
|
bool m_failed;
|
|
|
|
bool m_done;
|
|
|
|
|
|
|
|
// atoms needed for the protocol
|
|
|
|
Atom m_atomNone; // NONE, not None
|
|
|
|
Atom m_atomIncr;
|
|
|
|
|
|
|
|
// true iff we've received the selection notify
|
|
|
|
bool m_reading;
|
|
|
|
|
|
|
|
// the converted selection data
|
|
|
|
CString* m_data;
|
|
|
|
|
|
|
|
// the actual type of the data. if this is None then the
|
|
|
|
// selection owner cannot convert to the requested type.
|
|
|
|
Atom* m_actualTarget;
|
|
|
|
|
|
|
|
public:
|
|
|
|
// true iff the selection owner didn't follow ICCCM conventions
|
|
|
|
bool m_error;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Motif structure IDs
|
|
|
|
enum { kMotifClipFormat = 1, kMotifClipItem, kMotifClipHeader };
|
|
|
|
|
|
|
|
// _MOTIF_CLIP_HEADER structure
|
|
|
|
class CMotifClipHeader {
|
|
|
|
public:
|
|
|
|
SInt32 m_id; // kMotifClipHeader
|
|
|
|
SInt32 m_pad1[3];
|
|
|
|
SInt32 m_item;
|
|
|
|
SInt32 m_pad2[4];
|
|
|
|
SInt32 m_numItems;
|
|
|
|
SInt32 m_pad3[3];
|
|
|
|
SInt32 m_selectionOwner; // a Window
|
|
|
|
SInt32 m_pad4[2];
|
|
|
|
};
|
|
|
|
|
|
|
|
// Motif clip item structure
|
|
|
|
class CMotifClipItem {
|
|
|
|
public:
|
|
|
|
SInt32 m_id; // kMotifClipItem
|
|
|
|
SInt32 m_pad1[5];
|
|
|
|
SInt32 m_size;
|
|
|
|
SInt32 m_numFormats;
|
|
|
|
SInt32 m_numDeletedFormats;
|
|
|
|
SInt32 m_pad2[6];
|
|
|
|
};
|
|
|
|
|
|
|
|
// Motif clip format structure
|
|
|
|
class CMotifClipFormat {
|
|
|
|
public:
|
|
|
|
SInt32 m_id; // kMotifClipFormat
|
|
|
|
SInt32 m_pad1[6];
|
|
|
|
SInt32 m_length;
|
|
|
|
SInt32 m_data;
|
|
|
|
SInt32 m_type; // an Atom
|
|
|
|
SInt32 m_pad2[1];
|
|
|
|
SInt32 m_deleted;
|
|
|
|
SInt32 m_pad3[4];
|
|
|
|
};
|
|
|
|
|
|
|
|
// stores data needed to respond to a selection request
|
|
|
|
class CReply {
|
|
|
|
public:
|
|
|
|
CReply(Window, Atom target, ::Time);
|
|
|
|
CReply(Window, Atom target, ::Time, Atom property,
|
|
|
|
const CString& data, Atom type, int format);
|
|
|
|
|
|
|
|
public:
|
|
|
|
// information about the request
|
|
|
|
Window m_requestor;
|
|
|
|
Atom m_target;
|
|
|
|
::Time m_time;
|
|
|
|
Atom m_property;
|
|
|
|
|
|
|
|
// true iff we've sent the notification for this reply
|
|
|
|
bool m_replied;
|
|
|
|
|
|
|
|
// true iff the reply has sent its last message
|
|
|
|
bool m_done;
|
|
|
|
|
|
|
|
// the data to send and its type and format
|
|
|
|
CString m_data;
|
|
|
|
Atom m_type;
|
|
|
|
int m_format;
|
|
|
|
|
|
|
|
// index of next byte in m_data to send
|
|
|
|
UInt32 m_ptr;
|
|
|
|
};
|
|
|
|
typedef std::list<CReply*> CReplyList;
|
|
|
|
typedef std::map<Window, CReplyList> CReplyMap;
|
|
|
|
typedef std::map<Window, long> CReplyEventMask;
|
|
|
|
|
|
|
|
// ICCCM interoperability methods
|
|
|
|
void icccmFillCache();
|
|
|
|
bool icccmGetSelection(Atom target,
|
|
|
|
Atom* actualTarget, CString* data) const;
|
|
|
|
Time icccmGetTime() const;
|
|
|
|
|
|
|
|
// motif interoperability methods
|
|
|
|
bool motifLockClipboard() const;
|
|
|
|
void motifUnlockClipboard() const;
|
|
|
|
bool motifOwnsClipboard() const;
|
|
|
|
void motifFillCache();
|
|
|
|
bool motifGetSelection(const CMotifClipFormat*,
|
|
|
|
Atom* actualTarget, CString* data) const;
|
|
|
|
Time motifGetTime() const;
|
|
|
|
|
|
|
|
// reply methods
|
|
|
|
bool insertMultipleReply(Window, ::Time, Atom);
|
|
|
|
void insertReply(CReply*);
|
|
|
|
void pushReplies();
|
|
|
|
void pushReplies(CReplyMap::iterator&,
|
|
|
|
CReplyList&, CReplyList::iterator);
|
|
|
|
bool sendReply(CReply*);
|
|
|
|
void clearReplies();
|
|
|
|
void clearReplies(CReplyList&);
|
|
|
|
void sendNotify(Window requestor, Atom selection,
|
|
|
|
Atom target, Atom property, Time time);
|
|
|
|
bool wasOwnedAtTime(::Time) const;
|
|
|
|
|
|
|
|
// data conversion methods
|
|
|
|
Atom getTargetsData(CString&, int* format) const;
|
|
|
|
Atom getTimestampData(CString&, int* format) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef std::vector<IXWindowsClipboardConverter*> ConverterList;
|
|
|
|
|
|
|
|
Display* m_display;
|
|
|
|
Window m_window;
|
|
|
|
ClipboardID m_id;
|
|
|
|
Atom m_selection;
|
|
|
|
mutable bool m_open;
|
|
|
|
mutable Time m_time;
|
|
|
|
bool m_owner;
|
|
|
|
mutable Time m_timeOwned;
|
|
|
|
Time m_timeLost;
|
|
|
|
|
|
|
|
// true iff open and clipboard owned by a motif app
|
|
|
|
mutable bool m_motif;
|
|
|
|
|
|
|
|
// the added/cached clipboard data
|
|
|
|
mutable bool m_checkCache;
|
|
|
|
bool m_cached;
|
|
|
|
Time m_cacheTime;
|
|
|
|
bool m_added[kNumFormats];
|
|
|
|
CString m_data[kNumFormats];
|
|
|
|
|
|
|
|
// conversion request replies
|
|
|
|
CReplyMap m_replies;
|
|
|
|
CReplyEventMask m_eventMasks;
|
|
|
|
|
|
|
|
// clipboard format converters
|
|
|
|
ConverterList m_converters;
|
|
|
|
|
|
|
|
// atoms we'll need
|
|
|
|
Atom m_atomTargets;
|
|
|
|
Atom m_atomMultiple;
|
|
|
|
Atom m_atomTimestamp;
|
|
|
|
Atom m_atomInteger;
|
|
|
|
Atom m_atomAtom;
|
|
|
|
Atom m_atomAtomPair;
|
|
|
|
Atom m_atomData;
|
|
|
|
Atom m_atomINCR;
|
|
|
|
Atom m_atomMotifClipLock;
|
|
|
|
Atom m_atomMotifClipHeader;
|
|
|
|
Atom m_atomMotifClipAccess;
|
|
|
|
Atom m_atomGDKSelection;
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Clipboard format converter interface
|
|
|
|
/*!
|
|
|
|
This interface defines the methods common to all X11 clipboard format
|
|
|
|
converters.
|
|
|
|
*/
|
|
|
|
class IXWindowsClipboardConverter : public IInterface {
|
|
|
|
public:
|
|
|
|
//! @name accessors
|
|
|
|
//@{
|
|
|
|
|
|
|
|
//! Get clipboard format
|
|
|
|
/*!
|
|
|
|
Return the clipboard format this object converts from/to.
|
|
|
|
*/
|
|
|
|
virtual IClipboard::EFormat
|
|
|
|
getFormat() const = 0;
|
|
|
|
|
|
|
|
//! Get X11 format atom
|
|
|
|
/*!
|
|
|
|
Return the atom representing the X selection format that
|
|
|
|
this object converts from/to.
|
|
|
|
*/
|
|
|
|
virtual Atom getAtom() const = 0;
|
|
|
|
|
|
|
|
//! Get X11 property datum size
|
|
|
|
/*!
|
|
|
|
Return the size (in bits) of data elements returned by
|
|
|
|
toIClipboard().
|
|
|
|
*/
|
|
|
|
virtual int getDataSize() const = 0;
|
|
|
|
|
|
|
|
//! Convert from IClipboard format
|
|
|
|
/*!
|
|
|
|
Convert from the IClipboard format to the X selection format.
|
|
|
|
The input data must be in the IClipboard format returned by
|
|
|
|
getFormat(). The return data will be in the X selection
|
|
|
|
format returned by getAtom().
|
|
|
|
*/
|
|
|
|
virtual CString fromIClipboard(const CString&) const = 0;
|
|
|
|
|
|
|
|
//! Convert to IClipboard format
|
|
|
|
/*!
|
|
|
|
Convert from the X selection format to the IClipboard format
|
|
|
|
(i.e., the reverse of fromIClipboard()).
|
|
|
|
*/
|
|
|
|
virtual CString toIClipboard(const CString&) const = 0;
|
|
|
|
|
|
|
|
//@}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|