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.
This commit is contained in:
crs 2002-06-20 16:27:49 +00:00
parent 2423dc662d
commit cec075cb60
2 changed files with 21 additions and 32 deletions

View File

@ -3,6 +3,7 @@
#include "CThread.h" #include "CThread.h"
#include "CLog.h" #include "CLog.h"
#include "CStopwatch.h" #include "CStopwatch.h"
#include "stdvector.h"
#include <cstdio> #include <cstdio>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -1169,7 +1170,7 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display,
// a timeout expires. we use a timeout so we don't get locked up // a timeout expires. we use a timeout so we don't get locked up
// by badly behaved selection owners. // by badly behaved selection owners.
XEvent xevent; XEvent xevent;
SInt32 lastPending = 0; std::vector<XEvent> events;
CStopwatch timeout(true); CStopwatch timeout(true);
static const double s_timeout = 0.25; // FIXME -- is this too short? static const double s_timeout = 0.25; // FIXME -- is this too short?
while (!m_done && !m_failed) { while (!m_done && !m_failed) {
@ -1179,17 +1180,14 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display,
break; break;
} }
// get how many events are pending now // process events if any otherwise sleep
SInt32 pending = XPending(display); if (XPending(display) > 0) {
while (!m_done && !m_failed && XPending(display) > 0) {
// process events if there are more otherwise sleep XNextEvent(display, &xevent);
if (pending > lastPending) { if (!processEvent(display, &xevent)) {
lastPending = pending; // not processed so save it
while (!m_done && !m_failed && events.push_back(xevent);
XCheckIfEvent(display, &xevent, }
&CXWindowsClipboard::CICCCMGetClipboard::eventPredicate,
reinterpret_cast<XPointer>(this))) {
lastPending = XPending(display);
} }
} }
else { 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 // restore mask
XSelectInput(display, m_requestor, attr.your_event_mask); XSelectInput(display, m_requestor, attr.your_event_mask);
@ -1206,7 +1209,7 @@ CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display,
} }
bool bool
CXWindowsClipboard::CICCCMGetClipboard::doEventPredicate( CXWindowsClipboard::CICCCMGetClipboard::processEvent(
Display* display, XEvent* xevent) Display* display, XEvent* xevent)
{ {
// process event // process event
@ -1244,7 +1247,8 @@ CXWindowsClipboard::CICCCMGetClipboard::doEventPredicate(
xevent->xproperty.atom == m_property && xevent->xproperty.atom == m_property &&
xevent->xproperty.state == PropertyNewValue) { xevent->xproperty.state == PropertyNewValue) {
if (!m_reading) { if (!m_reading) {
return false; // we haven't gotten the SelectionNotify yet
return true;
} }
break; break;
} }
@ -1323,20 +1327,9 @@ log((CLOG_INFO " INCR secondary chunk")); // FIXME
m_done = true; m_done = true;
} }
// say we're not interested in this event if the conversion is // this event has been processed
// 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.
logc(!m_incr, (CLOG_DEBUG1 " got data, %d bytes", m_data->size())); logc(!m_incr, (CLOG_DEBUG1 " got data, %d bytes", m_data->size()));
return !m_incr; return true;
}
Bool
CXWindowsClipboard::CICCCMGetClipboard::eventPredicate(
Display* display, XEvent* xevent, XPointer arg)
{
CICCCMGetClipboard* self = reinterpret_cast<CICCCMGetClipboard*>(arg);
return self->doEventPredicate(display, xevent) ? True : False;
} }

View File

@ -107,11 +107,7 @@ private:
Atom* actualTarget, CString* data); Atom* actualTarget, CString* data);
private: private:
bool doEventPredicate(Display* display, bool processEvent(Display* display, XEvent* event);
XEvent* event);
static Bool eventPredicate(Display* display,
XEvent* event,
XPointer arg);
private: private:
Window m_requestor; Window m_requestor;