From 79fb890a4f2a13cc0f21e92f5b2a6e10af1430b4 Mon Sep 17 00:00:00 2001
From: Samuel Nevala <samuel.nevala@digia.com>
Date: Fri, 5 Feb 2010 09:51:00 +0200
Subject: s60 application loses normalGeometry when returning from fullscreen

Problem description: normalGeomerty lost during showFullScreen

1. Reported problen was due on void QSymbianControl::PositionChanged()
over write top->normaGeometry on every position change. As fix
top->normalGeometry is moved to new rect:s top left only when
widget windowState == 0.

2. Also made some new qwidget auto tests. Refactored s60 side
setWindowState to be more readable. Minimized window state now
hides window decoration.

QApplication & QWidget autotest run on emulator and tested on
s60 5.0 hw using attached application.

http://bugreports.qt.nokia.com/browse/QTBUG-6231

Task-number:QTBUG-6231

Merge-request: 2256
Reviewed-by: Jani Hautakangas <ext-jani.hautakangas@nokia.com>
---
 src/gui/kernel/qapplication_s60.cpp |  17 ++-
 src/gui/kernel/qwidget_s60.cpp      | 108 +++++------------
 tests/auto/qwidget/tst_qwidget.cpp  | 224 ++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+), 87 deletions(-)

diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 6e03d7c..4a137ee 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -924,8 +924,8 @@ void QSymbianControl::PositionChanged()
         cr.moveTopLeft(newPos);
         qwidget->data->crect = cr;
         QTLWExtra *top = qwidget->d_func()->maybeTopData();
-        if (top)
-            top->normalGeometry = cr;
+        if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState)
+            top->normalGeometry.moveTopLeft(newPos);
         if (qwidget->isVisible()) {
             QMoveEvent e(newPos, oldPos);
             qt_sendSpontaneousEvent(qwidget, &e);
@@ -960,15 +960,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
         qwidget->d_func()->setWindowIcon_sys(true);
         qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
 #ifdef Q_WS_S60
-        // If widget is fullscreen, hide status pane and button container
-        // otherwise show them.
+        // If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
         CEikStatusPane* statusPane = S60->statusPane();
         CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
-        bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
-        if (statusPane && (bool)statusPane->IsVisible() == isFullscreen)
-            statusPane->MakeVisible(!isFullscreen);
-        if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen)
-            buttonGroup->MakeVisible(!isFullscreen);
+        TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
+        if (statusPane)
+            statusPane->MakeVisible(visible);
+        if (buttonGroup)
+            buttonGroup->MakeVisible(visible);
 #endif
     } else if (QApplication::activeWindow() == qwidget->window()) {
         if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 0ce7534..c84e1cc 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1046,96 +1046,48 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
         return;
 
     if (isWindow()) {
-#ifdef Q_WS_S60
-        // Change window decoration visibility if switching to or from fullsccreen
-        // In addition decoration visibility is changed when the initial has been
-        // WindowNoState.
-        // The window decoration visibility has to be changed before doing actual
-        // window state change since in that order the availableGeometry will return
-        // directly the right size and we will avoid unnecessarty redraws
-        if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen) ||
-            oldstate == Qt::WindowNoState) {
-            CEikStatusPane* statusPane = S60->statusPane();
-            CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
-            if (newstate & Qt::WindowFullScreen) {
-                if (statusPane)
-                    statusPane->MakeVisible(false);
-                if (buttonGroup)
-                    buttonGroup->MakeVisible(false);
-            } else {
-                if (statusPane)
-                    statusPane->MakeVisible(true);
-                if (buttonGroup)
-                    buttonGroup->MakeVisible(true);
-            }
 
+        QSymbianControl *window = static_cast<QSymbianControl *>(effectiveWinId());
+        if (window && newstate & Qt::WindowMinimized) {
+            window->setFocusSafely(false);
+            window->MakeVisible(false);
+        } else if (window && oldstate & Qt::WindowMinimized) {
+            window->setFocusSafely(true);
+            window->MakeVisible(true);
         }
+
+#ifdef Q_WS_S60
+        // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration.
+        // The window decoration visibility has to be changed before doing actual window state 
+        // change since in that order the availableGeometry will return directly the right size and 
+        // we will avoid unnecessarty redraws
+        CEikStatusPane* statusPane = S60->statusPane();
+        CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+        TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); 
+        if (statusPane)
+            statusPane->MakeVisible(visible);
+        if (buttonGroup)
+            buttonGroup->MakeVisible(visible);
 #endif // Q_WS_S60
 
         createWinId();
         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
-        QTLWExtra *top = d->topData();
-
         // Ensure the initial size is valid, since we store it as normalGeometry below.
         if (!testAttribute(Qt::WA_Resized) && !isVisible())
             adjustSize();
 
-        if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
-            if ((newstate & Qt::WindowMaximized)) {
-                const QRect normalGeometry = geometry();
+        QTLWExtra *top = d->topData();
+        const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
 
-                const QRect r = top->normalGeometry;
-                setGeometry(qApp->desktop()->availableGeometry(this));
-                top->normalGeometry = r;
+        if (newstate & Qt::WindowFullScreen)
+            setGeometry(qApp->desktop()->screenGeometry(this));
+        else if (newstate & Qt::WindowMaximized)
+            setGeometry(qApp->desktop()->availableGeometry(this));
+        else 
+            setGeometry(normalGeometry);
 
-                if (top->normalGeometry.width() < 0)
-                    top->normalGeometry = normalGeometry;
-            } else {
-                // restore original geometry
-                setGeometry(top->normalGeometry);
-            }
-        }
-        if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
-            if (newstate & Qt::WindowFullScreen) {
-                const QRect normalGeometry = geometry();
-                const QRect r = top->normalGeometry;
-                setGeometry(qApp->desktop()->screenGeometry(this));
-
-                top->normalGeometry = r;
-                if (top->normalGeometry.width() < 0)
-                    top->normalGeometry = normalGeometry;
-            } else {
-                if (newstate & Qt::WindowMaximized) {
-                    const QRect r = top->normalGeometry;
-                    setGeometry(qApp->desktop()->availableGeometry(this));
-                    top->normalGeometry = r;
-                } else {
-                    setGeometry(top->normalGeometry);
-                }
-            }
-        }
-        if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
-            if (newstate & Qt::WindowMinimized) {
-                if (isVisible()) {
-                    QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
-                    if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
-                        id->setFocusSafely(false);
-                    id->MakeVisible(false);
-                }
-            } else {
-                if (isVisible()) {
-                    QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId());
-                    id->MakeVisible(true);
-                    if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
-                        id->setFocusSafely(true);
-                }
-                const QRect normalGeometry = geometry();
-                const QRect r = top->normalGeometry;
-                top->normalGeometry = r;
-                if (top->normalGeometry.width() < 0)
-                    top->normalGeometry = normalGeometry;
-            }
-        }
+        //restore normal geometry
+        top->normalGeometry = normalGeometry;
     }
 
     data->window_state = newstate;
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index ea90ae3..88bdc72 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -391,6 +391,10 @@ private slots:
 
 #ifdef Q_OS_SYMBIAN
     void cbaVisibility();
+    void fullScreenWindowModeTransitions();
+    void maximizedWindowModeTransitions();
+    void minimizedWindowModeTransitions();
+    void normalWindowModeTransitions();
 #endif
 
     void focusProxyAndInputMethods();
@@ -9687,6 +9691,226 @@ void tst_QWidget::cbaVisibility()
     CEikButtonGroupContainer* buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
     QVERIFY(buttonGroup->IsVisible());
 }
+
+void tst_QWidget::fullScreenWindowModeTransitions()
+{
+    QWidget widget;
+    QVBoxLayout *layout = new QVBoxLayout;
+    QPushButton *button = new QPushButton("test Button");
+    layout->addWidget(button);
+    widget.setLayout(layout);
+    widget.show();
+    
+    const QRect normalGeometry = widget.normalGeometry();
+    const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+    const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+    CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+    CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+    
+    //Enter 
+    widget.showNormal();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+    
+    widget.showMaximized();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+    
+    widget.showMinimized();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+    
+    //Exit 
+    widget.showFullScreen();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+
+    widget.showFullScreen();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+
+    widget.showFullScreen();
+    widget.showMinimized();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+}
+
+void tst_QWidget::maximizedWindowModeTransitions()
+{
+    QWidget widget;
+    QVBoxLayout *layout = new QVBoxLayout;
+    QPushButton *button = new QPushButton("test Button");
+    layout->addWidget(button);
+    widget.setLayout(layout);
+    widget.show();
+
+    const QRect normalGeometry = widget.normalGeometry();
+    const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+    const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+    CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+    CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+    
+    //Enter
+    widget.showNormal();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible()); 
+    
+    widget.showFullScreen();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible()); 
+    
+    widget.showMinimized();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible()); 
+    
+    //Exit
+    widget.showMaximized();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible()); 
+
+    widget.showMaximized();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+
+    widget.showMaximized();
+    widget.showMinimized();
+    // Since showMinimized hides window decoration availableGeometry gives different value
+    // than with decoration visible. Altual size does not really matter since widget is invisible.
+    QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+}
+
+void tst_QWidget::minimizedWindowModeTransitions()
+{
+    QWidget widget;
+    QVBoxLayout *layout = new QVBoxLayout;
+    QPushButton *button = new QPushButton("test Button");
+    layout->addWidget(button);
+    widget.setLayout(layout);
+    widget.show();
+    
+    const QRect normalGeometry = widget.normalGeometry();
+    const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+    const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+    CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+    CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+    
+    //Enter
+    widget.showNormal();
+    widget.showMinimized();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+    
+    widget.showFullScreen();
+    widget.showMinimized();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+    
+    widget.showMaximized();
+    widget.showMinimized();
+    // Since showMinimized hides window decoration availableGeometry gives different value
+    // than with decoration visible. Altual size does not really matter since widget is invisible.
+    QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+
+    //Exit
+    widget.showMinimized();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible()); 
+
+    widget.showMinimized();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible()); 
+
+    widget.showMinimized();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+}
+
+void tst_QWidget::normalWindowModeTransitions()
+{
+    QWidget widget;
+    QVBoxLayout *layout = new QVBoxLayout;
+    QPushButton *button = new QPushButton("test Button");
+    layout->addWidget(button);
+    widget.setLayout(layout);
+    widget.show();
+    
+    const QRect normalGeometry = widget.normalGeometry();
+    const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+    const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+    CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+    CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+    
+    //Enter
+    widget.showMaximized();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+    
+    widget.showFullScreen();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+    
+    widget.showMinimized();
+    widget.showNormal();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+    
+    //Exit
+    widget.showNormal();
+    widget.showMaximized();
+    QCOMPARE(widget.geometry(), maximumScreenGeometry);
+    QVERIFY(buttonGroup->IsVisible());
+    QVERIFY(statusPane->IsVisible());    
+
+    widget.showNormal();
+    widget.showFullScreen();
+    QCOMPARE(widget.geometry(), fullScreenGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+    
+    widget.showNormal();
+    widget.showMinimized();
+    QCOMPARE(widget.geometry(), normalGeometry);
+    QVERIFY(!buttonGroup->IsVisible());
+    QVERIFY(!statusPane->IsVisible());    
+}
 #endif
 
 class InputContextTester : public QInputContext
-- 
cgit v0.12