From 47c2d76dbab76fc33ca6c73ac701d6814d861f89 Mon Sep 17 00:00:00 2001
From: Andrew Knight <andrew.knight@theqtcompany.com>
Date: Fri, 14 Nov 2014 11:51:49 +0200
Subject: [PATCH] winrt: Resize window on Windows Phone using EGL

To avoid duplicating code in ANGLE, we can resize the framebuffer in QPA.
This potentially allows us to synchronize rendering to avoid displaying
a frame which is rendered for the new geometry but is displayed with the
old geometry.

Change-Id: I5f3a0634628d9ea4ca73349a02e646eb043bd757
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
---
 src/plugins/platforms/winrt/qwinrtscreen.cpp | 46 ++++++++++++++------
 1 file changed, 33 insertions(+), 13 deletions(-)

diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 681307ddcf3..fadcd01b066 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -473,6 +473,7 @@ QWinRTScreen::QWinRTScreen()
     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;
@@ -531,8 +532,10 @@ 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]);
@@ -610,7 +613,14 @@ QWinRTScreen::QWinRTScreen()
 
     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);
+    const QRect bounds = geometry();
+    EGLint windowAttributes[] = {
+        EGL_FIXED_SIZE_ANGLE, EGL_TRUE,
+        EGL_WIDTH, bounds.width(),
+        EGL_HEIGHT, bounds.height(),
+        EGL_NONE
+    };
+    d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), windowAttributes);
     if (d->eglSurface == EGL_NO_SURFACE)
         qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
 }
@@ -1051,26 +1061,33 @@ HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationPr
     return S_OK;
 }
 
-HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
+HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *)
 {
     Q_D(QWinRTScreen);
 
-    Size size;
-    HRESULT hr = args->get_Size(&size);
-    RETURN_OK_IF_FAILED("Failed to get window size.");
-
+    Rect size;
+    HRESULT hr;
+    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
 
-    // Regardless of state, all top-level windows are viewport-sized - this might change if
-    // a more advanced compositor is written.
     d->logicalSize = logicalSize;
-    const QRect newGeometry = geometry();
-    QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
-    QPlatformScreen::resizeMaximizedWindows();
-    handleExpose();
-
+    if (d->eglDisplay) {
+        const QRect newGeometry = geometry();
+#ifdef Q_OS_WINPHONE // Resize the EGL window
+        const int width = newGeometry.width() * (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::LandscapeOrientation ? -1 : 1);
+        const int height = newGeometry.height() * (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::InvertedLandscapeOrientation ? -1 : 1);
+        eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_WIDTH, width);
+        eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_HEIGHT, height);
+#endif
+        QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
+        QPlatformScreen::resizeMaximizedWindows();
+        handleExpose();
+    }
     return S_OK;
 }
 
@@ -1140,6 +1157,9 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *
         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;
 }
 
-- 
GitLab