From dce13e4b7b0d6cf04879fc3b1f2a241579296e73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@digia.com>
Date: Wed, 22 Oct 2014 13:29:52 +0200
Subject: [PATCH] Fix too many resizes and move events for native widgets

When the QWidgetWindow receives a resize or move event, it should check
with the widget if its crect already has this geometry. if not then send
the resize or move event

Ideally events should be sent whenever the QWidgetWindow receives them.
QTBUG-42383 is created for this problem

Task-number: QTBUG-29937
Task-number: QTBUG-38768
Task-number: QTBUG-30744
Change-Id: I1e9a5d25de29a98885edece927ba14d7a763eb01
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
---
 src/widgets/dialogs/qwizard.cpp               |   8 ++
 src/widgets/kernel/qwidget.cpp                |   5 +-
 src/widgets/kernel/qwidgetwindow.cpp          |  53 ++++++---
 src/widgets/kernel/qwidgetwindow_p.h          |   4 +-
 .../qwidget_window/tst_qwidget_window.cpp     | 101 ++++++++++++++++++
 5 files changed, 151 insertions(+), 20 deletions(-)
 mode change 100755 => 100644 tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp

diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index 1f7b18e8247..a378daa3d33 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -2571,6 +2571,14 @@ void QWizard::setWizardStyle(WizardStyle style)
         d->disableUpdates();
         d->wizStyle = style;
         d->updateButtonTexts();
+#if !defined(QT_NO_STYLE_WINDOWSVISTA)
+        if (aeroStyleChange) {
+            //Send a resizeevent since the antiflicker widget probably needs a new size
+            //because of the backbutton in the window title
+            QResizeEvent ev(geometry().size(), geometry().size());
+            QApplication::sendEvent(this, &ev);
+        }
+#endif
         d->updateLayout();
         updateGeometry();
         d->enableUpdates();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index cc262fa3e2c..315d615d897 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -7155,10 +7155,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
             }
         }
 
-        // generate a move event for QWidgets without window handles. QWidgets with native
-        // window handles already receive a move event from
-        // QGuiApplicationPrivate::processGeometryChangeEvent.
-        if (isMove && (!q->windowHandle() || q->testAttribute(Qt::WA_DontShowOnScreen))) {
+        if (isMove) {
             QMoveEvent e(q->pos(), oldPos);
             QApplication::sendEvent(q, &e);
         }
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 1cd042f99d2..e455b772fbd 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -543,14 +543,36 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
     QGuiApplication::sendSpontaneousEvent(receiver, event);
 }
 
-void QWidgetWindow::updateGeometry()
+bool QWidgetWindow::updateSize()
 {
+    bool changed = false;
     if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
-        return;
+        return changed;
+    if (m_widget->data->crect.size() != geometry().size()) {
+        changed = true;
+        m_widget->data->crect.setSize(geometry().size());
+    }
 
-    const QMargins margins = frameMargins();
+    updateMargins();
+    return changed;
+}
+
+bool QWidgetWindow::updatePos()
+{
+    bool changed = false;
+    if (m_widget->testAttribute(Qt::WA_OutsideWSRange))
+        return changed;
+    if (m_widget->data->crect.topLeft() != geometry().topLeft()) {
+        changed = true;
+        m_widget->data->crect.moveTopLeft(geometry().topLeft());
+    }
+    updateMargins();
+    return changed;
+}
 
-    m_widget->data->crect = geometry();
+void QWidgetWindow::updateMargins()
+{
+    const QMargins margins = frameMargins();
     QTLWExtra *te = m_widget->d_func()->topData();
     te->posIncludesFrame= false;
     te->frameStrut.setCoords(margins.left(), margins.top(), margins.right(), margins.bottom());
@@ -609,24 +631,25 @@ void QWidgetWindow::updateNormalGeometry()
 
 void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
 {
-    updateGeometry();
-    QGuiApplication::sendSpontaneousEvent(m_widget, event);
+    if (updatePos())
+        QGuiApplication::sendSpontaneousEvent(m_widget, event);
 }
 
 void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
 {
     QSize oldSize = m_widget->data->crect.size();
 
-    updateGeometry();
-    QGuiApplication::sendSpontaneousEvent(m_widget, event);
+    if (updateSize()) {
+        QGuiApplication::sendSpontaneousEvent(m_widget, event);
 
-    if (m_widget->d_func()->paintOnScreen()) {
-        QRegion updateRegion(geometry());
-        if (m_widget->testAttribute(Qt::WA_StaticContents))
-            updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
-        m_widget->d_func()->syncBackingStore(updateRegion);
-    } else {
-        m_widget->d_func()->syncBackingStore();
+        if (m_widget->d_func()->paintOnScreen()) {
+            QRegion updateRegion(geometry());
+            if (m_widget->testAttribute(Qt::WA_StaticContents))
+                updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
+            m_widget->d_func()->syncBackingStore(updateRegion);
+        } else {
+            m_widget->d_func()->syncBackingStore();
+        }
     }
 }
 
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 7f12ae8e206..0632a5c3647 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -108,7 +108,9 @@ private slots:
 
 private:
     void repaintWindow();
-    void updateGeometry();
+    bool updateSize();
+    bool updatePos();
+    void updateMargins();
     void updateNormalGeometry();
 
     enum FocusWidgets {
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
old mode 100755
new mode 100644
index c6c74641941..36791293ab9
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -95,6 +95,8 @@ private slots:
     void tst_updateWinId_QTBUG40681();
     void tst_recreateWindow_QTBUG40817();
 
+    void tst_resize_count();
+    void tst_move_count();
 };
 
 void tst_QWidget_window::initTestCase()
@@ -660,6 +662,105 @@ void tst_QWidget_window::tst_recreateWindow_QTBUG40817()
     tab.setCurrentIndex(1);
 }
 
+class ResizeWidget : public QWidget
+{
+Q_OBJECT
+public:
+    ResizeWidget(QWidget *parent = 0)
+        : QWidget(parent)
+        , resizeCount(0)
+    { }
+
+    int resizeCount;
+
+protected:
+    void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE
+    {
+        resizeCount++;
+    }
+};
+
+void tst_QWidget_window::tst_resize_count()
+{
+    {
+        ResizeWidget resize;
+        resize.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&resize));
+        QCOMPARE(resize.resizeCount, 1);
+        resize.resizeCount = 0;
+        QSize size = resize.size();
+        size.rwidth() += 10;
+        resize.resize(size);
+        QGuiApplication::sync();
+        QTRY_COMPARE(resize.resizeCount, 1);
+
+        resize.resizeCount = 0;
+
+        ResizeWidget child(&resize);
+        child.resize(200,200);
+        child.winId();
+        child.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&child));
+        QGuiApplication::sync();
+        QTRY_COMPARE(child.resizeCount, 1);
+        child.resizeCount = 0;
+        size = child.size();
+        size.rwidth() += 10;
+        child.resize(size);
+        QGuiApplication::sync();
+        QCOMPARE(resize.resizeCount, 0);
+        QCOMPARE(child.resizeCount, 1);
+    }
+    {
+        ResizeWidget parent;
+        ResizeWidget child(&parent);
+        child.resize(200,200);
+        child.winId();
+        parent.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&parent));
+        parent.resizeCount = 0;
+        QGuiApplication::sync();
+        QTRY_COMPARE(child.resizeCount, 1);
+        child.resizeCount = 0;
+        QSize size = child.size();
+        size.rwidth() += 10;
+        child.resize(size);
+        QGuiApplication::sync();
+        QCOMPARE(parent.resizeCount, 0);
+        QCOMPARE(child.resizeCount, 1);
+    }
+
+}
+
+class MoveWidget : public QWidget
+{
+Q_OBJECT
+public:
+    MoveWidget(QWidget *parent = 0)
+        : QWidget(parent)
+        , moveCount(0)
+    { }
+
+    void moveEvent(QMoveEvent *) Q_DECL_OVERRIDE
+    {
+        moveCount++;
+    }
+
+    int moveCount;
+};
+
+void tst_QWidget_window::tst_move_count()
+{
+    MoveWidget move;
+    move.move(500,500);
+    move.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&move));
+    QTRY_VERIFY(move.moveCount >= 1);
+    move.moveCount = 0;
+
+    move.move(220,250);
+    QTRY_VERIFY(move.moveCount >= 1);
+}
 
 QTEST_MAIN(tst_QWidget_window)
 #include "tst_qwidget_window.moc"
-- 
GitLab