some fixes for motif clipboard. still not handling incremental
transfer through root window property because not sure of the protocol.
This commit is contained in:
parent
c6ecc79c0d
commit
6fc6805a06
|
@ -29,6 +29,7 @@ CXWindowsClipboard::CXWindowsClipboard(Display* display,
|
||||||
m_atomTargets = XInternAtom(m_display, "TARGETS", False);
|
m_atomTargets = XInternAtom(m_display, "TARGETS", False);
|
||||||
m_atomMultiple = XInternAtom(m_display, "MULTIPLE", False);
|
m_atomMultiple = XInternAtom(m_display, "MULTIPLE", False);
|
||||||
m_atomTimestamp = XInternAtom(m_display, "TIMESTAMP", False);
|
m_atomTimestamp = XInternAtom(m_display, "TIMESTAMP", False);
|
||||||
|
m_atomInteger = XInternAtom(m_display, "INTEGER", False);
|
||||||
m_atomAtomPair = XInternAtom(m_display, "ATOM_PAIR", False);
|
m_atomAtomPair = XInternAtom(m_display, "ATOM_PAIR", False);
|
||||||
m_atomData = XInternAtom(m_display, "CLIP_TEMPORARY", False);
|
m_atomData = XInternAtom(m_display, "CLIP_TEMPORARY", False);
|
||||||
m_atomINCR = XInternAtom(m_display, "INCR", False);
|
m_atomINCR = XInternAtom(m_display, "INCR", False);
|
||||||
|
@ -512,11 +513,7 @@ CXWindowsClipboard::icccmFillCache()
|
||||||
Atom actualTarget;
|
Atom actualTarget;
|
||||||
CString targetData;
|
CString targetData;
|
||||||
if (!icccmGetSelection(target, &actualTarget, &targetData)) {
|
if (!icccmGetSelection(target, &actualTarget, &targetData)) {
|
||||||
log((CLOG_DEBUG1 " no data for target", target));
|
log((CLOG_DEBUG1 " no data for target %d", target));
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (actualTarget != target) {
|
|
||||||
log((CLOG_DEBUG1 " expeted (%d) and actual (%d) targets differ", target, actualTarget));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,7 +521,7 @@ CXWindowsClipboard::icccmFillCache()
|
||||||
IClipboard::EFormat format = converter->getFormat();
|
IClipboard::EFormat format = converter->getFormat();
|
||||||
m_data[format] = converter->toIClipboard(targetData);
|
m_data[format] = converter->toIClipboard(targetData);
|
||||||
m_added[format] = true;
|
m_added[format] = true;
|
||||||
log((CLOG_DEBUG " added format %d for target %d", converter->getFormat(), target));
|
log((CLOG_DEBUG " added format %d for target %d", format, target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +553,7 @@ CXWindowsClipboard::icccmGetTime() const
|
||||||
Atom actualTarget;
|
Atom actualTarget;
|
||||||
CString data;
|
CString data;
|
||||||
if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) &&
|
if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) &&
|
||||||
actualTarget == m_atomTimestamp) {
|
actualTarget == m_atomInteger) {
|
||||||
Time time = *reinterpret_cast<const Time*>(data.data());
|
Time time = *reinterpret_cast<const Time*>(data.data());
|
||||||
log((CLOG_DEBUG1 "got ICCCM time %d", time));
|
log((CLOG_DEBUG1 "got ICCCM time %d", time));
|
||||||
return time;
|
return time;
|
||||||
|
@ -632,9 +629,6 @@ CXWindowsClipboard::motifOwnsClipboard() const
|
||||||
&data, &target, &format, False)) {
|
&data, &target, &format, False)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (target != m_atomMotifClipHeader) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the owner window against the current clipboard owner
|
// check the owner window against the current clipboard owner
|
||||||
const CMotifClipHeader* header =
|
const CMotifClipHeader* header =
|
||||||
|
@ -664,9 +658,6 @@ CXWindowsClipboard::motifFillCache()
|
||||||
&data, &target, &format, False)) {
|
&data, &target, &format, False)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (target != m_atomMotifClipHeader) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that the header is okay
|
// check that the header is okay
|
||||||
const CMotifClipHeader* header =
|
const CMotifClipHeader* header =
|
||||||
|
@ -687,24 +678,27 @@ CXWindowsClipboard::motifFillCache()
|
||||||
&target, &format, False)) {
|
&target, &format, False)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (target != atomItem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that the item is okay
|
// check that the item is okay
|
||||||
const CMotifClipItem* item =
|
const CMotifClipItem* item =
|
||||||
reinterpret_cast<const CMotifClipItem*>(data.data());
|
reinterpret_cast<const CMotifClipItem*>(data.data());
|
||||||
if (data.size() < sizeof(CMotifClipItem) ||
|
if (data.size() < sizeof(CMotifClipItem) ||
|
||||||
item->m_id != kMotifClipItem ||
|
item->m_id != kMotifClipItem ||
|
||||||
item->m_numFormats < 1) {
|
item->m_numFormats - item->m_numDeletedFormats < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// format list is after static item structure elements
|
||||||
|
const SInt32 numFormats = item->m_numFormats - item->m_numDeletedFormats;
|
||||||
|
const SInt32* formats = reinterpret_cast<const SInt32*>(item->m_size +
|
||||||
|
reinterpret_cast<const char*>(data.data()));
|
||||||
|
|
||||||
// get the available formats
|
// get the available formats
|
||||||
std::vector<CMotifClipFormat> motifFormats;
|
typedef std::map<Atom, CString> CMotifFormatMap;
|
||||||
for (SInt32 i = 0; i < item->m_numFormats; ++i) {
|
CMotifFormatMap motifFormats;
|
||||||
|
for (SInt32 i = 0; i < numFormats; ++i) {
|
||||||
// get Motif format property from the root window
|
// get Motif format property from the root window
|
||||||
sprintf(name, "_MOTIF_CLIP_ITEM_%d", item->m_formats[i]);
|
sprintf(name, "_MOTIF_CLIP_ITEM_%d", formats[i]);
|
||||||
Atom atomFormat = XInternAtom(m_display, name, False);
|
Atom atomFormat = XInternAtom(m_display, name, False);
|
||||||
CString data;
|
CString data;
|
||||||
if (!CXWindowsUtil::getWindowProperty(m_display, root,
|
if (!CXWindowsUtil::getWindowProperty(m_display, root,
|
||||||
|
@ -712,9 +706,6 @@ CXWindowsClipboard::motifFillCache()
|
||||||
&target, &format, False)) {
|
&target, &format, False)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (target != atomFormat) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that the format is okay
|
// check that the format is okay
|
||||||
const CMotifClipFormat* motifFormat =
|
const CMotifClipFormat* motifFormat =
|
||||||
|
@ -722,21 +713,18 @@ CXWindowsClipboard::motifFillCache()
|
||||||
if (data.size() < sizeof(CMotifClipFormat) ||
|
if (data.size() < sizeof(CMotifClipFormat) ||
|
||||||
motifFormat->m_id != kMotifClipFormat ||
|
motifFormat->m_id != kMotifClipFormat ||
|
||||||
motifFormat->m_length < 0 ||
|
motifFormat->m_length < 0 ||
|
||||||
motifFormat->m_type == None) {
|
motifFormat->m_type == None ||
|
||||||
|
motifFormat->m_deleted != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save it
|
// save it
|
||||||
motifFormats.push_back(*motifFormat);
|
motifFormats.insert(std::make_pair(motifFormat->m_type, data));
|
||||||
}
|
}
|
||||||
const UInt32 numMotifFormats = motifFormats.size();
|
const UInt32 numMotifFormats = motifFormats.size();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// try each converter in order (because they're in order of
|
// try each converter in order (because they're in order of
|
||||||
// preference).
|
// preference).
|
||||||
const Atom* targets = reinterpret_cast<const Atom*>(data.data());
|
|
||||||
const UInt32 numTargets = data.size() / sizeof(Atom);
|
|
||||||
for (ConverterList::const_iterator index = m_converters.begin();
|
for (ConverterList::const_iterator index = m_converters.begin();
|
||||||
index != m_converters.end(); ++index) {
|
index != m_converters.end(); ++index) {
|
||||||
IXWindowsClipboardConverter* converter = *index;
|
IXWindowsClipboardConverter* converter = *index;
|
||||||
|
@ -747,48 +735,63 @@ CXWindowsClipboard::motifFillCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if atom is in target list
|
// see if atom is in target list
|
||||||
UInt32 i;
|
CMotifFormatMap::const_iterator index =
|
||||||
Atom target = None;
|
motifFormats.find(converter->getAtom());
|
||||||
for (i = 0; i < numMotifFormats; ++i) {
|
if (index == motifFormats.end()) {
|
||||||
if (converter->getAtom() == motifFormats[i].m_type) {
|
|
||||||
target = motifFormats[i].m_type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (target == None) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get format
|
||||||
|
const CMotifClipFormat* motifFormat =
|
||||||
|
reinterpret_cast<const CMotifClipFormat*>(
|
||||||
|
index->second.data());
|
||||||
|
const Atom target = motifFormat->m_type;
|
||||||
|
|
||||||
// get the data (finally)
|
// get the data (finally)
|
||||||
SInt32 length = motifFormats[i].m_length;
|
Atom actualTarget;
|
||||||
sprintf(name, "_MOTIF_CLIP_ITEM_%d", motifFormats[i].m_data);
|
|
||||||
Atom atomData = XInternAtom(m_display, name, False), atomTarget;
|
|
||||||
CString targetData;
|
CString targetData;
|
||||||
if (!CXWindowsUtil::getWindowProperty(m_display, root,
|
if (!motifGetSelection(motifFormat, &actualTarget, &targetData)) {
|
||||||
atomData, &targetData,
|
log((CLOG_DEBUG1 " no data for target %d", target));
|
||||||
&atomTarget, &format, False)) {
|
|
||||||
log((CLOG_DEBUG1 " no data for target", target));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (atomTarget != atomData) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// truncate data to length specified in the format
|
|
||||||
targetData.erase(length);
|
|
||||||
|
|
||||||
// add to clipboard and note we've done it
|
// add to clipboard and note we've done it
|
||||||
IClipboard::EFormat format = converter->getFormat();
|
IClipboard::EFormat format = converter->getFormat();
|
||||||
m_data[format] = converter->toIClipboard(targetData);
|
m_data[format] = converter->toIClipboard(targetData);
|
||||||
m_added[format] = true;
|
m_added[format] = true;
|
||||||
log((CLOG_DEBUG " added format %d for target %d", converter->getFormat(), target));
|
log((CLOG_DEBUG " added format %d for target %d", format, target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CXWindowsClipboard::motifGetSelection(const CMotifClipFormat* format,
|
||||||
|
Atom* actualTarget, CString* data) const
|
||||||
|
{
|
||||||
|
// if the current clipboard owner and the owner indicated by the
|
||||||
|
// motif clip header are the same then transfer via a property on
|
||||||
|
// the root window, otherwise transfer as a normal ICCCM client.
|
||||||
|
if (!motifOwnsClipboard()) {
|
||||||
|
return icccmGetSelection(format->m_type, actualTarget, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// use motif way
|
||||||
|
// FIXME -- this isn't right. it'll only work if the data is
|
||||||
|
// already stored on the root window and only if it fits in a
|
||||||
|
// property. motif has some scheme for transferring part by
|
||||||
|
// part that i don't know.
|
||||||
|
char name[18 + 20];
|
||||||
|
sprintf(name, "_MOTIF_CLIP_ITEM_%d", format->m_data);
|
||||||
|
Atom target = XInternAtom(m_display, name, False);
|
||||||
|
Window root = RootWindow(m_display, DefaultScreen(m_display));
|
||||||
|
return CXWindowsUtil::getWindowProperty(m_display, root,
|
||||||
|
target, data,
|
||||||
|
actualTarget, NULL, False);
|
||||||
|
}
|
||||||
|
|
||||||
IClipboard::Time
|
IClipboard::Time
|
||||||
CXWindowsClipboard::motifGetTime() const
|
CXWindowsClipboard::motifGetTime() const
|
||||||
{
|
{
|
||||||
// FIXME -- does Motif report this?
|
// FIXME -- where does Motif report this?
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1165,7 +1168,7 @@ CXWindowsClipboard::getTimestampData(CString& data, int* format) const
|
||||||
checkCache();
|
checkCache();
|
||||||
data.append(reinterpret_cast<const char*>(&m_timeOwned), 4);
|
data.append(reinterpret_cast<const char*>(&m_timeOwned), 4);
|
||||||
*format = 32;
|
*format = 32;
|
||||||
return m_atomTimestamp;
|
return m_atomInteger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,20 +89,6 @@ private:
|
||||||
void fillCache() const;
|
void fillCache() const;
|
||||||
void doFillCache();
|
void doFillCache();
|
||||||
|
|
||||||
// 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;
|
|
||||||
Time motifGetTime() const;
|
|
||||||
void motifFillCache();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// helper classes
|
// helper classes
|
||||||
//
|
//
|
||||||
|
@ -160,17 +146,17 @@ private:
|
||||||
SInt32 m_pad3[3];
|
SInt32 m_pad3[3];
|
||||||
Window m_selectionOwner;
|
Window m_selectionOwner;
|
||||||
SInt32 m_pad4[2];
|
SInt32 m_pad4[2];
|
||||||
SInt32 m_items[1]; // m_numItems items
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Motif clip item structure
|
// Motif clip item structure
|
||||||
class CMotifClipItem {
|
class CMotifClipItem {
|
||||||
public:
|
public:
|
||||||
SInt32 m_id; // kMotifClipItem
|
SInt32 m_id; // kMotifClipItem
|
||||||
SInt32 m_pad1[6];
|
SInt32 m_pad1[5];
|
||||||
|
SInt32 m_size;
|
||||||
SInt32 m_numFormats;
|
SInt32 m_numFormats;
|
||||||
SInt32 m_pad2[7];
|
SInt32 m_numDeletedFormats;
|
||||||
SInt32 m_formats[1]; // m_numFormats formats
|
SInt32 m_pad2[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Motif clip format structure
|
// Motif clip format structure
|
||||||
|
@ -181,7 +167,9 @@ private:
|
||||||
SInt32 m_length;
|
SInt32 m_length;
|
||||||
SInt32 m_data;
|
SInt32 m_data;
|
||||||
Atom m_type;
|
Atom m_type;
|
||||||
SInt32 m_pad2[6];
|
SInt32 m_pad2[1];
|
||||||
|
int m_deleted;
|
||||||
|
SInt32 m_pad3[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
// stores data needed to respond to a selection request
|
// stores data needed to respond to a selection request
|
||||||
|
@ -216,6 +204,21 @@ private:
|
||||||
typedef std::map<Window, CReplyList> CReplyMap;
|
typedef std::map<Window, CReplyList> CReplyMap;
|
||||||
typedef std::map<Window, long> CReplyEventMask;
|
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
|
// reply methods
|
||||||
bool insertMultipleReply(Window, ::Time, Atom);
|
bool insertMultipleReply(Window, ::Time, Atom);
|
||||||
void insertReply(CReply*);
|
void insertReply(CReply*);
|
||||||
|
@ -267,6 +270,7 @@ private:
|
||||||
Atom m_atomTargets;
|
Atom m_atomTargets;
|
||||||
Atom m_atomMultiple;
|
Atom m_atomMultiple;
|
||||||
Atom m_atomTimestamp;
|
Atom m_atomTimestamp;
|
||||||
|
Atom m_atomInteger;
|
||||||
Atom m_atomAtomPair;
|
Atom m_atomAtomPair;
|
||||||
Atom m_atomData;
|
Atom m_atomData;
|
||||||
Atom m_atomINCR;
|
Atom m_atomINCR;
|
||||||
|
|
Loading…
Reference in New Issue