From 6fc6805a06370077a52897ef7aa52b956e558253 Mon Sep 17 00:00:00 2001 From: crs Date: Wed, 24 Jul 2002 17:07:52 +0000 Subject: [PATCH] some fixes for motif clipboard. still not handling incremental transfer through root window property because not sure of the protocol. --- platform/CXWindowsClipboard.cpp | 113 ++++++++++++++++---------------- platform/CXWindowsClipboard.h | 42 ++++++------ 2 files changed, 81 insertions(+), 74 deletions(-) diff --git a/platform/CXWindowsClipboard.cpp b/platform/CXWindowsClipboard.cpp index 8ba736b0..1168247a 100644 --- a/platform/CXWindowsClipboard.cpp +++ b/platform/CXWindowsClipboard.cpp @@ -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(data.data()); log((CLOG_DEBUG1 "got ICCCM time %d", time)); return time; @@ -626,15 +623,12 @@ CXWindowsClipboard::motifOwnsClipboard() const Atom target; SInt32 format; CString data; - Window root = RootWindow(m_display, DefaultScreen(m_display)); + Window root = RootWindow(m_display, DefaultScreen(m_display)); if (!CXWindowsUtil::getWindowProperty(m_display, root, m_atomMotifClipHeader, &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(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(item->m_size + + reinterpret_cast(data.data())); + // get the available formats - std::vector motifFormats; - for (SInt32 i = 0; i < item->m_numFormats; ++i) { + typedef std::map 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(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( + 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(&m_timeOwned), 4); *format = 32; - return m_atomTimestamp; + return m_atomInteger; } diff --git a/platform/CXWindowsClipboard.h b/platform/CXWindowsClipboard.h index cbd2898e..7c1a7d6e 100644 --- a/platform/CXWindowsClipboard.h +++ b/platform/CXWindowsClipboard.h @@ -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 CReplyMap; typedef std::map 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;