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:
parent
2423dc662d
commit
cec075cb60
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue