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;