From cec075cb604dce1f6f7ec3797a0285f2fc692c02 Mon Sep 17 00:00:00 2001 From: crs Date: Thu, 20 Jun 2002 16:27:49 +0000 Subject: [PATCH] fixed bug introduced by previous checkin. calling XCheckIfEvent() multiple times is *not* the same as calling XIfEvent() because the former will re-encounter events that it didn't process previously. to make things simple it now pulls events off the queue and saves them if not processed for selection transfer and puts them back afterwards. --- platform/CXWindowsClipboard.cpp | 47 ++++++++++++++------------------- platform/CXWindowsClipboard.h | 6 +---- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/platform/CXWindowsClipboard.cpp b/platform/CXWindowsClipboard.cpp index 1d0fbb4d..f894789b 100644 --- a/platform/CXWindowsClipboard.cpp +++ b/platform/CXWindowsClipboard.cpp @@ -3,6 +3,7 @@ #include "CThread.h" #include "CLog.h" #include "CStopwatch.h" +#include "stdvector.h" #include #include @@ -1169,7 +1170,7 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display, // a timeout expires. we use a timeout so we don't get locked up // by badly behaved selection owners. XEvent xevent; - SInt32 lastPending = 0; + std::vector events; CStopwatch timeout(true); static const double s_timeout = 0.25; // FIXME -- is this too short? while (!m_done && !m_failed) { @@ -1179,17 +1180,14 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display, break; } - // get how many events are pending now - SInt32 pending = XPending(display); - - // process events if there are more otherwise sleep - if (pending > lastPending) { - lastPending = pending; - while (!m_done && !m_failed && - XCheckIfEvent(display, &xevent, - &CXWindowsClipboard::CICCCMGetClipboard::eventPredicate, - reinterpret_cast(this))) { - lastPending = XPending(display); + // process events if any otherwise sleep + if (XPending(display) > 0) { + while (!m_done && !m_failed && XPending(display) > 0) { + XNextEvent(display, &xevent); + if (!processEvent(display, &xevent)) { + // not processed so save it + events.push_back(xevent); + } } } else { @@ -1197,6 +1195,11 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display, } } + // put unprocessed events back + for (UInt32 i = events.size(); i > 0; --i) { + XPutBackEvent(display, &events[i - 1]); + } + // restore mask XSelectInput(display, m_requestor, attr.your_event_mask); @@ -1206,7 +1209,7 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display, } bool -CXWindowsClipboard::CICCCMGetClipboard::doEventPredicate( +CXWindowsClipboard::CICCCMGetClipboard::processEvent( Display* display, XEvent* xevent) { // process event @@ -1244,7 +1247,8 @@ CXWindowsClipboard::CICCCMGetClipboard::doEventPredicate( xevent->xproperty.atom == m_property && xevent->xproperty.state == PropertyNewValue) { if (!m_reading) { - return false; + // we haven't gotten the SelectionNotify yet + return true; } break; } @@ -1323,20 +1327,9 @@ log((CLOG_INFO " INCR secondary chunk")); // FIXME m_done = true; } - // say we're not interested in this event if the conversion is - // incremental. that'll cause this method to be called again - // when there's more data. we finally finish the incremental - // copy when we read a 0 byte property. + // this event has been processed logc(!m_incr, (CLOG_DEBUG1 " got data, %d bytes", m_data->size())); - return !m_incr; -} - -Bool -CXWindowsClipboard::CICCCMGetClipboard::eventPredicate( - Display* display, XEvent* xevent, XPointer arg) -{ - CICCCMGetClipboard* self = reinterpret_cast(arg); - return self->doEventPredicate(display, xevent) ? True : False; + return true; } diff --git a/platform/CXWindowsClipboard.h b/platform/CXWindowsClipboard.h index 82d695e5..940ab71c 100644 --- a/platform/CXWindowsClipboard.h +++ b/platform/CXWindowsClipboard.h @@ -107,11 +107,7 @@ private: Atom* actualTarget, CString* data); private: - bool doEventPredicate(Display* display, - XEvent* event); - static Bool eventPredicate(Display* display, - XEvent* event, - XPointer arg); + bool processEvent(Display* display, XEvent* event); private: Window m_requestor;