diff --git a/platform/CXWindowsClipboard.cpp b/platform/CXWindowsClipboard.cpp index f894789b..08cb1f98 100644 --- a/platform/CXWindowsClipboard.cpp +++ b/platform/CXWindowsClipboard.cpp @@ -800,7 +800,7 @@ CXWindowsClipboard::insertReply(CReply* reply) if (newWindow) { // note errors while we adjust event masks bool error = false; - CXWindowsUtil::CErrorLock lock(&error); + CXWindowsUtil::CErrorLock lock(m_display, &error); // get and save the current event mask XWindowAttributes attr; @@ -852,7 +852,7 @@ CXWindowsClipboard::pushReplies(CReplyMap::iterator mapIndex, // if there are no more replies in the list then remove the list // and stop watching the requestor for events. if (replies.empty()) { - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); Window requestor = mapIndex->first; XSelectInput(m_display, requestor, m_eventMasks[requestor]); m_replies.erase(mapIndex); @@ -926,7 +926,7 @@ CXWindowsClipboard::sendReply(CReply* reply) log((CLOG_DEBUG1 "clipboard: sending failure to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); reply->m_done = true; if (reply->m_property != None) { - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); XDeleteProperty(m_display, reply->m_requestor, reply->m_property); } @@ -1016,7 +1016,7 @@ CXWindowsClipboard::sendNotify(Window requestor, event.xselection.target = target; event.xselection.property = property; event.xselection.time = time; - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); XSendEvent(m_display, requestor, False, 0, &event); } diff --git a/platform/CXWindowsScreenSaver.cpp b/platform/CXWindowsScreenSaver.cpp index 89070e3a..f197b88a 100644 --- a/platform/CXWindowsScreenSaver.cpp +++ b/platform/CXWindowsScreenSaver.cpp @@ -24,7 +24,7 @@ CXWindowsScreenSaver::CXWindowsScreenSaver(Display* display) : // watch top-level windows for changes { bool error = false; - CXWindowsUtil::CErrorLock lock(&error); + CXWindowsUtil::CErrorLock lock(m_display, &error); Window root = DefaultRootWindow(m_display); XWindowAttributes attr; XGetWindowAttributes(m_display, root, &attr); @@ -46,7 +46,7 @@ CXWindowsScreenSaver::CXWindowsScreenSaver(Display* display) : CXWindowsScreenSaver::~CXWindowsScreenSaver() { // stop watching root for events - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); Window root = DefaultRootWindow(m_display); XSelectInput(m_display, root, m_rootEventMask); } @@ -179,7 +179,7 @@ CXWindowsScreenSaver::sendNotify(bool activated) event.xclient.data.l[3] = 0; event.xclient.data.l[4] = 0; - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); XSendEvent(m_display, m_notify, False, 0, &event); } } @@ -202,7 +202,7 @@ CXWindowsScreenSaver::updateXScreenSaver() } // find top-level window with m_atomScreenSaverVersion string property - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); Window root = DefaultRootWindow(m_display); Window rw, pw, *cw; unsigned int nc; @@ -224,7 +224,7 @@ CXWindowsScreenSaver::updateXScreenSaver() // see if xscreensaver is active if (m_xscreensaver != None) { bool error = false; - CXWindowsUtil::CErrorLock lock(&error); + CXWindowsUtil::CErrorLock lock(m_display, &error); XWindowAttributes attr; XGetWindowAttributes(m_display, m_xscreensaver, &attr); setXScreenSaver(!error && attr.map_state != IsUnmapped); @@ -250,6 +250,6 @@ CXWindowsScreenSaver::sendXScreenSaverCommand( event.xclient.data.l[3] = 0; event.xclient.data.l[4] = 0; - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(m_display); XSendEvent(m_display, m_xscreensaver, False, 0, &event); } diff --git a/platform/CXWindowsUtil.cpp b/platform/CXWindowsUtil.cpp index d7b9ba4c..8279d084 100644 --- a/platform/CXWindowsUtil.cpp +++ b/platform/CXWindowsUtil.cpp @@ -19,7 +19,7 @@ CXWindowsUtil::getWindowProperty(Display* display, Window window, int actualDatumSize; // ignore errors. XGetWindowProperty() will report failure. - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(display); // read the property const long length = XMaxRequestSize(display); @@ -93,7 +93,7 @@ CXWindowsUtil::setWindowProperty(Display* display, Window window, // save errors bool error = false; - CXWindowsUtil::CErrorLock lock(&error); + CXWindowsUtil::CErrorLock lock(display, &error); // how much data to send in first chunk? UInt32 chunkSize = size; @@ -179,23 +179,31 @@ CXWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg) CXWindowsUtil::CErrorLock* CXWindowsUtil::CErrorLock::s_top = NULL; -CXWindowsUtil::CErrorLock::CErrorLock() +CXWindowsUtil::CErrorLock::CErrorLock(Display* display) : + m_display(display) { install(&CXWindowsUtil::CErrorLock::ignoreHandler, NULL); } -CXWindowsUtil::CErrorLock::CErrorLock(bool* flag) +CXWindowsUtil::CErrorLock::CErrorLock(Display* display, bool* flag) : + m_display(display) { install(&CXWindowsUtil::CErrorLock::saveHandler, flag); } -CXWindowsUtil::CErrorLock::CErrorLock(ErrorHandler handler, void* data) +CXWindowsUtil::CErrorLock::CErrorLock(Display* display, + ErrorHandler handler, void* data) : + m_display(display) { install(handler, data); } CXWindowsUtil::CErrorLock::~CErrorLock() { + // make sure everything finishes before uninstalling handler + XSync(m_display, False); + + // restore old handler XSetErrorHandler(m_oldXHandler); s_top = m_next; } @@ -203,6 +211,10 @@ CXWindowsUtil::CErrorLock::~CErrorLock() void CXWindowsUtil::CErrorLock::install(ErrorHandler handler, void* data) { + // make sure everything finishes before installing handler + XSync(m_display, False); + + // install handler m_handler = handler; m_userData = data; m_oldXHandler = XSetErrorHandler( @@ -221,13 +233,14 @@ CXWindowsUtil::CErrorLock::internalHandler(Display* display, XErrorEvent* event) } void -CXWindowsUtil::CErrorLock::ignoreHandler(Display*, XErrorEvent*, void*) +CXWindowsUtil::CErrorLock::ignoreHandler(Display*, XErrorEvent* e, void*) { - // do nothing + log((CLOG_DEBUG "ignoring X error: %d", e->error_code)); } void -CXWindowsUtil::CErrorLock::saveHandler(Display*, XErrorEvent*, void* flag) +CXWindowsUtil::CErrorLock::saveHandler(Display*, XErrorEvent* e, void* flag) { + log((CLOG_DEBUG "flagging X error: %d", e->error_code)); *reinterpret_cast(flag) = true; } diff --git a/platform/CXWindowsUtil.h b/platform/CXWindowsUtil.h index 9e8add53..fefcc92a 100644 --- a/platform/CXWindowsUtil.h +++ b/platform/CXWindowsUtil.h @@ -30,9 +30,9 @@ public: class CErrorLock { public: typedef void (*ErrorHandler)(Display*, XErrorEvent*, void* userData); - CErrorLock(); - CErrorLock(bool* errorFlag); - CErrorLock(ErrorHandler, void* userData); + CErrorLock(Display*); + CErrorLock(Display*, bool* errorFlag); + CErrorLock(Display*, ErrorHandler, void* userData); ~CErrorLock(); private: @@ -44,6 +44,7 @@ public: private: typedef int (*XErrorHandler)(Display*, XErrorEvent*); + Display* m_display; ErrorHandler m_handler; void* m_userData; XErrorHandler m_oldXHandler; diff --git a/server/CXWindowsPrimaryScreen.cpp b/server/CXWindowsPrimaryScreen.cpp index a500e545..1537af18 100644 --- a/server/CXWindowsPrimaryScreen.cpp +++ b/server/CXWindowsPrimaryScreen.cpp @@ -617,7 +617,7 @@ CXWindowsPrimaryScreen::selectEvents(Display* display, Window w) const // ignore errors while we adjust event masks. windows could be // destroyed at any time after the XQueryTree() in doSelectEvents() // so we must ignore BadWindow errors. - CXWindowsUtil::CErrorLock lock; + CXWindowsUtil::CErrorLock lock(display); // adjust event masks doSelectEvents(display, w);