WinRT: Improve event dispatcher

- Sleep when there are no events to process. Otherwise, CPU usage remains
  high all the time.
- Reorder processing so window events are processed after being collected
  by the native event loop.
- Provide basic interrupt and WaitForMoreEvents flag support.

Task-number: QTBUG-35327

Change-Id: I8a5545cba5f3e65eafd0bb40695bf6ffde68bb04
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
bb10
Andrew Knight 2014-01-06 22:51:49 +02:00 committed by The Qt Project
parent ae56140b50
commit 153f82390d
2 changed files with 35 additions and 8 deletions

View File

@ -52,12 +52,14 @@
using namespace ABI::Windows::ApplicationModel::Core;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
QT_BEGIN_NAMESPACE
QWinRTEventDispatcher::QWinRTEventDispatcher(ICoreDispatcher *dispatcher, QObject *parent)
: QEventDispatcherWinRT(parent)
, m_dispatcher(dispatcher)
, m_interrupt(false)
{
}
@ -66,14 +68,38 @@ bool QWinRTEventDispatcher::hasPendingEvents()
return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued();
}
void QWinRTEventDispatcher::interrupt()
{
m_interrupt = true;
}
bool QWinRTEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
if (m_dispatcher)
m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
bool canWait = flags & QEventLoop::WaitForMoreEvents;
bool didProcess;
m_interrupt = false;
do {
// Send Qt events
didProcess = QEventDispatcherWinRT::processEvents(flags);
const bool didProcess = QWindowSystemInterface::sendWindowSystemEvents(flags);
// Process system events
emit aboutToBlock();
if (m_dispatcher)
m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
emit awake();
return QEventDispatcherWinRT::processEvents(flags & ~QEventLoop::WaitForMoreEvents) || didProcess;
// Dispatch accumulated user events
didProcess |= QWindowSystemInterface::sendWindowSystemEvents(flags);
canWait = canWait && !didProcess && !m_interrupt;
// Short sleep if there is nothing to do
if (canWait) {
emit aboutToBlock();
WaitForSingleObjectEx(GetCurrentThread(), 1, true);
emit awake();
}
} while (canWait);
return didProcess;
}
QT_END_NAMESPACE

View File

@ -42,11 +42,10 @@
#ifndef QWINRTEVENTDISPATCHER_H
#define QWINRTEVENTDISPATCHER_H
#include <QtCore/QAbstractEventDispatcher>
#include <QtCore/QEvent>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
#include <wrl.h>
namespace ABI {
namespace Windows {
namespace UI {
@ -66,11 +65,13 @@ public:
explicit QWinRTEventDispatcher(ABI::Windows::UI::Core::ICoreDispatcher *dispatcher, QObject *parent = 0);
protected:
void interrupt();
bool hasPendingEvents();
bool processEvents(QEventLoop::ProcessEventsFlags flags);
private:
ABI::Windows::UI::Core::ICoreDispatcher *m_dispatcher;
Microsoft::WRL::ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> m_dispatcher;
bool m_interrupt;
friend class QWinRTIntegration;
};