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 "CLog.h"
#include "CStopwatch.h"
#include "stdvector.h"
#include <cstdio>
#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
// by badly behaved selection owners.
XEvent xevent;
SInt32 lastPending = 0;
std::vector<XEvent> 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<XPointer>(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<CICCCMGetClipboard*>(arg);
return self->doEventPredicate(display, xevent) ? True : False;
return true;
}

View File

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