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:
crs 2002-07-24 17:07:52 +00:00
parent c6ecc79c0d
commit 6fc6805a06
2 changed files with 81 additions and 74 deletions

View File

@ -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;
@ -626,15 +623,12 @@ CXWindowsClipboard::motifOwnsClipboard() const
Atom target; Atom target;
SInt32 format; SInt32 format;
CString data; CString data;
Window root = RootWindow(m_display, DefaultScreen(m_display)); Window root = RootWindow(m_display, DefaultScreen(m_display));
if (!CXWindowsUtil::getWindowProperty(m_display, root, if (!CXWindowsUtil::getWindowProperty(m_display, root,
m_atomMotifClipHeader, m_atomMotifClipHeader,
&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;
} }

View File

@ -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;