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>bb10
parent
2b66a37a3e
commit
2eda13c965
|
|
@ -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)
|
||||
|
|
@ -116,13 +138,41 @@ QEventDispatcherWinRT::~QEventDispatcherWinRT()
|
|||
}
|
||||
|
||||
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
{
|
||||
Q_D(QEventDispatcherWinRT);
|
||||
|
||||
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);
|
||||
|
||||
// we are awake, broadcast it
|
||||
emit awake();
|
||||
QCoreApplicationPrivate::sendPostedEvents(0, 0, QThreadData::current());
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ public:
|
|||
protected:
|
||||
QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent = 0);
|
||||
|
||||
virtual bool sendPostedEvents(QEventLoop::ProcessEventsFlags flags);
|
||||
bool event(QEvent *);
|
||||
int activateTimers();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
bool QWinRTEventDispatcher::sendPostedEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
{
|
||||
m_interrupt = true;
|
||||
}
|
||||
|
||||
bool QWinRTEventDispatcher::processEvents(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue