diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-02-10 10:11:18 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-12 20:12:17 +0100 |
commit | 2eda13c965497e41bb2d031f7890979a819d6438 (patch) | |
tree | 0a1335f9345a2c95af030fea5aa767e31af29d2c | |
parent | 2b66a37a3e9b6528d5e398a2c1dad4611a38e1b4 (diff) |
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 <oliver.wolff@digia.com>
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_winrt.cpp | 69 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_winrt_p.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrteventdispatcher.cpp | 44 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrteventdispatcher.h | 23 | ||||
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtintegration.cpp | 5 |
5 files changed, 69 insertions, 73 deletions
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 <QtCore/QCoreApplication> #include <QtCore/QThread> #include <QtCore/QHash> - -#include <private/qcoreapplication_p.h> -#include <private/qthread_p.h> #include <private/qabstracteventdispatcher_p.h> #include <wrl.h> #include <windows.foundation.h> #include <windows.system.threading.h> +#include <windows.ui.core.h> +#include <windows.applicationmodel.core.h> 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<IThreadPoolTimer *, int> timerIds; ComPtr<IThreadPoolTimerStatics> timerFactory; + ComPtr<ICoreDispatcher> coreDispatcher; + + bool interrupt; }; QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent) : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent) { + Q_D(QEventDispatcherWinRT); + ComPtr<ICoreApplication> application; + HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), + IID_PPV_ARGS(&application)); + if (SUCCEEDED(hr)) { + ComPtr<ICoreApplicationView> view; + hr = application->GetCurrentView(&view); + if (SUCCEEDED(hr)) { + ComPtr<ICoreWindow> 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); diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h index 0631b2ea33..5cc37fb538 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt_p.h +++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h @@ -99,6 +99,7 @@ public: protected: QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent = 0); + virtual bool sendPostedEvents(QEventLoop::ProcessEventsFlags flags); bool event(QEvent *); int activateTimers(); }; diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp index baa8b5c636..98eb83f5eb 100644 --- a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp @@ -46,20 +46,10 @@ #include <QtCore/QThread> #include <QtGui/QGuiApplication> -#include <Windows.ui.core.h> -#include <Windows.ApplicationModel.core.h> - -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) +QWinRTEventDispatcher::QWinRTEventDispatcher(QObject *parent) : QEventDispatcherWinRT(parent) - , m_dispatcher(dispatcher) - , m_interrupt(false) { } @@ -68,37 +58,11 @@ bool QWinRTEventDispatcher::hasPendingEvents() return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued(); } -void QWinRTEventDispatcher::interrupt() -{ - m_interrupt = true; -} - -bool QWinRTEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) +bool QWinRTEventDispatcher::sendPostedEvents(QEventLoop::ProcessEventsFlags flags) { - bool canWait = flags & QEventLoop::WaitForMoreEvents; - bool didProcess; - m_interrupt = false; - do { - // Send Qt events - didProcess = QEventDispatcherWinRT::processEvents(flags); - - // Process system events - emit aboutToBlock(); - if (m_dispatcher) - m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent); - emit awake(); - - // Dispatch accumulated user events + bool didProcess = QEventDispatcherWinRT::sendPostedEvents(flags); + if (!(flags & QEventLoop::ExcludeUserInputEvents)) 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; } diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h index 741007c7fa..612d5ff6e2 100644 --- a/src/plugins/platforms/winrt/qwinrteventdispatcher.h +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h @@ -44,36 +44,17 @@ #include <QtCore/private/qeventdispatcher_winrt_p.h> -#include <wrl.h> - -namespace ABI { - namespace Windows { - namespace UI { - namespace Core { - struct ICoreDispatcher; - } - } - } -} - QT_BEGIN_NAMESPACE class QWinRTEventDispatcher : public QEventDispatcherWinRT { Q_OBJECT public: - explicit QWinRTEventDispatcher(ABI::Windows::UI::Core::ICoreDispatcher *dispatcher, QObject *parent = 0); + explicit QWinRTEventDispatcher(QObject *parent = 0); protected: - void interrupt(); bool hasPendingEvents(); - bool processEvents(QEventLoop::ProcessEventsFlags flags); - -private: - Microsoft::WRL::ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> m_dispatcher; - bool m_interrupt; - - friend class QWinRTIntegration; + bool sendPostedEvents(QEventLoop::ProcessEventsFlags flags); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 80ed9d1aab..be82390723 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -114,10 +114,7 @@ QWinRTIntegration::~QWinRTIntegration() QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const { - ICoreDispatcher *dispatcher; - if (FAILED(m_screen->coreWindow()->get_Dispatcher(&dispatcher))) - qCritical("Could not capture UI Dispatcher"); - return new QWinRTEventDispatcher(dispatcher); + return new QWinRTEventDispatcher; } bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const |