winrt: Handle dispatcher thread change

If the calling thread changes when processing events, the dispatcher
will no longer have thread access and event processing will fail. This
can e.g. prevent new threads from being created. To remedy this, the
dispatcher object is re-fetched if the thread is changed.

Change-Id: I519cff521f9b84211db3f28a7a28b532de44a6a4
Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
Andrew Knight 2014-07-25 23:21:07 +03:00
parent c7abf81786
commit ed7894dd77

View File

@ -133,6 +133,7 @@ private:
ComPtr<IThreadPoolTimerStatics> timerFactory; ComPtr<IThreadPoolTimerStatics> timerFactory;
ComPtr<ICoreDispatcher> coreDispatcher; ComPtr<ICoreDispatcher> coreDispatcher;
QPointer<QThread> thread;
bool interrupt; bool interrupt;
}; };
@ -140,24 +141,6 @@ private:
QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent) QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
: QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent) : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent)
{ {
Q_D(QEventDispatcherWinRT);
// Obtain the WinRT Application, view, and window
ComPtr<ICoreImmersiveApplication> application;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
RETURN_VOID_IF_FAILED("Failed to activate the application factory");
ComPtr<ICoreApplicationView> view;
hr = application->get_MainView(&view);
RETURN_VOID_IF_FAILED("Failed to get the main view");
ComPtr<ICoreWindow> window;
hr = view->get_CoreWindow(&window);
RETURN_VOID_IF_FAILED("Failed to get the core window");
hr = window->get_Dispatcher(&d->coreDispatcher);
RETURN_VOID_IF_FAILED("Failed to get the core dispatcher");
} }
QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent) QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
@ -172,6 +155,26 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{ {
Q_D(QEventDispatcherWinRT); Q_D(QEventDispatcherWinRT);
if (d->thread != QThread::currentThread()) {
ComPtr<ICoreImmersiveApplication> application;
HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
IID_PPV_ARGS(&application));
RETURN_FALSE_IF_FAILED("Failed to get the application factory");
ComPtr<ICoreApplicationView> view;
hr = application->get_MainView(&view);
RETURN_FALSE_IF_FAILED("Failed to get the main view");
ComPtr<ICoreWindow> window;
hr = view->get_CoreWindow(&window);
RETURN_FALSE_IF_FAILED("Failed to get the core window");
hr = window->get_Dispatcher(&d->coreDispatcher);
RETURN_FALSE_IF_FAILED("Failed to get the core dispatcher");
d->thread = QThread::currentThread();
}
bool didProcess = false; bool didProcess = false;
forever { forever {
// Process native events // Process native events