diff options
author | Alexander Volkov <a.volkov@rusbitech.ru> | 2019-01-24 15:53:28 +0300 |
---|---|---|
committer | Gatis Paeglis <gatis.paeglis@qt.io> | 2019-01-25 15:59:51 +0000 |
commit | 730cbad8824bcfcb7ab60371a6563cfb6dd5658d (patch) | |
tree | 4e1d88c0662fb1b90f55758bfed92762a484a3ec /src/plugins | |
parent | c9b9a0ea2f274688da26af20102d349336fdb2a0 (diff) |
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>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbclipboard.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.cpp | 9 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.h | 7 |
3 files changed, 19 insertions, 2 deletions
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index bc92f82d5f..ac8b029916 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -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; diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index f6158d3127..acec0486c2 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -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? diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h index 235f2824be..11d0b8e963 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.h +++ b/src/plugins/platforms/xcb/qxcbeventqueue.h @@ -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> |