diff --git a/mt/CThreadRep.cpp b/mt/CThreadRep.cpp index 604a3650..82e15992 100644 --- a/mt/CThreadRep.cpp +++ b/mt/CThreadRep.cpp @@ -628,6 +628,14 @@ CThreadRep::wait(CThreadRep* target, double timeout) bool CThreadRep::waitForEvent(double timeout) { + // check if messages are available first. if we don't do this then + // MsgWaitForMultipleObjects() will block even if the queue isn't + // empty if the messages in the queue were there before the last + // call to GetMessage()/PeekMessage(). + if (HIWORD(GetQueueStatus(QS_ALLINPUT)) != 0) { + return true; + } + // is cancellation enabled? const DWORD n = (isCancellable() ? 1 : 0); diff --git a/platform/CMSWindowsScreen.cpp b/platform/CMSWindowsScreen.cpp index 63e34d1f..b6e87f56 100644 --- a/platform/CMSWindowsScreen.cpp +++ b/platform/CMSWindowsScreen.cpp @@ -208,11 +208,7 @@ CMSWindowsScreen::mainLoop() void CMSWindowsScreen::exitMainLoop() { - // post an arbitrary message after the quit because - // MsgWaitForMultipleObjects() is broken and might not wake up if - // just WM_QUIT is in the queue. PostThreadMessage(m_threadID, WM_QUIT, 0, 0); - PostThreadMessage(m_threadID, WM_APP + 1, 0, 0); } void @@ -423,15 +419,33 @@ CMSWindowsScreen::onPreDispatch(const CEvent* event) const MSG* msg = &event->m_msg; switch (msg->message) { case SYNERGY_MSG_SCREEN_SAVER: - if (msg->wParam != 0) { - if (m_screensaver->checkStarted(msg->message, FALSE, 0)) { - m_eventHandler->onScreensaver(true); + { + // activating or deactivating? + bool activate = (msg->wParam != 0); + + // ignore this message if there are any other screen saver + // messages already in the queue. this is important because + // our checkStarted() function has a deliberate delay, so it + // can't respond to events at full CPU speed and will fall + // behind if a lot of screen saver events are generated. + // that can easily happen because windows will continually + // send SC_SCREENSAVE until the screen saver starts, even if + // the screen saver is disabled! + MSG msg; + if (!PeekMessage(&msg, NULL, SYNERGY_MSG_SCREEN_SAVER, + SYNERGY_MSG_SCREEN_SAVER, PM_NOREMOVE)) { + if (activate) { + if (m_screensaver->checkStarted( + SYNERGY_MSG_SCREEN_SAVER, FALSE, 0)) { + m_eventHandler->onScreensaver(true); + } + } + else { + m_eventHandler->onScreensaver(false); + } } + return true; } - else { - m_eventHandler->onScreensaver(false); - } - return true; case WM_TIMER: // if current desktop is not the input desktop then switch to it.