File xcb-compare-to-previous-state-when-sending-geometry.patch of Package libqt5-qtbase.1959

From 56f6252e7285c9c61a99416fa2a8571fd67c597f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?=
 <tor.arne.vestbo@theqtcompany.com>
Date: Tue, 1 Dec 2015 16:27:09 +0100
Subject: [PATCH] xcb: compare to previous state when sending geometry and
 expose events
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

By calculating the previous geometry and passing it on when calling
handleGeometryChange we can detect cases where setGeometry() on a
QWindow didn't result in the expected geometry. The new (actual)
geometry is delivered as a resize event.

This also allows us to only send expose events when the size of the
window has actually changed (instead of also sending when the window
has just moved).

Due to the async delivery of geometry changes on the xcb platform we
need to avoid using QWindowPrivate's cached state of the geometry, as
that will result in duplicate resize events when events are not flushed
in between two system resize events coming in with the same size.

Change-Id: I3d4abe4a1095dd96e6e354288d5b646c623c30dd
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
---
 src/plugins/platforms/xcb/qxcbwindow.cpp | 33 ++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

Index: b/src/plugins/platforms/xcb/qxcbwindow.cpp
===================================================================
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1950,21 +1950,39 @@ void QXcbWindow::handleConfigureNotifyEv
         }
     }
 
-    const QRect rect = QRect(pos, QSize(event->width, event->height));
-    QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(rect);
+    // The original geometry requested by setGeometry() might be different
+    // from what we end up with after applying window constraints.
+    QRect requestedGeometry = geometry();
+
+    const QRect actualGeometry = QRect(pos, QSize(event->width, event->height));
+    QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry);
 
     QXcbScreen *currentScreen = m_xcbScreen;
     m_xcbScreen = static_cast<QXcbScreen*>(newScreen);
     if (!newScreen)
         return;
 
-    QPlatformWindow::setGeometry(rect);
-    QWindowSystemInterface::handleGeometryChange(window(), rect);
+    // Persist the actual geometry so that QWindow::geometry() can
+    // be queried in the resize event.
+    QPlatformWindow::setGeometry(actualGeometry);
+
+    // FIXME: In the case of the requestedGeometry not matching the actualGeometry due
+    // to e.g. the window manager applying restrictions to the geometry, the application
+    // will never see a move/resize event if the actualGeometry is the same as the current
+    // geometry, and may think the requested geometry was fulfilled.
+    QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
+
     if (newScreen != currentScreen)
         QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
 
-    if (m_mapped)
-        QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
+    // For expose events we have no way of telling QGuiApplication to used the locally
+    // cached version of the previous state, so we may in some situations end up with
+    // an additional expose event.
+    QRect previousGeometry = requestedGeometry != actualGeometry ?
+        requestedGeometry : qt_window_private(window())->geometry;
+
+    if (m_mapped && actualGeometry.size() != previousGeometry.size())
+        QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size()));
 
     if (m_usingSyncProtocol && m_syncState == SyncReceived)
         m_syncState = SyncAndConfigureReceived;