winrt: Connect callbacks after after integration class constructed.

It was possible for Windows Runtime callback to run while integration
class was constructed. That caused an assert when handling
application state change. Fix this by connecting callbacks after
integration class fully constructed.

Change-Id: I029c2e1f932e8edc3665443cc17dbf11eaae1bf6
Task-Id: QTBUG-48109
Reviewed-by: Andrew Knight <andrew.knight@intopalo.com>
This commit is contained in:
Samuel Nevala 2015-10-19 15:14:52 +03:00
parent 9388bbe4bd
commit ceec35a6de
4 changed files with 77 additions and 60 deletions

View File

@ -133,25 +133,13 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
HRESULT hr;
ComPtr<Xaml::IWindowStatics> windowStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Window).Get(),
IID_PPV_ARGS(&windowStatics));
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IWindow> window;
hr = windowStatics->get_Current(&window);
Q_ASSERT_SUCCEEDED(hr);
hr = window->Activate();
Q_ASSERT_SUCCEEDED(hr);
d->mainScreen = new QWinRTScreen(window.Get());
d->inputContext.reset(new QWinRTInputContext(d->mainScreen));
screenAdded(d->mainScreen);
QEventDispatcherWinRT::runOnXamlThread([d]() {
d->mainScreen = new QWinRTScreen;
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
d->inputContext.reset(new QWinRTInputContext(d->mainScreen));
screenAdded(d->mainScreen);
d->platformServices = new QWinRTServices;
}
@ -184,6 +172,15 @@ QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const
return new QWinRTEventDispatcher;
}
void QWinRTIntegration::initialize()
{
Q_D(const QWinRTIntegration);
QEventDispatcherWinRT::runOnXamlThread([d]() {
d->mainScreen->initialize();
return S_OK;
});
}
bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {

View File

@ -88,6 +88,7 @@ public:
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE;
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
QPlatformServices *services() const Q_DECL_OVERRIDE;

View File

@ -447,7 +447,7 @@ public:
};
// To be called from the XAML thread
QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
QWinRTScreen::QWinRTScreen()
: d_ptr(new QWinRTScreenPrivate)
{
Q_D(QWinRTScreen);
@ -455,7 +455,17 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
d->touchDevice = Q_NULLPTR;
HRESULT hr;
hr = xamlWindow->get_CoreWindow(&d->coreWindow);
ComPtr<Xaml::IWindowStatics> windowStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Window).Get(),
IID_PPV_ARGS(&windowStatics));
Q_ASSERT_SUCCEEDED(hr);
ComPtr<Xaml::IWindow> window;
hr = windowStatics->get_Current(&window);
Q_ASSERT_SUCCEEDED(hr);
hr = window->Activate();
Q_ASSERT_SUCCEEDED(hr);
hr = window->get_CoreWindow(&d->coreWindow);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->Activate();
Q_ASSERT_SUCCEEDED(hr);
@ -465,35 +475,6 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
Q_ASSERT_SUCCEEDED(hr);
d->logicalSize = QSizeF(rect.Width, rect.Height);
hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
Q_ASSERT_SUCCEEDED(hr);
#ifndef Q_OS_WINPHONE
hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
Q_ASSERT_SUCCEEDED(hr);
#endif
hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
Q_ASSERT_SUCCEEDED(hr);
// Orientation handling
ComPtr<IDisplayInformationStatics> displayInformationStatics;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
@ -509,12 +490,6 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
Q_ASSERT_SUCCEEDED(hr);
d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
Q_ASSERT_SUCCEEDED(hr);
// Set initial orientation & pixel density
onDpiChanged(Q_NULLPTR, Q_NULLPTR);
d->orientation = d->nativeOrientation;
@ -542,7 +517,7 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
ComPtr<Xaml::IUIElement> uiElement;
hr = canvas.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
hr = xamlWindow->put_Content(uiElement.Get());
hr = window->put_Content(uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
hr = canvas.As(&d->canvas);
Q_ASSERT_SUCCEEDED(hr);
@ -556,10 +531,6 @@ QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
Q_ASSERT_SUCCEEDED(hr);
hr = statusBarStatics->GetForCurrentView(&d->statusBar);
Q_ASSERT_SUCCEEDED(hr);
hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]);
Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
}
@ -726,6 +697,50 @@ void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window)
}
#endif //Q_OS_WINPHONE
void QWinRTScreen::initialize()
{
Q_D(QWinRTScreen);
HRESULT hr;
hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
Q_ASSERT_SUCCEEDED(hr);
#ifndef Q_OS_WINPHONE
hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
Q_ASSERT_SUCCEEDED(hr);
#else
hr = d->statusBar->add_Showing(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarShowing).Get(), &d->statusBarTokens[&IStatusBar::remove_Showing]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->statusBar->add_Hiding(Callback<StatusBarHandler>(this, &QWinRTScreen::onStatusBarHiding).Get(), &d->statusBarTokens[&IStatusBar::remove_Hiding]);
Q_ASSERT_SUCCEEDED(hr);
#endif
hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
Q_ASSERT_SUCCEEDED(hr);
hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
Q_ASSERT_SUCCEEDED(hr);
onVisibilityChanged(nullptr, nullptr);
}
QWindow *QWinRTScreen::topWindow() const
{
Q_D(const QWinRTScreen);
@ -1089,8 +1104,10 @@ HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEventArgs *args)
{
Q_D(QWinRTScreen);
boolean visible;
args->get_Visible(&visible);
HRESULT hr = args ? args->get_Visible(&visible) : d->coreWindow->get_Visible(&visible);
RETURN_OK_IF_FAILED("Failed to get visbile.");
QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden);
if (visible)
handleExpose();

View File

@ -83,7 +83,7 @@ class QWinRTScreenPrivate;
class QWinRTScreen : public QPlatformScreen
{
public:
explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow);
explicit QWinRTScreen();
~QWinRTScreen();
QRect geometry() const Q_DECL_OVERRIDE;
#ifdef Q_OS_WINPHONE
@ -115,6 +115,8 @@ public:
void setStatusBarVisibility(bool visible, QWindow *window);
#endif
void initialize();
private:
void handleExpose();