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_atomMultiple = XInternAtom(m_display, "MULTIPLE", False);
|
||||
m_atomTimestamp = XInternAtom(m_display, "TIMESTAMP", False);
|
||||
m_atomInteger = XInternAtom(m_display, "INTEGER", False);
|
||||
m_atomAtomPair = XInternAtom(m_display, "ATOM_PAIR", False);
|
||||
m_atomData = XInternAtom(m_display, "CLIP_TEMPORARY", False);
|
||||
m_atomINCR = XInternAtom(m_display, "INCR", False);
|
||||
|
@ -512,11 +513,7 @@ CXWindowsClipboard::icccmFillCache()
|
|||
Atom actualTarget;
|
||||
CString targetData;
|
||||
if (!icccmGetSelection(target, &actualTarget, &targetData)) {
|
||||
log((CLOG_DEBUG1 " no data for target", target));
|
||||
continue;
|
||||
}
|
||||
if (actualTarget != target) {
|
||||
log((CLOG_DEBUG1 " expeted (%d) and actual (%d) targets differ", target, actualTarget));
|
||||
log((CLOG_DEBUG1 " no data for target %d", target));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -524,7 +521,7 @@ CXWindowsClipboard::icccmFillCache()
|
|||
IClipboard::EFormat format = converter->getFormat();
|
||||
m_data[format] = converter->toIClipboard(targetData);
|
||||
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;
|
||||
CString data;
|
||||
if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) &&
|
||||
actualTarget == m_atomTimestamp) {
|
||||
actualTarget == m_atomInteger) {
|
||||
Time time = *reinterpret_cast<const Time*>(data.data());
|
||||
log((CLOG_DEBUG1 "got ICCCM time %d", time));
|
||||
return time;
|
||||
|
@ -632,9 +629,6 @@ CXWindowsClipboard::motifOwnsClipboard() const
|
|||
&data, &target, &format, False)) {
|
||||
return false;
|
||||
}
|
||||
if (target != m_atomMotifClipHeader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the owner window against the current clipboard owner
|
||||
const CMotifClipHeader* header =
|
||||
|
@ -664,9 +658,6 @@ CXWindowsClipboard::motifFillCache()
|
|||
&data, &target, &format, False)) {
|
||||
return;
|
||||
}
|
||||
if (target != m_atomMotifClipHeader) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check that the header is okay
|
||||
const CMotifClipHeader* header =
|
||||
|
@ -687,24 +678,27 @@ CXWindowsClipboard::motifFillCache()
|
|||
&target, &format, False)) {
|
||||
return;
|
||||
}
|
||||
if (target != atomItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check that the item is okay
|
||||
const CMotifClipItem* item =
|
||||
reinterpret_cast<const CMotifClipItem*>(data.data());
|
||||
if (data.size() < sizeof(CMotifClipItem) ||
|
||||
item->m_id != kMotifClipItem ||
|
||||
item->m_numFormats < 1) {
|
||||
item->m_numFormats - item->m_numDeletedFormats < 1) {
|
||||
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
|
||||
std::vector<CMotifClipFormat> motifFormats;
|
||||
for (SInt32 i = 0; i < item->m_numFormats; ++i) {
|
||||
typedef std::map<Atom, CString> CMotifFormatMap;
|
||||
CMotifFormatMap motifFormats;
|
||||
for (SInt32 i = 0; i < numFormats; ++i) {
|
||||
// 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);
|
||||
CString data;
|
||||
if (!CXWindowsUtil::getWindowProperty(m_display, root,
|
||||
|
@ -712,9 +706,6 @@ CXWindowsClipboard::motifFillCache()
|
|||
&target, &format, False)) {
|
||||
continue;
|
||||
}
|
||||
if (target != atomFormat) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check that the format is okay
|
||||
const CMotifClipFormat* motifFormat =
|
||||
|
@ -722,21 +713,18 @@ CXWindowsClipboard::motifFillCache()
|
|||
if (data.size() < sizeof(CMotifClipFormat) ||
|
||||
motifFormat->m_id != kMotifClipFormat ||
|
||||
motifFormat->m_length < 0 ||
|
||||
motifFormat->m_type == None) {
|
||||
motifFormat->m_type == None ||
|
||||
motifFormat->m_deleted != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// save it
|
||||
motifFormats.push_back(*motifFormat);
|
||||
motifFormats.insert(std::make_pair(motifFormat->m_type, data));
|
||||
}
|
||||
const UInt32 numMotifFormats = motifFormats.size();
|
||||
|
||||
|
||||
|
||||
// try each converter in order (because they're in order of
|
||||
// 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();
|
||||
index != m_converters.end(); ++index) {
|
||||
IXWindowsClipboardConverter* converter = *index;
|
||||
|
@ -747,48 +735,63 @@ CXWindowsClipboard::motifFillCache()
|
|||
}
|
||||
|
||||
// see if atom is in target list
|
||||
UInt32 i;
|
||||
Atom target = None;
|
||||
for (i = 0; i < numMotifFormats; ++i) {
|
||||
if (converter->getAtom() == motifFormats[i].m_type) {
|
||||
target = motifFormats[i].m_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target == None) {
|
||||
CMotifFormatMap::const_iterator index =
|
||||
motifFormats.find(converter->getAtom());
|
||||
if (index == motifFormats.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get format
|
||||
const CMotifClipFormat* motifFormat =
|
||||
reinterpret_cast<const CMotifClipFormat*>(
|
||||
index->second.data());
|
||||
const Atom target = motifFormat->m_type;
|
||||
|
||||
// get the data (finally)
|
||||
SInt32 length = motifFormats[i].m_length;
|
||||
sprintf(name, "_MOTIF_CLIP_ITEM_%d", motifFormats[i].m_data);
|
||||
Atom atomData = XInternAtom(m_display, name, False), atomTarget;
|
||||
Atom actualTarget;
|
||||
CString targetData;
|
||||
if (!CXWindowsUtil::getWindowProperty(m_display, root,
|
||||
atomData, &targetData,
|
||||
&atomTarget, &format, False)) {
|
||||
log((CLOG_DEBUG1 " no data for target", target));
|
||||
if (!motifGetSelection(motifFormat, &actualTarget, &targetData)) {
|
||||
log((CLOG_DEBUG1 " no data for target %d", target));
|
||||
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
|
||||
IClipboard::EFormat format = converter->getFormat();
|
||||
m_data[format] = converter->toIClipboard(targetData);
|
||||
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
|
||||
CXWindowsClipboard::motifGetTime() const
|
||||
{
|
||||
// FIXME -- does Motif report this?
|
||||
// FIXME -- where does Motif report this?
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1165,7 +1168,7 @@ CXWindowsClipboard::getTimestampData(CString& data, int* format) const
|
|||
checkCache();
|
||||
data.append(reinterpret_cast<const char*>(&m_timeOwned), 4);
|
||||
*format = 32;
|
||||
return m_atomTimestamp;
|
||||
return m_atomInteger;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -89,20 +89,6 @@ private:
|
|||
void fillCache() const;
|
||||
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
|
||||
//
|
||||
|
@ -160,17 +146,17 @@ private:
|
|||
SInt32 m_pad3[3];
|
||||
Window m_selectionOwner;
|
||||
SInt32 m_pad4[2];
|
||||
SInt32 m_items[1]; // m_numItems items
|
||||
};
|
||||
|
||||
// Motif clip item structure
|
||||
class CMotifClipItem {
|
||||
public:
|
||||
SInt32 m_id; // kMotifClipItem
|
||||
SInt32 m_pad1[6];
|
||||
SInt32 m_pad1[5];
|
||||
SInt32 m_size;
|
||||
SInt32 m_numFormats;
|
||||
SInt32 m_pad2[7];
|
||||
SInt32 m_formats[1]; // m_numFormats formats
|
||||
SInt32 m_numDeletedFormats;
|
||||
SInt32 m_pad2[6];
|
||||
};
|
||||
|
||||
// Motif clip format structure
|
||||
|
@ -181,7 +167,9 @@ private:
|
|||
SInt32 m_length;
|
||||
SInt32 m_data;
|
||||
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
|
||||
|
@ -216,6 +204,21 @@ private:
|
|||
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*);
|
||||
|
@ -267,6 +270,7 @@ private:
|
|||
Atom m_atomTargets;
|
||||
Atom m_atomMultiple;
|
||||
Atom m_atomTimestamp;
|
||||
Atom m_atomInteger;
|
||||
Atom m_atomAtomPair;
|
||||
Atom m_atomData;
|
||||
Atom m_atomINCR;
|
||||
|
|
Loading…
Reference in New Issue