summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/winrt/qwinrtintegration.cpp
diff options
context:
space:
mode:
authorAndrew Knight <andrew.knight@intopalo.com>2015-08-12 12:43:54 +0300
committerAndrew Knight <andrew.knight@intopalo.com>2015-08-13 16:12:37 +0000
commit807ec8ea48281d5dbe365895fd9679da5b6753a5 (patch)
treeb65ffb79da8e2941385b345dda7cc49f5638a0b0 /src/plugins/platforms/winrt/qwinrtintegration.cpp
parentebc2b963aa9e8ce2e983ef08c9b503ccc1702fdb (diff)
winrt: Refactor platform plugin for XAML support
By using XAML as the platform compositor, many benefits are possible: - Better input context handling for tablets - Better multiple window support (including non-fullscreen windows) - Support for transparent windows and window opacity - Integration with native platform controls - Simpler orientation handling on Windows Phone with built-in transitions This patch applies only the minimal parts to make XAML mode work just as the raw D3D mode. It does this by: - Moving all OpenGL parts into QWinRTEGLContext. This will allow us to have non-OpenGL windows later (e.g. Direct2D raster surfaces). - Moving more window-specific parts into QWinRTWindow. Each window creates a SwapChainPanel which can then be used for ANGLE (or Direct2D) content. - Moving non screen-specific parts into QWinRTIntegration. - Having QWinRTScreen create the base XAML element Canvas. - Running certain calls on the UI thread where necessary. The following code parts were removed: - The UIAutomationCore code in QWinRTInputContext, as this is incompatible with XAML automation. - The D3D Trim and device blacklist, as these have been fixed in ANGLE. - Core dispatcher processing in QEventDispatcherWinRT. Now there is only one native event dispatcher; it is always running and never needs to be pumped. Future commits should address: - Maintaining the window stack list and visibility using the XAML Canvas. - Allowing for windows (e.g. popups) to be sized and positioned instead of fullscreen. - Using the XAML automation API to improve the platform input context. [ChangeLog][QPA][winrt] Windows Store apps are now composited inside a XAML container, allowing for tighter integration with the native UI layer. Change-Id: I285c6dea657c5dab2fda2b1bd8e8e5dd15882c72 Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/winrt/qwinrtintegration.cpp')
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp173
1 files changed, 159 insertions, 14 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 70ee6dbe6a..7079d46523 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -45,37 +45,138 @@
#include "qwinrtfontdatabase.h"
#include "qwinrttheme.h"
+#include <QtCore/QCoreApplication>
+#include <QtGui/QSurface>
#include <QtGui/QOpenGLContext>
+#include <qfunctions_winrt.h>
+#include <functional>
#include <wrl.h>
+#include <windows.ui.xaml.h>
+#include <windows.applicationmodel.h>
+#include <windows.applicationmodel.core.h>
#include <windows.ui.core.h>
#include <windows.ui.viewmanagement.h>
-#include <Windows.ApplicationModel.core.h>
+#include <windows.graphics.display.h>
+#ifdef Q_OS_WINPHONE
+# include <windows.phone.ui.input.h>
+#endif
using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::UI;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::ViewManagement;
+using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::ApplicationModel::Core;
+#ifdef Q_OS_WINPHONE
+using namespace ABI::Windows::Phone::UI::Input;
+#endif
+
+typedef IEventHandler<IInspectable *> ResumeHandler;
+typedef IEventHandler<SuspendingEventArgs *> SuspendHandler;
+#ifdef Q_OS_WINPHONE
+typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
+#endif
QT_BEGIN_NAMESPACE
-QWinRTIntegration::QWinRTIntegration()
- : m_success(false)
- , m_fontDatabase(new QWinRTFontDatabase)
- , m_services(new QWinRTServices)
+typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
+uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
+
+class QWinRTIntegrationPrivate
+{
+public:
+ QPlatformFontDatabase *fontDatabase;
+ QPlatformServices *platformServices;
+ QWinRTScreen *mainScreen;
+ QScopedPointer<QWinRTInputContext> inputContext;
+
+ ComPtr<ICoreApplication> application;
+ QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
+#ifdef Q_OS_WINPHONE
+ ComPtr<IHardwareButtonsStatics> hardwareButtons;
+ QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
+#endif
+};
+
+QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
{
- m_screen = new QWinRTScreen;
- screenAdded(m_screen);
+ Q_D(QWinRTIntegration);
+
+ d->fontDatabase = new QWinRTFontDatabase;
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&d->application));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTIntegration::onSuspended).Get(),
+ &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTIntegration::onResume).Get(),
+ &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
- m_success = true;
+#ifdef Q_OS_WINPHONE
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(),
+ IID_PPV_ARGS(&d->hardwareButtons));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(),
+ &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
+ 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);
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
}
QWinRTIntegration::~QWinRTIntegration()
{
+ Q_D(QWinRTIntegration);
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
+ for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) {
+ hr = (d->hardwareButtons.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif
+ for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i) {
+ hr = (d->application.Get()->*i.key())(i.value());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ destroyScreen(d->mainScreen);
Windows::Foundation::Uninitialize();
}
+bool QWinRTIntegration::succeeded() const
+{
+ Q_D(const QWinRTIntegration);
+ return d->mainScreen;
+}
+
QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const
{
return new QWinRTEventDispatcher;
@@ -112,28 +213,31 @@ QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *wi
QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- QWinRTScreen *screen = static_cast<QWinRTScreen *>(context->screen()->handle());
- return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface(), screen->eglConfig());
+ return new QWinRTEGLContext(context);
}
QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const
{
- return m_fontDatabase;
+ Q_D(const QWinRTIntegration);
+ return d->fontDatabase;
}
QPlatformInputContext *QWinRTIntegration::inputContext() const
{
- return m_screen->inputContext();
+ Q_D(const QWinRTIntegration);
+ return d->inputContext.data();
}
QPlatformServices *QWinRTIntegration::services() const
{
- return m_services;
+ Q_D(const QWinRTIntegration);
+ return d->platformServices;
}
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
- return m_screen->keyboardModifiers();
+ Q_D(const QWinRTIntegration);
+ return d->mainScreen->keyboardModifiers();
}
QStringList QWinRTIntegration::themeNames() const
@@ -149,4 +253,45 @@ name) const
return 0;
}
+
+// System-level integration points
+
+#ifdef Q_OS_WINPHONE
+HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
+{
+ Q_D(QWinRTIntegration);
+
+ QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
+ QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
+ backPress.setAccepted(false);
+ backRelease.setAccepted(false);
+
+ QWindow *window = d->mainScreen->topWindow();
+ QObject *receiver = window ? static_cast<QObject *>(window)
+ : static_cast<QObject *>(QCoreApplication::instance());
+
+ // If the event is ignored, the app go to the background
+ QCoreApplication::sendEvent(receiver, &backPress);
+ QCoreApplication::sendEvent(receiver, &backRelease);
+ args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
+
+ return S_OK;
+}
+#endif // Q_OS_WINPHONE
+
+HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *)
+{
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
+ QWindowSystemInterface::flushWindowSystemEvents();
+ return S_OK;
+}
+
+HRESULT QWinRTIntegration::onResume(IInspectable *, IInspectable *)
+{
+ // First the system invokes onResume and then changes
+ // the visibility of the screen to be active.
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationHidden);
+ return S_OK;
+}
+
QT_END_NAMESPACE