From 2eda13c965497e41bb2d031f7890979a819d6438 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 10 Feb 2014 10:11:18 +0200 Subject: WinRT: move most of GUI event dispatcher logic into core The native event dispatcher is responsible for delivering callbacks to non-GUI handlers, such as network socket listeners. So, the non-GUI logic is moved into the core dispatcher so that the event loop works better for apps (and test cases) which use QCoreApplication. Change-Id: Ic5f7d939cf164198fd39aa5880e265ae560b39b4 Reviewed-by: Oliver Wolff --- src/corelib/kernel/qeventdispatcher_winrt.cpp | 69 +++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 8 deletions(-) (limited to 'src/corelib/kernel/qeventdispatcher_winrt.cpp') diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index cd843a4986..8b2dd2ef6d 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -44,18 +44,19 @@ #include #include #include - -#include -#include #include #include #include #include +#include +#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::System::Threading; using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::ApplicationModel::Core; QT_BEGIN_NAMESPACE @@ -92,7 +93,6 @@ public: void unregisterTimer(WinRTTimerInfo *t); void sendTimerEvent(int timerId); - private: static HRESULT timerExpiredCallback(IThreadPoolTimer *timer); @@ -100,11 +100,33 @@ private: QHash timerIds; ComPtr timerFactory; + ComPtr coreDispatcher; + + bool interrupt; }; QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent) : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent) { + Q_D(QEventDispatcherWinRT); + ComPtr application; + HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + IID_PPV_ARGS(&application)); + if (SUCCEEDED(hr)) { + ComPtr view; + hr = application->GetCurrentView(&view); + if (SUCCEEDED(hr)) { + ComPtr window; + hr = view->get_CoreWindow(&window); + if (SUCCEEDED(hr)) { + hr = window->get_Dispatcher(&d->coreDispatcher); + if (SUCCEEDED(hr)) + return; + } + } + } + qCritical("QEventDispatcherWinRT: Unable to capture the core dispatcher. %s", + qPrintable(qt_error_string(hr))); } QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent) @@ -117,12 +139,40 @@ QEventDispatcherWinRT::~QEventDispatcherWinRT() bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) { - Q_UNUSED(flags); + Q_D(QEventDispatcherWinRT); - // we are awake, broadcast it - emit awake(); - QCoreApplicationPrivate::sendPostedEvents(0, 0, QThreadData::current()); + bool didProcess = false; + forever { + // Process native events + if (d->coreDispatcher) + d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent); + + // Dispatch accumulated user events + didProcess = sendPostedEvents(flags); + if (didProcess) + break; + + if (d->interrupt) + break; + + // Short sleep if there is nothing to do + if (flags & QEventLoop::WaitForMoreEvents) { + emit aboutToBlock(); + WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE); + emit awake(); + } + } + d->interrupt = false; + return didProcess; +} +bool QEventDispatcherWinRT::sendPostedEvents(QEventLoop::ProcessEventsFlags flags) +{ + Q_UNUSED(flags); + if (hasPendingEvents()) { + QCoreApplication::sendPostedEvents(); + return true; + } return false; } @@ -268,6 +318,8 @@ void QEventDispatcherWinRT::wakeUp() void QEventDispatcherWinRT::interrupt() { + Q_D(QEventDispatcherWinRT); + d->interrupt = true; } void QEventDispatcherWinRT::flush() @@ -318,6 +370,7 @@ bool QEventDispatcherWinRT::event(QEvent *e) } QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() + : interrupt(false) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory); -- cgit v1.2.3