winrt: Refactor platform plugin for XAML support
authorAndrew Knight <andrew.knight@intopalo.com>
Wed, 12 Aug 2015 09:43:54 +0000 (12:43 +0300)
committerAndrew Knight <andrew.knight@intopalo.com>
Thu, 13 Aug 2015 16:12:37 +0000 (16:12 +0000)
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>
13 files changed:
src/corelib/kernel/qeventdispatcher_winrt.cpp
src/corelib/kernel/qeventdispatcher_winrt_p.h
src/plugins/platforms/winrt/qwinrtcursor.cpp
src/plugins/platforms/winrt/qwinrteglcontext.cpp
src/plugins/platforms/winrt/qwinrteglcontext.h
src/plugins/platforms/winrt/qwinrtinputcontext.cpp
src/plugins/platforms/winrt/qwinrtinputcontext.h
src/plugins/platforms/winrt/qwinrtintegration.cpp
src/plugins/platforms/winrt/qwinrtintegration.h
src/plugins/platforms/winrt/qwinrtscreen.cpp
src/plugins/platforms/winrt/qwinrtscreen.h
src/plugins/platforms/winrt/qwinrtwindow.cpp
src/plugins/platforms/winrt/qwinrtwindow.h

index eceba8d002504fda17475cf8522bca9f42bdd298..f771974a244aee45333270b4eb2edc35c1745b88 100644 (file)
@@ -40,6 +40,7 @@
 #include <private/qabstracteventdispatcher_p.h>
 #include <private/qcoreapplication_p.h>
 
+#include <functional>
 #include <wrl.h>
 #include <windows.foundation.h>
 #include <windows.system.threading.h>
@@ -70,6 +71,23 @@ struct WinRTTimerInfo : public QAbstractEventDispatcher::TimerInfo {
     quint64 targetTime;
 };
 
+class AgileDispatchedHandler : public RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>, IDispatchedHandler, IAgileObject>
+{
+public:
+    AgileDispatchedHandler(const std::function<HRESULT()> &delegate)
+        : delegate(delegate)
+    {
+    }
+
+    HRESULT __stdcall Invoke()
+    {
+        return delegate();
+    }
+
+private:
+    std::function<HRESULT()> delegate;
+};
+
 class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
 {
     Q_DECLARE_PUBLIC(QEventDispatcherWinRT)
@@ -80,8 +98,6 @@ public:
 
 private:
     ComPtr<IThreadPoolTimerStatics> timerFactory;
-    ComPtr<ICoreDispatcher> coreDispatcher;
-    QPointer<QThread> thread;
 
     QHash<int, QObject *> timerIdToObject;
     QVector<WinRTTimerInfo> timerInfos;
@@ -136,40 +152,11 @@ private:
         }
         return true;
     }
-
-    void fetchCoreDispatcher()
-    {
-        ComPtr<ICoreImmersiveApplication> application;
-        HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
-                                            IID_PPV_ARGS(&application));
-        RETURN_VOID_IF_FAILED("Failed to get the application factory");
-
-        static ComPtr<ICoreApplicationView> view;
-        if (view)
-            return;
-
-        hr = application->get_MainView(&view);
-        RETURN_VOID_IF_FAILED("Failed to get the main view");
-
-        ComPtr<ICoreApplicationView2> view2;
-        hr = view.As(&view2);
-        RETURN_VOID_IF_FAILED("Failed to cast the main view");
-
-        hr = view2->get_Dispatcher(&coreDispatcher);
-        if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) // expected in thread pool cases
-            return;
-        RETURN_VOID_IF_FAILED("Failed to get core dispatcher");
-
-        thread = QThread::currentThread();
-    }
 };
 
 QEventDispatcherWinRT::QEventDispatcherWinRT(QObject *parent)
     : QAbstractEventDispatcher(*new QEventDispatcherWinRTPrivate, parent)
 {
-    Q_D(QEventDispatcherWinRT);
-
-    d->fetchCoreDispatcher();
 }
 
 QEventDispatcherWinRT::QEventDispatcherWinRT(QEventDispatcherWinRTPrivate &dd, QObject *parent)
@@ -180,25 +167,43 @@ QEventDispatcherWinRT::~QEventDispatcherWinRT()
 {
 }
 
+HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT ()> &delegate)
+{
+    static __declspec(thread) ICoreDispatcher *dispatcher = nullptr;
+    if (!dispatcher) {
+        HRESULT hr;
+        ComPtr<ICoreImmersiveApplication> application;
+        hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+                                    IID_PPV_ARGS(&application));
+        ComPtr<ICoreApplicationView> view;
+        hr = application->get_MainView(&view);
+        Q_ASSERT_SUCCEEDED(hr);
+        ComPtr<ICoreWindow> window;
+        hr = view->get_CoreWindow(&window);
+        Q_ASSERT_SUCCEEDED(hr);
+        hr = window->get_Dispatcher(&dispatcher);
+        Q_ASSERT_SUCCEEDED(hr);
+    }
+
+    HRESULT hr;
+    boolean onXamlThread;
+    hr = dispatcher->get_HasThreadAccess(&onXamlThread);
+    Q_ASSERT_SUCCEEDED(hr);
+    if (onXamlThread) // Already there
+        return delegate();
+
+    ComPtr<IAsyncAction> op;
+    hr = dispatcher->RunAsync(CoreDispatcherPriority_Normal, Make<AgileDispatchedHandler>(delegate).Get(), &op);
+    if (FAILED(hr))
+        return hr;
+    return QWinRTFunctions::await(op);
+}
+
 bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
 {
     Q_D(QEventDispatcherWinRT);
 
-    if (d->thread && d->thread != QThread::currentThread())
-        d->fetchCoreDispatcher();
-
     do {
-        // Process native events
-        if (d->coreDispatcher) {
-            boolean hasThreadAccess;
-            HRESULT hr = d->coreDispatcher->get_HasThreadAccess(&hasThreadAccess);
-            if (SUCCEEDED(hr) && hasThreadAccess) {
-                hr = d->coreDispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
-                if (FAILED(hr))
-                    qErrnoWarning(hr, "Failed to process events");
-            }
-        }
-
         // Additional user events have to be handled before timer events, but the function may not
         // return yet.
         const bool userEventsSent = sendPostedEvents(flags);
@@ -284,10 +289,11 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
 
     TimeSpan period;
     period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
-    IThreadPoolTimer *timer;
     const HANDLE handle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE);
     const HANDLE cancelHandle = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE|EVENT_MODIFY_STATE);
-    HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
+    HRESULT hr = runOnXamlThread([&]() {
+        IThreadPoolTimer *timer;
+        HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
         Callback<ITimerElapsedHandler>([handle, cancelHandle](IThreadPoolTimer *timer) {
             DWORD cancelResult = WaitForSingleObjectEx(cancelHandle, 0, TRUE);
             if (cancelResult == WAIT_OBJECT_0) {
@@ -306,13 +312,15 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
             CloseHandle(cancelHandle);
             return S_OK;
         }).Get(), &timer);
+        RETURN_HR_IF_FAILED("Failed to create periodic timer");
+
+        d->addTimer(timerId, interval, timerType, object, handle, cancelHandle);
+        return hr;
+    });
     if (FAILED(hr)) {
-        qErrnoWarning(hr, "Failed to create periodic timer");
         CloseHandle(handle);
         CloseHandle(cancelHandle);
-        return;
     }
-    d->addTimer(timerId, interval, timerType, object, handle, cancelHandle);
 }
 
 bool QEventDispatcherWinRT::unregisterTimer(int timerId)
index fd3d259c96b08b876e284ae277a16557a40be994..073aa1c121dab7c3aaf1ec2f37e439e026da0c77 100644 (file)
@@ -50,6 +50,8 @@
 
 #include <qt_windows.h>
 
+namespace std { template <typename T> class function; }
+
 QT_BEGIN_NAMESPACE
 
 quint64 qt_msectime();
@@ -65,6 +67,8 @@ public:
     explicit QEventDispatcherWinRT(QObject *parent = 0);
     ~QEventDispatcherWinRT();
 
+    static HRESULT runOnXamlThread(const std::function<HRESULT()> &delegate);
+
     bool processEvents(QEventLoop::ProcessEventsFlags flags);
     bool hasPendingEvents();
 
index 94ce23bd2cddfd186c2b0ca3558f185f902c6da7..707f3bf0ba061585a9697faa75671bc25c3c1cd8 100644 (file)
 
 #include "qwinrtcursor.h"
 #include "qwinrtscreen.h"
+#include <private/qeventdispatcher_winrt_p.h>
 
 #include <QtCore/qfunctions_winrt.h>
 #include <QtGui/QGuiApplication>
 #include <QtGui/QScreen>
 
+#include <functional>
 #include <wrl.h>
 #include <windows.ui.core.h>
 #include <windows.foundation.h>
@@ -77,12 +79,17 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
 {
     Q_D(QWinRTCursor);
 
+    HRESULT hr;
     ICoreWindow *coreWindow = static_cast<QWinRTScreen *>(window->screen()->handle())->coreWindow();
 
     CoreCursorType type;
     switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
     case Qt::BlankCursor:
-        coreWindow->put_PointerCursor(Q_NULLPTR);
+        hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow]() {
+            coreWindow->put_PointerCursor(Q_NULLPTR);
+            return S_OK;
+        });
+        RETURN_VOID_IF_FAILED("Failed to set blank native cursor");
         return;
     default:
     case Qt::OpenHandCursor:
@@ -142,11 +149,13 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
     }
 
     ComPtr<ICoreCursor> cursor;
-    HRESULT hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
+    hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
     RETURN_VOID_IF_FAILED("Failed to create native cursor.");
 
-    hr = coreWindow->put_PointerCursor(cursor.Get());
-    RETURN_VOID_IF_FAILED("Failed to set native cursor.");
+    hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &cursor]() {
+        return coreWindow->put_PointerCursor(cursor.Get());
+    });
+    RETURN_VOID_IF_FAILED("Failed to set native cursor");
 }
 #endif // QT_NO_CURSOR
 
@@ -154,8 +163,12 @@ QPoint QWinRTCursor::pos() const
 {
     ICoreWindow *coreWindow =
             static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle())->coreWindow();
+    HRESULT hr;
     Point point;
-    coreWindow->get_PointerPosition(&point);
+    hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &point]() {
+        return coreWindow->get_PointerPosition(&point);
+    });
+    RETURN_IF_FAILED("Failed to get native cursor position", QPoint());
     return QPoint(point.X, point.Y);
 }
 
index 42ffe8f716b625315fb5daf6de9ee275ada5403b..44aab266ca8f8517d47a446cf4a2b6c3ea0045b9 100644 (file)
 ****************************************************************************/
 
 #include "qwinrteglcontext.h"
+#include "qwinrtwindow.h"
+#include <private/qeventdispatcher_winrt_p.h>
 
+#include <functional>
+
+#include <EGL/egl.h>
 #define EGL_EGLEXT_PROTOTYPES
-#include "EGL/eglext.h"
+#include <EGL/eglext.h>
+
+#include <QOpenGLContext>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
 
 QT_BEGIN_NAMESPACE
 
-QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config)
-    : QEGLPlatformContext(format, share, display, &config), m_eglSurface(surface)
+class QWinRTEGLContextPrivate
+{
+public:
+    QSurfaceFormat format;
+    EGLDisplay eglDisplay;
+    EGLConfig eglConfig;
+    EGLContext eglContext;
+    QHash<QPlatformSurface *, EGLSurface> surfaceForWindow;
+};
+
+QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context)
+    : d_ptr(new QWinRTEGLContextPrivate)
+{
+    Q_D(QWinRTEGLContext);
+    d->format = context->format();
+    d->format.setRenderableType(QSurfaceFormat::OpenGLES);
+}
+
+QWinRTEGLContext::~QWinRTEGLContext()
 {
+    Q_D(QWinRTEGLContext);
+    foreach (const EGLSurface &surface, d->surfaceForWindow)
+        eglDestroySurface(d->eglDisplay, surface);
+    if (d->eglContext != EGL_NO_CONTEXT)
+        eglDestroyContext(d->eglDisplay, d->eglContext);
+    if (d->eglDisplay != EGL_NO_DISPLAY)
+        eglTerminate(d->eglDisplay);
 }
 
-void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface)
+void QWinRTEGLContext::initialize()
 {
-#ifdef Q_OS_WINPHONE
-    const QSize size = surface->surface()->size();
-    eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface),
-                       0, 0, size.width(), size.height());
-#else
-    eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface));
-#endif
+    Q_D(QWinRTEGLContext);
+
+    eglBindAPI(EGL_OPENGL_ES_API);
+    d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (d->eglDisplay == EGL_NO_DISPLAY)
+        qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
+
+    if (!eglInitialize(d->eglDisplay, nullptr, nullptr))
+        qCritical("Failed to initialize EGL: 0x%x", eglGetError());
+
+    d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->format);
+
+    const EGLint flags = d->format.testOption(QSurfaceFormat::DebugContext)
+            ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0;
+    const EGLint attributes[] = {
+        EGL_CONTEXT_CLIENT_VERSION, d->format.majorVersion(),
+        EGL_CONTEXT_MINOR_VERSION_KHR, d->format.minorVersion(),
+        EGL_CONTEXT_FLAGS_KHR, flags,
+        EGL_NONE
+    };
+    d->eglContext = eglCreateContext(d->eglDisplay, d->eglConfig, nullptr, attributes);
+    if (d->eglContext == EGL_NO_CONTEXT) {
+        qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError());
+        return;
+    }
 }
 
-EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface)
 {
-    if (surface->surface()->surfaceClass() == QSurface::Window) {
-        // All windows use the same surface
-        return m_eglSurface;
-    } else {
-        // TODO: return EGL surfaces for offscreen surfaces
-        qWarning("This plugin does not support offscreen surfaces.");
-        return EGL_NO_SURFACE;
+    Q_D(QWinRTEGLContext);
+    Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
+
+    EGLSurface surface = d->surfaceForWindow.value(windowSurface);
+    if (surface == EGL_NO_SURFACE) {
+        QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface);
+        HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() {
+            surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig,
+                                             reinterpret_cast<EGLNativeWindowType>(window->winId()),
+                                             nullptr);
+            if (surface == EGL_NO_SURFACE) {
+                qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
+                return E_FAIL;
+            }
+            return S_OK;
+        });
+        if (FAILED(hr))
+            return false;
+        d->surfaceForWindow.insert(windowSurface, surface);
     }
+
+    const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext);
+    if (!ok) {
+        qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+        return false;
+    }
+
+    eglSwapInterval(d->eglDisplay, d->format.swapInterval());
+    return true;
+}
+
+void QWinRTEGLContext::doneCurrent()
+{
+    Q_D(const QWinRTEGLContext);
+    const bool ok = eglMakeCurrent(d->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    if (!ok)
+        qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+}
+
+void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface)
+{
+    Q_D(QWinRTEGLContext);
+    Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface);
+
+    eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface));
+}
+
+QSurfaceFormat QWinRTEGLContext::format() const
+{
+    Q_D(const QWinRTEGLContext);
+    return d->format;
 }
 
 QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
@@ -221,7 +314,7 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName)
     if (i != standardFuncs.end())
         return i.value();
 
-    return QEGLPlatformContext::getProcAddress(procName);
+    return eglGetProcAddress(procName.constData());
 }
 
 QT_END_NAMESPACE
index 958d623c4cff6d98ff9d02b6da39d866cd967b08..31a2124b034c595a5deba40433072ff5706aa8f0 100644 (file)
 #ifndef QWINDOWSEGLCONTEXT_H
 #define QWINDOWSEGLCONTEXT_H
 
-#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <qpa/qplatformopenglcontext.h>
 
 QT_BEGIN_NAMESPACE
 
-class QWinRTEGLContext : public QEGLPlatformContext
+class QWinRTEGLContextPrivate;
+class QWinRTEGLContext : public QPlatformOpenGLContext
 {
 public:
-    explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config);
+    explicit QWinRTEGLContext(QOpenGLContext *context);
+    ~QWinRTEGLContext();
 
-    void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
-    QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
+    void initialize() Q_DECL_OVERRIDE;
+
+    bool makeCurrent(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
+    void doneCurrent() Q_DECL_OVERRIDE;
+    void swapBuffers(QPlatformSurface *windowSurface) Q_DECL_OVERRIDE;
 
-protected:
-    EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
+    QSurfaceFormat format() const Q_DECL_OVERRIDE;
+    QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
 
 private:
-    EGLSurface m_eglSurface;
+    QScopedPointer<QWinRTEGLContextPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QWinRTEGLContext)
 };
 
 QT_END_NAMESPACE
index c94b53ef1c6cc0af4ed6f30f708a97fc1caa0065..7bd9e87ca6bfcabbbfd5e101259818a415d0154d 100644 (file)
@@ -182,135 +182,6 @@ void QWinRTInputContext::hideInputPanel()
         qErrnoWarning(hr, "Failed to hide input panel.");
 }
 
-#else // Q_OS_WINPHONE
-
-// IRawElementProviderSimple
-HRESULT QWinRTInputContext::get_ProviderOptions(ProviderOptions *retVal)
-{
-    *retVal = ProviderOptions_ServerSideProvider|ProviderOptions_UseComThreading;
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetPatternProvider(PATTERNID id, IUnknown **retVal)
-{
-    switch (id) {
-    case 10002: //UIA_ValuePatternId
-        return QueryInterface(__uuidof(IValueProvider), (void**)retVal);
-        break;
-    case 10014: //UIA_TextPatternId:
-        return QueryInterface(__uuidof(ITextProvider), (void**)retVal);
-    case 10029: //UIA_TextChildPatternId:
-        *retVal = nullptr;
-        break;
-    default:
-        qWarning("Unhandled pattern ID: %d", id);
-        break;
-    }
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal)
-{
-    switch (idProp) {
-    case 30003: //UIA_ControlTypePropertyId
-        retVal->vt = VT_I4;
-        retVal->lVal = 50025; //UIA_CustomControlTypeId
-        break;
-    case 30008: //UIA_IsKeyboardFocusablePropertyId
-    case 30009: //UIA_HasKeyboardFocusPropertyId
-        // These are probably never actually called
-    case 30016: //UIA_IsControlElementPropertyId
-    case 30017: //UIA_IsContentElementPropertyId
-        retVal->vt = VT_BOOL;
-        retVal->boolVal = VARIANT_TRUE;
-        break;
-    case 30019: //UIA_IsPasswordPropertyId
-        retVal->vt = VT_BOOL;
-        retVal->boolVal = VARIANT_FALSE;
-        break;
-    case 30020: //UIA_NativeWindowHandlePropertyId
-        retVal->vt = VT_PTR;
-        retVal->punkVal = m_screen->coreWindow();
-        break;
-    }
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal)
-{
-    // Return the window's element provider
-    IInspectable *hostProvider;
-    HRESULT hr = m_screen->coreWindow()->get_AutomationHostProvider(&hostProvider);
-    if (SUCCEEDED(hr)) {
-        hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal));
-        hostProvider->Release();
-    }
-    return hr;
-}
-
-// ITextProvider
-HRESULT QWinRTInputContext::GetSelection(SAFEARRAY **)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::GetVisibleRanges(SAFEARRAY **)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::RangeFromPoint(UiaPoint, ITextRangeProvider **)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_DocumentRange(ITextRangeProvider **)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_SupportedTextSelection(SupportedTextSelection *)
-{
-    // To be useful, requires listening to the focus object for a selection change and raising an event
-    return S_OK;
-}
-
-// IValueProvider
-HRESULT QWinRTInputContext::SetValue(LPCWSTR)
-{
-    // To be useful, requires listening to the focus object for a value change and raising an event
-    // May be useful for inputPanel autocomplete, etc.
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_Value(BSTR *)
-{
-    // To be useful, requires listening to the focus object for a value change and raising an event
-    // May be useful for inputPanel autocomplete, etc.
-    return S_OK;
-}
-
-HRESULT QWinRTInputContext::get_IsReadOnly(BOOL *isReadOnly)
-{
-    // isReadOnly dictates keyboard opening behavior when view is tapped.
-    // We need to decide if the user tapped within a control which is about to receive focus...
-    // Since this isn't possible (this function gets called before we receive the touch event),
-    // the most platform-aligned option is to show the keyboard if an editable item has focus,
-    // and close the keyboard if it is already open.
-    *isReadOnly = m_isInputPanelVisible || !inputMethodAccepted();
-    return S_OK;
-}
-
-#endif // !Q_OS_WINPHONE
+#endif // Q_OS_WINPHONE
 
 QT_END_NAMESPACE
index ce7fbabf499c3faee2bb1319c0b935e8b9d05595..cc3bce435f45ad3da6fa2360611819fa321ceeed 100644 (file)
@@ -41,9 +41,6 @@
 #include <QtCore/QRectF>
 
 #include <wrl.h>
-#ifndef Q_OS_WINPHONE
-#  include <UIAutomationCore.h>
-#endif
 
 namespace ABI {
     namespace Windows {
@@ -63,11 +60,6 @@ QT_BEGIN_NAMESPACE
 
 class QWinRTScreen;
 class QWinRTInputContext : public QPlatformInputContext
-#ifndef Q_OS_WINPHONE
-                         , public Microsoft::WRL::RuntimeClass<
-                           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
-                           IRawElementProviderSimple, ITextProvider, IValueProvider>
-#endif // !Q_OS_WINPHONE
 {
 public:
     explicit QWinRTInputContext(QWinRTScreen *);
@@ -79,26 +71,7 @@ public:
 #ifdef Q_OS_WINPHONE
     void showInputPanel();
     void hideInputPanel();
-#else // Q_OS_WINPHONE
-    // IRawElementProviderSimple
-    HRESULT __stdcall get_ProviderOptions(ProviderOptions *retVal);
-    HRESULT __stdcall GetPatternProvider(PATTERNID, IUnknown **);
-    HRESULT __stdcall GetPropertyValue(PROPERTYID idProp, VARIANT *retVal);
-    HRESULT __stdcall get_HostRawElementProvider(IRawElementProviderSimple **retVal);
-
-    // ITextProvider
-    HRESULT __stdcall GetSelection(SAFEARRAY **);
-    HRESULT __stdcall GetVisibleRanges(SAFEARRAY **);
-    HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **);
-    HRESULT __stdcall RangeFromPoint(UiaPoint, ITextRangeProvider **);
-    HRESULT __stdcall get_DocumentRange(ITextRangeProvider **);
-    HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *);
-
-    // IValueProvider
-    HRESULT __stdcall SetValue(LPCWSTR);
-    HRESULT __stdcall get_Value(BSTR *);
-    HRESULT __stdcall get_IsReadOnly(BOOL *);
-#endif // !Q_OS_WINPHONE
+#endif
 
 private:
     HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *,
index 70ee6dbe6a2ecef25579c907961bd24cd89f30c7..7079d4652384457a3e678c31683c816912194c55 100644 (file)
 #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
index bbd6c1e41b80e051bc6a3bf3c362417b7fceea9d..0115e034b525e8803416d4b886682cb54307ef40 100644 (file)
 
 #include <qpa/qplatformintegration.h>
 
+namespace ABI {
+    namespace Windows {
+        namespace ApplicationModel {
+            struct ISuspendingEventArgs;
+        }
+        namespace Foundation {
+            struct IAsyncAction;
+        }
+#ifdef Q_OS_WINPHONE
+        namespace Phone {
+            namespace UI {
+                namespace Input {
+                    struct IBackPressedEventArgs;
+                }
+            }
+        }
+#endif
+    }
+}
+struct IAsyncInfo;
+struct IInspectable;
+
 QT_BEGIN_NAMESPACE
 
 class QAbstractEventDispatcher;
-class QWinRTScreen;
 
+class QWinRTIntegrationPrivate;
 class QWinRTIntegration : public QPlatformIntegration
 {
 private:
@@ -53,10 +75,12 @@ public:
 
     static QWinRTIntegration *create()
     {
-        QWinRTIntegration *integration = new QWinRTIntegration;
-        return integration->m_success ? integration : 0;
+        QScopedPointer<QWinRTIntegration> integration(new QWinRTIntegration);
+        return integration->succeeded() ? integration.take() : nullptr;
     }
 
+    bool succeeded() const;
+
     bool hasCapability(QPlatformIntegration::Capability cap) const;
     QVariant styleHint(StyleHint hint) const;
 
@@ -71,11 +95,16 @@ public:
 
     QStringList themeNames() const;
     QPlatformTheme *createPlatformTheme(const QString &name) const;
+
 private:
-    bool m_success;
-    QWinRTScreen *m_screen;
-    QPlatformFontDatabase *m_fontDatabase;
-    QPlatformServices *m_services;
+#ifdef Q_OS_WINPHONE
+    HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
+#endif
+    HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
+    HRESULT onResume(IInspectable *, IInspectable *);
+
+    QScopedPointer<QWinRTIntegrationPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QWinRTIntegration)
 };
 
 QT_END_NAMESPACE
index 1d36bb31f6c4c621618f872e41bb2b9bbf3a4929..89ad33657b8c83d0663837a04fdd018f918461c5 100644 (file)
 
 #include "qwinrtscreen.h"
 
-#define EGL_EGLEXT_PROTOTYPES
-#include <EGL/eglext.h>
-#include <d3d11.h>
-#include <dxgi1_2.h>
-#ifndef Q_OS_WINPHONE
-#include <dxgi1_3.h>
-#endif
-
 #include "qwinrtbackingstore.h"
 #include "qwinrtinputcontext.h"
 #include "qwinrtcursor.h"
-#include "qwinrteglcontext.h"
+#include <private/qeventdispatcher_winrt_p.h>
 
 #include <QtGui/QSurfaceFormat>
 #include <QtGui/QGuiApplication>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
 #include <qpa/qwindowsysteminterface.h>
 #include <QtCore/qt_windows.h>
 #include <QtCore/qfunctions_winrt.h>
 
+#include <functional>
 #include <wrl.h>
 #include <windows.system.h>
 #include <Windows.Applicationmodel.h>
 #include <windows.ui.h>
 #include <windows.ui.core.h>
 #include <windows.ui.input.h>
+#include <windows.ui.xaml.h>
 #include <windows.ui.viewmanagement.h>
 #include <windows.graphics.display.h>
 #include <windows.foundation.h>
-#ifdef Q_OS_WINPHONE
-#include <windows.phone.ui.input.h>
-#endif
 
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
@@ -77,17 +67,13 @@ using namespace ABI::Windows::ApplicationModel;
 using namespace ABI::Windows::ApplicationModel::Core;
 using namespace ABI::Windows::Foundation;
 using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI;
 using namespace ABI::Windows::UI::Core;
 using namespace ABI::Windows::UI::Input;
 using namespace ABI::Windows::UI::ViewManagement;
 using namespace ABI::Windows::Devices::Input;
 using namespace ABI::Windows::Graphics::Display;
-#ifdef Q_OS_WINPHONE
-using namespace ABI::Windows::Phone::UI::Input;
-#endif
 
-typedef IEventHandler<IInspectable*> ResumeHandler;
-typedef IEventHandler<SuspendingEventArgs*> SuspendHandler;
 typedef ITypedEventHandler<CoreWindow*, WindowActivatedEventArgs*> ActivatedHandler;
 typedef ITypedEventHandler<CoreWindow*, CoreWindowEventArgs*> ClosedHandler;
 typedef ITypedEventHandler<CoreWindow*, CharacterReceivedEventArgs*> CharacterReceivedHandler;
@@ -96,11 +82,7 @@ typedef ITypedEventHandler<CoreWindow*, KeyEventArgs*> KeyHandler;
 typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
 typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
 typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
-typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
 typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
-#ifdef Q_OS_WINPHONE
-typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
-#endif
 
 QT_BEGIN_NAMESPACE
 
@@ -419,33 +401,23 @@ static inline Qt::Key qKeyFromCode(quint32 code, int mods)
     return static_cast<Qt::Key>(code & 0xff);
 }
 
-typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
-uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
 typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken);
 uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
 typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
 uint qHash(DisplayCallbackRemover 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 QWinRTScreenPrivate
 {
 public:
-    ComPtr<ICoreApplication> application;
+    QTouchDevice *touchDevice;
     ComPtr<ICoreWindow> coreWindow;
+    ComPtr<Xaml::IDependencyObject> canvas;
+    ComPtr<IApplicationView> view;
     ComPtr<IDisplayInformation> displayInformation;
-#ifdef Q_OS_WINPHONE
-    ComPtr<IHardwareButtonsStatics> hardwareButtons;
-#endif
 
     QScopedPointer<QWinRTCursor> cursor;
-#ifdef Q_OS_WINPHONE
-    QScopedPointer<QWinRTInputContext> inputContext;
-#else
-    ComPtr<QWinRTInputContext> inputContext;
-#endif
+
+    QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
 
     QSizeF logicalSize;
     QSurfaceFormat surfaceFormat;
@@ -458,68 +430,30 @@ public:
 #ifndef Q_OS_WINPHONE
     QHash<quint32, QPair<Qt::Key, QString>> activeKeys;
 #endif
-    QTouchDevice *touchDevice;
-    QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
 
-    EGLDisplay eglDisplay;
-    EGLSurface eglSurface;
-    EGLConfig eglConfig;
-
-    QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
     QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
     QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
-#ifdef Q_OS_WINPHONE
-    QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
-#endif
 };
 
-QWinRTScreen::QWinRTScreen()
+// To be called from the XAML thread
+QWinRTScreen::QWinRTScreen(Xaml::IWindow *xamlWindow)
     : d_ptr(new QWinRTScreenPrivate)
 {
     Q_D(QWinRTScreen);
     d->orientation = Qt::PrimaryOrientation;
     d->touchDevice = Q_NULLPTR;
-    d->eglDisplay = EGL_NO_DISPLAY;
 
-    // Obtain the WinRT Application, view, and window
     HRESULT hr;
-    hr = RoGetActivationFactory(Wrappers::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, &QWinRTScreen::onSuspended).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
-    Q_ASSERT_SUCCEEDED(hr);
-    hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
-    Q_ASSERT_SUCCEEDED(hr);
-
-    ComPtr<ICoreApplicationView> view;
-    hr = d->application->GetCurrentView(&view);
-    Q_ASSERT_SUCCEEDED(hr);
-    hr = view->get_CoreWindow(&d->coreWindow);
+    hr = xamlWindow->get_CoreWindow(&d->coreWindow);
     Q_ASSERT_SUCCEEDED(hr);
     hr = d->coreWindow->Activate();
     Q_ASSERT_SUCCEEDED(hr);
 
-#ifdef Q_OS_WINPHONE
-    d->inputContext.reset(new QWinRTInputContext(this));
-#else
-    d->inputContext = Make<QWinRTInputContext>(this);
-#endif
-
     Rect rect;
     hr = d->coreWindow->get_Bounds(&rect);
     Q_ASSERT_SUCCEEDED(hr);
     d->logicalSize = QSizeF(rect.Width, rect.Height);
 
-    d->surfaceFormat.setAlphaBufferSize(0);
-    d->surfaceFormat.setRedBufferSize(8);
-    d->surfaceFormat.setGreenBufferSize(8);
-    d->surfaceFormat.setBlueBufferSize(8);
-    d->surfaceFormat.setDepthBufferSize(24);
-    d->surfaceFormat.setStencilBufferSize(8);
-    d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
-    d->surfaceFormat.setSamples(1);
-    d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
-
     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]);
@@ -538,24 +472,14 @@ QWinRTScreen::QWinRTScreen()
     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);
-    hr = d->coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &d->windowTokens[&ICoreWindow::remove_AutomationProviderRequested]);
-    Q_ASSERT_SUCCEEDED(hr);
-#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, &QWinRTScreen::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
-    Q_ASSERT_SUCCEEDED(hr);
-#endif // Q_OS_WINPHONE
 
     // Orientation handling
     ComPtr<IDisplayInformationStatics> displayInformationStatics;
@@ -583,45 +507,34 @@ QWinRTScreen::QWinRTScreen()
     d->orientation = d->nativeOrientation;
     onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
 
-    d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (d->eglDisplay == EGL_NO_DISPLAY)
-        qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
-
-    if (!eglInitialize(d->eglDisplay, NULL, NULL))
-        qCritical("Failed to initialize EGL: 0x%x", eglGetError());
-
-    // Check that the device properly supports depth/stencil rendering, and disable them if not
-    ComPtr<ID3D11Device> d3dDevice;
-    const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
-    if (ok && d3dDevice) {
-        ComPtr<IDXGIDevice> dxgiDevice;
-        hr = d3dDevice.As(&dxgiDevice);
-        if (SUCCEEDED(hr)) {
-            ComPtr<IDXGIAdapter> dxgiAdapter;
-            hr = dxgiDevice->GetAdapter(&dxgiAdapter);
-            if (SUCCEEDED(hr)) {
-                ComPtr<IDXGIAdapter2> dxgiAdapter2;
-                hr = dxgiAdapter.As(&dxgiAdapter2);
-                if (SUCCEEDED(hr)) {
-                    DXGI_ADAPTER_DESC2 desc;
-                    hr = dxgiAdapter2->GetDesc2(&desc);
-                    if (SUCCEEDED(hr)) {
-                        // The following GPUs do not render properly with depth/stencil
-                        if ((desc.VendorId == 0x4d4f4351 && desc.DeviceId == 0x32303032)) { // Qualcomm Adreno 225
-                            d->surfaceFormat.setDepthBufferSize(-1);
-                            d->surfaceFormat.setStencilBufferSize(-1);
-                        }
-                    }
-                }
-            }
-        }
-    }
+    ComPtr<IApplicationViewStatics2> applicationViewStatics;
+    hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
+                                IID_PPV_ARGS(&applicationViewStatics));
+    RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
 
-    d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->surfaceFormat);
-    d->surfaceFormat = q_glFormatFromConfig(d->eglDisplay, d->eglConfig, d->surfaceFormat);
-    d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), NULL);
-    if (d->eglSurface == EGL_NO_SURFACE)
-        qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
+    hr = applicationViewStatics->GetForCurrentView(&d->view);
+    RETURN_VOID_IF_FAILED("Could not access currentView");
+
+    // Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added
+    ComPtr<Xaml::Controls::ICanvas> canvas;
+    hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas);
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<Xaml::IFrameworkElement> frameworkElement;
+    hr = canvas.As(&frameworkElement);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = frameworkElement->put_Width(d->logicalSize.width());
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = frameworkElement->put_Height(d->logicalSize.height());
+    Q_ASSERT_SUCCEEDED(hr);
+    ComPtr<Xaml::IUIElement> uiElement;
+    hr = canvas.As(&uiElement);
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = xamlWindow->put_Content(uiElement.Get());
+    Q_ASSERT_SUCCEEDED(hr);
+    hr = canvas.As(&d->canvas);
+    Q_ASSERT_SUCCEEDED(hr);
+
+    d->cursor.reset(new QWinRTCursor);
 }
 
 QWinRTScreen::~QWinRTScreen()
@@ -629,16 +542,20 @@ QWinRTScreen::~QWinRTScreen()
     Q_D(QWinRTScreen);
 
     // Unregister callbacks
-    for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i)
-        (d->application.Get()->*i.key())(i.value());
-    for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i)
-        (d->coreWindow.Get()->*i.key())(i.value());
-    for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i)
-        (d->displayInformation.Get()->*i.key())(i.value());
-#ifdef Q_OS_WINPHONE
-    for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i)
-        (d->hardwareButtons.Get()->*i.key())(i.value());
-#endif
+    HRESULT hr;
+    hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+        HRESULT hr;
+        for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i) {
+            hr = (d->coreWindow.Get()->*i.key())(i.value());
+            Q_ASSERT_SUCCEEDED(hr);
+        }
+        for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i) {
+            hr = (d->displayInformation.Get()->*i.key())(i.value());
+            Q_ASSERT_SUCCEEDED(hr);
+        }
+        return hr;
+    });
+    RETURN_VOID_IF_FAILED("Failed to unregister screen event callbacks");
 }
 
 QRect QWinRTScreen::geometry() const
@@ -657,12 +574,6 @@ QImage::Format QWinRTScreen::format() const
     return QImage::Format_ARGB32_Premultiplied;
 }
 
-QSurfaceFormat QWinRTScreen::surfaceFormat() const
-{
-    Q_D(const QWinRTScreen);
-    return d->surfaceFormat;
-}
-
 QSizeF QWinRTScreen::physicalSize() const
 {
     Q_D(const QWinRTScreen);
@@ -682,21 +593,9 @@ qreal QWinRTScreen::scaleFactor() const
     return d->scaleFactor;
 }
 
-QWinRTInputContext *QWinRTScreen::inputContext() const
-{
-    Q_D(const QWinRTScreen);
-#ifdef Q_OS_WINPHONE
-    return d->inputContext.data();
-#else
-    return d->inputContext.Get();
-#endif
-}
-
 QPlatformCursor *QWinRTScreen::cursor() const
 {
     Q_D(const QWinRTScreen);
-    if (!d->cursor)
-        const_cast<QWinRTScreenPrivate *>(d)->cursor.reset(new QWinRTCursor);
     return d->cursor.data();
 }
 
@@ -744,22 +643,10 @@ ICoreWindow *QWinRTScreen::coreWindow() const
     return d->coreWindow.Get();
 }
 
-EGLDisplay QWinRTScreen::eglDisplay() const
-{
-    Q_D(const QWinRTScreen);
-    return d->eglDisplay;
-}
-
-EGLSurface QWinRTScreen::eglSurface() const
-{
-    Q_D(const QWinRTScreen);
-    return d->eglSurface;
-}
-
-EGLConfig QWinRTScreen::eglConfig() const
+Xaml::IDependencyObject *QWinRTScreen::canvas() const
 {
     Q_D(const QWinRTScreen);
-    return d->eglConfig;
+    return d->canvas.Get();
 }
 
 QWindow *QWinRTScreen::topWindow() const
@@ -809,6 +696,20 @@ void QWinRTScreen::lower(QWindow *window)
     handleExpose();
 }
 
+void QWinRTScreen::updateWindowTitle()
+{
+    Q_D(QWinRTScreen);
+
+    QWindow *window = topWindow();
+    if (!window)
+        return;
+
+    const QString title = window->title();
+    HStringReference titleRef(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
+    HRESULT hr = d->view->put_Title(titleRef.Get());
+    RETURN_VOID_IF_FAILED("Unable to set window title");
+}
+
 void QWinRTScreen::handleExpose()
 {
     Q_D(QWinRTScreen);
@@ -1055,17 +956,6 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
     return S_OK;
 }
 
-HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
-{
-#ifndef Q_OS_WINPHONE
-    Q_D(const QWinRTScreen);
-    args->put_AutomationProvider(d->inputContext.Get());
-#else
-    Q_UNUSED(args)
-#endif
-    return S_OK;
-}
-
 HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *)
 {
     Q_D(QWinRTScreen);
@@ -1075,18 +965,14 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
     hr = d->coreWindow->get_Bounds(&size);
     RETURN_OK_IF_FAILED("Failed to get window bounds");
     QSizeF logicalSize = QSizeF(size.Width, size.Height);
-#ifndef Q_OS_WINPHONE // This handler is called from orientation changed, in which case we should always update the size
     if (d->logicalSize == logicalSize)
         return S_OK;
-#endif
 
     d->logicalSize = logicalSize;
-    if (d->eglDisplay) {
-        const QRect newGeometry = geometry();
-        QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
-        QPlatformScreen::resizeMaximizedWindows();
-        handleExpose();
-    }
+    const QRect newGeometry = geometry();
+    QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
+    QPlatformScreen::resizeMaximizedWindows();
+    handleExpose();
     return S_OK;
 }
 
@@ -1110,31 +996,6 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args
     return S_OK;
 }
 
-HRESULT QWinRTScreen::onSuspended(IInspectable *, ISuspendingEventArgs *)
-{
-#ifndef Q_OS_WINPHONE
-    Q_D(QWinRTScreen);
-    ComPtr<ID3D11Device> d3dDevice;
-    const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf());
-    if (ok && d3dDevice) {
-        ComPtr<IDXGIDevice3> dxgiDevice;
-        if (SUCCEEDED(d3dDevice.As(&dxgiDevice)))
-            dxgiDevice->Trim();
-    }
-#endif
-    QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
-    QWindowSystemInterface::flushWindowSystemEvents();
-    return S_OK;
-}
-
-HRESULT QWinRTScreen::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;
-}
-
 HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
 {
     foreach (QWindow *w, QGuiApplication::topLevelWindows())
@@ -1165,10 +1026,6 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *
         d->orientation = newOrientation;
         QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
     }
-
-#ifdef Q_OS_WINPHONE // The size changed handler is ignored in favor of this callback
-    onSizeChanged(Q_NULLPTR, Q_NULLPTR);
-#endif
     return S_OK;
 }
 
@@ -1205,27 +1062,4 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
     return S_OK;
 }
 
-#ifdef Q_OS_WINPHONE
-HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
-{
-    Q_D(QWinRTScreen);
-
-    QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
-    QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
-    backPress.setAccepted(false);
-    backRelease.setAccepted(false);
-
-    QObject *receiver = d->visibleWindows.isEmpty()
-            ? static_cast<QObject *>(QGuiApplication::instance())
-            : static_cast<QObject *>(d->visibleWindows.first());
-
-    // If the event is ignored, the app will suspend
-    QGuiApplication::sendEvent(receiver, &backPress);
-    QGuiApplication::sendEvent(receiver, &backRelease);
-    args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
-
-    return S_OK;
-}
-#endif // Q_OS_WINPHONE
-
 QT_END_NAMESPACE
index d34ce75748e5a06e5c61dc8bc314b92932237ed0..796e6abb80925dcbea07d082f59a6ab87a3f936a 100644 (file)
@@ -40,8 +40,6 @@
 #include <qpa/qplatformscreen.h>
 #include <qpa/qwindowsysteminterface.h>
 
-#include <EGL/egl.h>
-
 namespace ABI {
     namespace Windows {
         namespace ApplicationModel {
@@ -59,21 +57,16 @@ namespace ABI {
                 struct IWindowActivatedEventArgs;
                 struct IWindowSizeChangedEventArgs;
             }
+            namespace Xaml {
+                struct IDependencyObject;
+                struct IWindow;
+            }
         }
         namespace Graphics {
             namespace Display {
                 struct IDisplayInformation;
             }
         }
-#ifdef Q_OS_WINPHONE
-        namespace Phone {
-            namespace UI {
-                namespace Input {
-                    struct IBackPressedEventArgs;
-                }
-            }
-        }
-#endif
     }
 }
 struct IInspectable;
@@ -81,23 +74,20 @@ struct IInspectable;
 QT_BEGIN_NAMESPACE
 
 class QTouchDevice;
-class QWinRTEGLContext;
 class QWinRTCursor;
 class QWinRTInputContext;
 class QWinRTScreenPrivate;
 class QWinRTScreen : public QPlatformScreen
 {
 public:
-    explicit QWinRTScreen();
+    explicit QWinRTScreen(ABI::Windows::UI::Xaml::IWindow *xamlWindow);
     ~QWinRTScreen();
     QRect geometry() const;
     int depth() const;
     QImage::Format format() const;
-    QSurfaceFormat surfaceFormat() const;
     QSizeF physicalSize() const Q_DECL_OVERRIDE;
     QDpi logicalDpi() const Q_DECL_OVERRIDE;
     qreal scaleFactor() const;
-    QWinRTInputContext *inputContext() const;
     QPlatformCursor *cursor() const;
     Qt::KeyboardModifiers keyboardModifiers() const;
 
@@ -110,10 +100,10 @@ public:
     void raise(QWindow *window);
     void lower(QWindow *window);
 
+    void updateWindowTitle();
+
     ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
-    EGLDisplay eglDisplay() const; // To opengl context
-    EGLSurface eglSurface() const; // To window
-    EGLConfig eglConfig() const;
+    ABI::Windows::UI::Xaml::IDependencyObject *canvas() const;
 
 private:
     void handleExpose();
@@ -127,20 +117,13 @@ private:
     HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
 
     HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *);
-    HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
-    HRESULT onResume(IInspectable *, IInspectable *);
 
     HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *);
     HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *);
-    HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *);
 
     HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
     HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
 
-#ifdef Q_OS_WINPHONE
-    HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
-#endif
-
     QScopedPointer<QWinRTScreenPrivate> d_ptr;
     Q_DECLARE_PRIVATE(QWinRTScreen)
 };
index adc5dfb776182877c257e4da247a8077d58efaef..634d62ef249e58508994361e5e1e1c30e9a972b7 100644 (file)
 
 #include "qwinrtwindow.h"
 #include "qwinrtscreen.h"
+#include <private/qeventdispatcher_winrt_p.h>
 
-#include <qpa/qwindowsysteminterface.h>
+#include <EGL/egl.h>
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/eglext.h>
+
+#include <qfunctions_winrt.h>
 #include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
 #include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
 #include <QtGui/QOpenGLContext>
+#include <QtGui/QWindow>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
 
-#include <qfunctions_winrt.h>
-#include <windows.ui.viewmanagement.h>
+#include <functional>
 #include <wrl.h>
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.controls.h>
+#include <windows.ui.viewmanagement.h>
 
 using namespace ABI::Windows::UI::ViewManagement;
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI;
 
 QT_BEGIN_NAMESPACE
 
+class QWinRTWindowPrivate
+{
+public:
+    QWinRTScreen *screen;
+
+    QSurfaceFormat surfaceFormat;
+    QString windowTitle;
+
+    ComPtr<Xaml::Controls::ISwapChainPanel> swapChainPanel;
+};
+
 QWinRTWindow::QWinRTWindow(QWindow *window)
     : QPlatformWindow(window)
-    , m_screen(static_cast<QWinRTScreen*>(screen()))
+    , d_ptr(new QWinRTWindowPrivate)
 {
+    Q_D(QWinRTWindow);
+
+    d->screen = static_cast<QWinRTScreen *>(screen());
     setWindowFlags(window->flags());
     setWindowState(window->windowState());
     setWindowTitle(window->title());
     handleContentOrientationChange(window->contentOrientation());
+
+    d->surfaceFormat.setAlphaBufferSize(0);
+    d->surfaceFormat.setRedBufferSize(8);
+    d->surfaceFormat.setGreenBufferSize(8);
+    d->surfaceFormat.setBlueBufferSize(8);
+    d->surfaceFormat.setDepthBufferSize(24);
+    d->surfaceFormat.setStencilBufferSize(8);
+    d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+    d->surfaceFormat.setSamples(1);
+    d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+
+    HRESULT hr;
+    hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+        // Create a new swapchain and place it inside the canvas
+        HRESULT hr;
+        hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
+                                &d->swapChainPanel);
+        Q_ASSERT_SUCCEEDED(hr);
+        ComPtr<Xaml::IUIElement> uiElement;
+        hr = d->swapChainPanel.As(&uiElement);
+        Q_ASSERT_SUCCEEDED(hr);
+
+        ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
+        ComPtr<Xaml::Controls::IPanel> panel;
+        hr = canvas.As(&panel);
+        Q_ASSERT_SUCCEEDED(hr);
+        ComPtr<IVector<Xaml::UIElement *>> children;
+        hr = panel->get_Children(&children);
+        Q_ASSERT_SUCCEEDED(hr);
+        hr = children->Append(uiElement.Get());
+        Q_ASSERT_SUCCEEDED(hr);
+        return S_OK;
+    });
+    Q_ASSERT_SUCCEEDED(hr);
+
     setGeometry(window->geometry());
 }
 
 QWinRTWindow::~QWinRTWindow()
 {
-    m_screen->removeWindow(window());
+    Q_D(QWinRTWindow);
+
+    HRESULT hr;
+    hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+        HRESULT hr;
+        ComPtr<Xaml::IDependencyObject> canvas = d->screen->canvas();
+        ComPtr<Xaml::Controls::IPanel> panel;
+        hr = canvas.As(&panel);
+        Q_ASSERT_SUCCEEDED(hr);
+        ComPtr<IVector<Xaml::UIElement *>> children;
+        hr = panel->get_Children(&children);
+        Q_ASSERT_SUCCEEDED(hr);
+
+        ComPtr<Xaml::IUIElement> uiElement;
+        hr = d->swapChainPanel.As(&uiElement);
+        Q_ASSERT_SUCCEEDED(hr);
+        quint32 index;
+        boolean found;
+        hr = children->IndexOf(uiElement.Get(), &index, &found);
+        Q_ASSERT_SUCCEEDED(hr);
+        if (found) {
+            hr = children->RemoveAt(index);
+            Q_ASSERT_SUCCEEDED(hr);
+        }
+        return S_OK;
+    });
+    RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down");
 }
 
 QSurfaceFormat QWinRTWindow::format() const
 {
-    return m_screen->surfaceFormat();
+    Q_D(const QWinRTWindow);
+    return d->surfaceFormat;
 }
 
 bool QWinRTWindow::isActive() const
 {
-    return m_screen->topWindow() == window();
+    Q_D(const QWinRTWindow);
+    return d->screen->topWindow() == window();
 }
 
 bool QWinRTWindow::isExposed() const
@@ -87,55 +178,70 @@ bool QWinRTWindow::isExposed() const
 
 void QWinRTWindow::setGeometry(const QRect &rect)
 {
+    Q_D(QWinRTWindow);
+
     if (window()->isTopLevel()) {
-        QPlatformWindow::setGeometry(m_screen->geometry());
+        QPlatformWindow::setGeometry(d->screen->geometry());
         QWindowSystemInterface::handleGeometryChange(window(), geometry());
     } else {
         QPlatformWindow::setGeometry(rect);
         QWindowSystemInterface::handleGeometryChange(window(), rect);
     }
+
+    HRESULT hr;
+    hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+        HRESULT hr;
+        ComPtr<Xaml::IFrameworkElement> frameworkElement;
+        hr = d->swapChainPanel.As(&frameworkElement);
+        Q_ASSERT_SUCCEEDED(hr);
+        const QSizeF size = QSizeF(geometry().size()) / d->screen->scaleFactor();
+        hr = frameworkElement->put_Width(size.width());
+        Q_ASSERT_SUCCEEDED(hr);
+        hr = frameworkElement->put_Height(size.height());
+        Q_ASSERT_SUCCEEDED(hr);
+        return S_OK;
+    });
+    Q_ASSERT_SUCCEEDED(hr);
 }
 
 void QWinRTWindow::setVisible(bool visible)
 {
+    Q_D(QWinRTWindow);
     if (!window()->isTopLevel())
         return;
     if (visible)
-        m_screen->addWindow(window());
+        d->screen->addWindow(window());
     else
-        m_screen->removeWindow(window());
+        d->screen->removeWindow(window());
 }
 
 void QWinRTWindow::setWindowTitle(const QString &title)
 {
-    ComPtr<IApplicationViewStatics2> statics;
-    HRESULT hr;
-
-    hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
-                              IID_PPV_ARGS(&statics));
-    RETURN_VOID_IF_FAILED("Could not get ApplicationViewStatics");
-
-    ComPtr<IApplicationView> view;
-    hr = statics->GetForCurrentView(&view);
-    RETURN_VOID_IF_FAILED("Could not access currentView");
-
-    HStringReference str(reinterpret_cast<LPCWSTR>(title.utf16()), title.length());
-    hr = view->put_Title(str.Get());
-    RETURN_VOID_IF_FAILED("Unable to set window title");
+    Q_D(QWinRTWindow);
+    d->windowTitle = title;
+    d->screen->updateWindowTitle();
 }
 
 void QWinRTWindow::raise()
 {
+    Q_D(QWinRTWindow);
     if (!window()->isTopLevel())
         return;
-    m_screen->raise(window());
+    d->screen->raise(window());
 }
 
 void QWinRTWindow::lower()
 {
+    Q_D(QWinRTWindow);
     if (!window()->isTopLevel())
         return;
-    m_screen->lower(window());
+    d->screen->lower(window());
+}
+
+WId QWinRTWindow::winId() const
+{
+    Q_D(const QWinRTWindow);
+    return WId(d->swapChainPanel.Get());
 }
 
 qreal QWinRTWindow::devicePixelRatio() const
index 3cfe346ab2dbe3310a14c3d735e0dcb1b7503dfd..88c149b08023d06307bebb158e58acc49f620301 100644 (file)
@@ -42,8 +42,7 @@
 
 QT_BEGIN_NAMESPACE
 
-class QWinRTScreen;
-
+class QWinRTWindowPrivate;
 class QWinRTWindow : public QPlatformWindow
 {
 public:
@@ -59,10 +58,13 @@ public:
     void raise();
     void lower();
 
+    WId winId() const Q_DECL_OVERRIDE;
+
     qreal devicePixelRatio() const Q_DECL_OVERRIDE;
 
 private:
-    QWinRTScreen *m_screen;
+    QScopedPointer<QWinRTWindowPrivate> d_ptr;
+    Q_DECLARE_PRIVATE(QWinRTWindow)
 };
 
 QT_END_NAMESPACE