From 722b7d6cc4117eac900dd0fb51f451f830ce7605 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Wed, 20 May 2020 22:11:14 +0300 Subject: [PATCH] XWindowsEventQueueBuffer: Fix delays when waiting for new events QLength() may return 0 even if there are events pending because they need to be read from the display socket in order to become visible. We must use XPending() which will poll the socket if QLength() == 0. --- src/lib/platform/XWindowsEventQueueBuffer.cpp | 15 ++++++++++++++- src/lib/platform/XWindowsEventQueueBuffer.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/lib/platform/XWindowsEventQueueBuffer.cpp b/src/lib/platform/XWindowsEventQueueBuffer.cpp index 78f0e5af8..8b8c3b59f 100644 --- a/src/lib/platform/XWindowsEventQueueBuffer.cpp +++ b/src/lib/platform/XWindowsEventQueueBuffer.cpp @@ -82,6 +82,19 @@ XWindowsEventQueueBuffer::~XWindowsEventQueueBuffer() close(m_pipefd[1]); } +int XWindowsEventQueueBuffer::getPendingCountLocked() +{ + Lock lock(&m_mutex); + // work around a bug in old libx11 which causes the first XPending not to read events under + // certain conditions. The issue happens when libx11 has not yet received replies for all + // flushed events. In that case, internally XPending will not try to process received events + // as the reply for the last event was not found. As a result, XPending will return the number + // of pending events without regard to the events it has just read. + // https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/1 fixes this on libx11 side. + m_impl->XPending(m_display); + return m_impl->XPending(m_display); +} + void XWindowsEventQueueBuffer::waitForEvent(double dtimeout) { @@ -163,7 +176,7 @@ XWindowsEventQueueBuffer::waitForEvent(double dtimeout) // we want to give the cpu a chance s owe up this to 25ms #define TIMEOUT_DELAY 25 - while (((dtimeout < 0.0) || (remaining > 0)) && QLength(m_display)==0 && retval==0){ + while (((dtimeout < 0.0) || (remaining > 0)) && getPendingCountLocked() == 0 && retval == 0) { #if HAVE_POLL retval = poll(pfds, 2, TIMEOUT_DELAY); //16ms = 60hz, but we make it > to play nicely with the cpu if (pfds[1].revents & POLLIN) { diff --git a/src/lib/platform/XWindowsEventQueueBuffer.h b/src/lib/platform/XWindowsEventQueueBuffer.h index e49b282b0..13f6b160d 100644 --- a/src/lib/platform/XWindowsEventQueueBuffer.h +++ b/src/lib/platform/XWindowsEventQueueBuffer.h @@ -51,6 +51,8 @@ class XWindowsEventQueueBuffer : public IEventQueueBuffer { private: void flush(); + int getPendingCountLocked(); + private: typedef std::vector EventList; IXWindowsImpl* m_impl;