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:
parent
c9b9a0ea2f
commit
730cbad882
@ -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;
|
||||
|
@ -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?
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user