xcb: Avoid repaint lags with DnD

The lags can be seen when dragged data is requested for a
MIME type. This leads to calling QXcbClipboard::waitForClipboardEvent()
which runs a loop in the GUI thread and processes events from
QXcbEventQueue. The loop ends when a corresponding event is
received, otherwise it makes a delay of 50 ms before the next
iteration.

Sync with QXcbEventQueue thread by QWaitCondition instead
of using the delay. This way the loop will end as soon as
possible and Expose events will be processed with minimal
delay.

Task-number: QTBUG-44849
Fixes: QTBUG-55442
Fixes: QTBUG-62344
Fixes: QTBUG-73253
Change-Id: Ie18d63b51a7260c83d53ffe1169b25e5135dd73b
Reviewed-by: Mikhail Svetkin <mikhail.svetkin@qt.io>
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Alexander Volkov 2019-01-24 15:53:28 +03:00 committed by Gatis Paeglis
parent c9b9a0ea2f
commit 730cbad882
3 changed files with 19 additions and 2 deletions

View File

@ -810,8 +810,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i
connection()->flush();
// sleep 50 ms, so we don't use up CPU cycles all the time.
QThread::msleep(50);
const auto elapsed = timer.elapsed();
if (elapsed < clipboard_timeout)
queue->waitForNewEvents(clipboard_timeout - elapsed);
} while (timer.elapsed() < clipboard_timeout);
return nullptr;

View File

@ -229,6 +229,8 @@ void QXcbEventQueue::run()
enqueueEvent(event);
while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
enqueueEvent(event);
m_newEventsCondition.wakeOne();
wakeUpDispatcher();
}
@ -346,6 +348,13 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
return result;
}
void QXcbEventQueue::waitForNewEvents(unsigned long time)
{
m_newEventsMutex.lock();
m_newEventsCondition.wait(&m_newEventsMutex, time);
m_newEventsMutex.unlock();
}
void QXcbEventQueue::sendCloseConnectionEvent() const
{
// A hack to close XCB connection. Apparently XCB does not have any APIs for this?

View File

@ -43,6 +43,8 @@
#include <QtCore/QHash>
#include <QtCore/QEventLoop>
#include <QtCore/QVector>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>
#include <xcb/xcb.h>
@ -104,6 +106,8 @@ public:
bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
PeekOptions option = PeekDefault, qint32 peekerId = -1);
void waitForNewEvents(unsigned long time = ULONG_MAX);
private:
QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
void dequeueNode();
@ -131,6 +135,9 @@ private:
// debug stats
quint64 m_nodesOnHeap = 0;
QMutex m_newEventsMutex;
QWaitCondition m_newEventsCondition;
};
template<typename Peeker>