Index: /trunk/src/gui/kernel/qapplication_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 119)
+++ /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 120)
@@ -44,4 +44,6 @@
 #include "qt_os2.h"
 
+#include "qdebug.h"
+
 #include "qapplication.h"
 #include "qapplication_p.h"
@@ -61,4 +63,6 @@
 #include "qkeymapper_p.h"
 #include "qcursor_p.h"
+
+#define QT_DEBUGMSGFLOW
 
 QT_BEGIN_NAMESPACE
@@ -120,6 +124,6 @@
 //  void syncBackingStore(const QRegion &rgn) { d_func()->syncBackingStore(rgn); }
 //  void syncBackingStore() { d_func()->syncBackingStore(); }
-//  QWidgetData *dataPtr() { return data; }
-//  QWidgetPrivate *dptr() { return d_func(); }
+    QWidgetData *dataPtr() { return data; }
+    QWidgetPrivate *dptr() { return d_func(); }
 //  QRect frameStrut() const { return d_func()->frameStrut(); }
     bool        pmEvent(QMSG *m, MRESULT *r) { return QWidget::pmEvent(m, r); }
@@ -494,4 +498,12 @@
         // flip y coordinate
         qmsg.ptl.y = QApplication::desktop()->height() - (qmsg.ptl.y + 1);
+
+#if defined(QT_DEBUGMSGFLOW)
+        {
+            QString str = qStrQMSG(qmsg);
+            if (!str.isEmpty())
+                qDebug() << "*** [W]" << str.toUtf8().constData();
+        }
+#endif
 
         // send through app filter
@@ -709,4 +721,6 @@
 #endif
 
+        MRESULT rc = (MRESULT) FALSE;
+
         HWND hwndC = WinWindowFromID(hwnd, FID_CLIENT);
         QETWidget *widget = (QETWidget*)QWidget::find(hwndC);
@@ -714,5 +728,80 @@
             break;
 
+        Q_ASSERT(widget->isWindow());
+
+#if defined(QT_DEBUGMSGFLOW)
+        {
+            QMSG qmsg; // create QMSG structure
+            qmsg.hwnd = hwnd;
+            qmsg.msg = msg;
+            qmsg.mp1 = mp1;
+            qmsg.mp2 = mp2;
+            QString str = qStrQMSG(qmsg);
+            if (!str.isEmpty())
+                qDebug() << "*** [F]" << str.toUtf8().constData();
+        }
+#endif
+
         switch(msg) {
+
+        case WM_WINDOWPOSCHANGED: {
+            // We detect spontaneous min/max/restore events here instead of
+            // WM_MINMAXFRAME, because WM_MINMAXFRAME is a pre-process message
+            // (i.e. no actual changes have been made). We need actual changes
+            // in order to update the frame strut and send WindowStateChange.
+            rc = QtOldFrameProc(hwnd, msg, mp1, mp2);
+
+            ULONG awp = LONGFROMMP(mp2);
+
+            bool window_state_change = false;
+            Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state);
+
+            if (awp & AWP_MINIMIZED) {
+                window_state_change = true;
+                widget->dataPtr()->window_state |= Qt::WindowMinimized;
+                if (widget->isVisible()) {
+                    QHideEvent e;
+                    qt_sendSpontaneousEvent(widget, &e);
+                    widget->dptr()->hideChildren(true);
+                    const QString title = widget->windowIconText();
+                    if (!title.isEmpty())
+                        widget->dptr()->setWindowTitle_helper(title);
+                }
+            } else {
+                if (awp & AWP_MAXIMIZED) {
+                    widget->topData()->normalGeometry = widget->geometry();
+                }
+                if (awp & AWP_RESTORED) {
+                    window_state_change = true;
+                    if (awp & AWP_MAXIMIZED)
+                        widget->dataPtr()->window_state |= Qt::WindowMaximized;
+                    else if (!widget->isMinimized())
+                        widget->dataPtr()->window_state &= ~Qt::WindowMaximized;
+
+                    if (widget->isMinimized()) {
+                        widget->dataPtr()->window_state &= ~Qt::WindowMinimized;
+                        widget->dptr()->showChildren(true);
+                        QShowEvent e;
+                        qt_sendSpontaneousEvent(widget, &e);
+                        const QString title = widget->windowTitle();
+                        if (!title.isEmpty())
+                            widget->dptr()->setWindowTitle_helper(title);
+                    }
+                }
+            }
+
+            if (window_state_change) {
+                widget->dptr()->updateFrameStrut();
+                if (!widget->topData()->inSetWindowState) {
+                    // send WindowStateChange event if this message is NOT
+                    // originated from QWidget::setWindowState().
+                    QWindowStateChangeEvent e(oldstate);
+                    qt_sendSpontaneousEvent(widget, &e);
+                }
+            }
+
+            return rc;
+        }
+
         default:
             break;
@@ -1476,8 +1565,6 @@
     d_func()->hd = WinBeginPaint(internalWinId(), 0, &rcl);
 
-#if 1
-    qDebug("WM_PAINT: [%s] BEGIN %ld,%ld-%ld,%ld hps=%08lX",
-           QWidgetPrivate::name(this).constData(),
-           rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop, d_func()->hd);
+#if defined(QT_DEBUGMSGFLOW)
+    qDebug() << " PAINT BEGIN:" << rcl << "hps:" << qStrHPS(d_func()->hd);
 #endif
 
@@ -1501,9 +1588,8 @@
     // Mapping region from system to qt (32 bit) coordinate system.
     updRect.translate(data->wrect.topLeft());
-#if 1
-    qDebug("WM_PAINT: [%s] update=%d,%d/%d,%d",
-           QWidgetPrivate::name(this).constData(),
-           updRect.x(), updRect.y(), updRect.width(), updRect.height());
-#endif
+#if defined(QT_DEBUGMSGFLOW)
+    qDebug() << " PAINT updRect:" << updRect;
+#endif
+
     // @todo use hrgn here converted to QRegion?
     d_func()->syncBackingStore(updRect);
@@ -1512,6 +1598,6 @@
     d_func()->hd = NULLHANDLE;
 
-#if 1
-    qDebug("WM_PAINT: [%s] END", QWidgetPrivate::name(this).constData());
+#if defined(QT_DEBUGMSGFLOW)
+    qDebug() << " PAINT END";
 #endif
 
@@ -1659,3 +1745,100 @@
 }
 
+
+/*!
+    Returns a QWidget pointer or 0 if there is no widget corresponding to the
+    given HWND. As opposed to QWidget::find(), correctly handles WC_FRAME
+    windows created for top level widgets. Used for debugging.
+ */
+QWidget *qWidgetFromHWND(HWND hwnd)
+{
+    char buf[10];
+    if (WinQueryClassName(hwnd, sizeof(buf), buf)) {
+        if (!strcmp(buf, "#1")) // WC_FRAME
+            hwnd = WinWindowFromID(hwnd, FID_CLIENT);
+        return QWidget::find(hwnd);
+    }
+    return 0;
+}
+
+/*!
+    \internal
+
+    Returns a human readable widget name in the form "class/name". Used for
+    debugging.
+ */
+QDbgStr qWidgetName(QWidget *w)
+{
+    if (w)
+        return QString()
+            .sprintf("%s.%s", w->metaObject()->className(),
+                     w->objectName().isEmpty() ? "<noname>" :
+                     w->objectName().toUtf8().constData());
+    return QString(QLatin1String("<no-widget>"));
+}
+
+QDbgStr qStrHWND(HWND hwnd)
+{
+    return QString().sprintf("%08lX/", hwnd) +
+           qWidgetName(qWidgetFromHWND(hwnd));
+}
+
+QDbgStr qStrHPS(HPS hps)
+{
+    return QString().sprintf("%08lX", hps);
+}
+
+QDbgStr qStrHPOINTER(HPOINTER hptr)
+{
+    return QString().sprintf("%08lX", hptr);
+}
+
+QDbgStr qStrHRGN(HRGN hrgn)
+{
+    return QString().sprintf("%08lX", hrgn);
+}
+
+QDbgStr qStrQMSG(const QMSG &qmsg)
+{
+    QString str;
+
+    #define myCaseBegin(a) case a: { \
+        str = QString().sprintf(#a ": hwnd %08lX.", qmsg.hwnd); \
+        str += qWidgetName(qWidgetFromHWND(qmsg.hwnd));
+    #define myCaseEnd() }
+
+    switch (qmsg.msg) {
+
+    myCaseBegin(WM_PAINT)
+        break;
+    myCaseEnd()
+
+    myCaseBegin(WM_SIZE)
+        str += QString().
+            sprintf(" old (%hd,%ld) new (%hd,%hd)",
+                    SHORT1FROMMP(qmsg.mp1), SHORT2FROMMP(qmsg.mp1),
+                    SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2));
+        break;
+    myCaseEnd()
+
+    myCaseBegin(WM_MOVE)
+        break;
+    myCaseEnd()
+
+    default:
+        break;
+    }
+
+    return str;
+
+    #undef myCaseEnd
+    #undef myCaseBegin
+}
+
+QDbgStr qStrRECTL(const RECTL &rcl)
+{
+    return QString().sprintf("RECTL(%ld,%ld %ld,%ld)",
+                             rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop);
+}
+
 QT_END_NAMESPACE
Index: /trunk/src/gui/kernel/qwidget_p.h
===================================================================
--- /trunk/src/gui/kernel/qwidget_p.h	(revision 119)
+++ /trunk/src/gui/kernel/qwidget_p.h	(revision 120)
@@ -157,4 +157,5 @@
     HWND fId;
     HSWITCH swEntry;
+    uint inSetWindowState : 1;
 #endif
     QRect normalGeometry; // used by showMin/maximized/FullScreen
@@ -636,8 +637,4 @@
 #ifdef Q_WS_PM
     void validateObstacles();
-
-    static QWidget *fromHWND(HWND hwnd);
-    static QByteArray name(QWidget *w);
-    inline static QByteArray name(HWND hwnd) { return name(fromHWND(hwnd)); }
 #endif
 
Index: /trunk/src/gui/kernel/qwidget_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 119)
+++ /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 120)
@@ -44,4 +44,6 @@
 #include "qt_os2.h"
 
+#include "qdebug.h"
+
 #include "qwidget.h"
 #include "qwidget_p.h"
@@ -49,12 +51,11 @@
 #include "qapplication.h"
 #include "qdesktopwidget.h"
+#include "qevent.h"
 
 #include "private/qapplication_p.h"
 #include "private/qbackingstore_p.h"
 
-#include <qdebug.h>
-
-#define QT_DEBUGWINCREATEDESTROY
-#define QT_DEBUGWIDGETMASK
+//#define QT_DEBUGWINCREATEDESTROY
+//#define QT_DEBUGWIDGETMASK
 
 QT_BEGIN_NAMESPACE
@@ -143,8 +144,6 @@
 {
 #if defined(QT_DEBUGWIDGETMASK)
-    qDebug("qt_WinInvalidateRegionEx: hwnd=%08lX [%s] "
-           "hwndFrom=%08lX hwndTo=%08lX", hwnd,
-           QWidgetPrivate::name(hwnd).constData(),
-           hwndFrom, hwndTo);
+    qDebug("qt_WinInvalidateRegionEx: hwnd=%s hwndFrom=%08lX hwndTo=%08lX",
+           qStrHWND(hwnd).toUtf8().constData(), hwndFrom, hwndTo);
 #endif
 
@@ -174,6 +173,6 @@
         WinQueryWindowPos(child, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-        qDebug(" child=%08lX [fl=%08lX] [%s]", child, swp.fl,
-               QWidgetPrivate::name(child).constData());
+        qDebug(" child=%s [fl=%08lX]", qStrHWND(child).toUtf8().constData(),
+               swp.fl);
 #endif
         // proceed only if not hidden
@@ -259,8 +258,7 @@
 
 #if defined(QT_DEBUGWIDGETMASK)
-    qDebug("qt_WinProcessWindowObstacles: hwnd=%08lX [%s], prcl=%p "
-           "hrgn=%08lX, op=%ld flags=%08lX", hwnd,
-           QWidgetPrivate::name(hwnd).constData(),
-           prcl, hrgn, op, flags);
+    qDebug("qt_WinProcessWindowObstacles: hwnd=%s, prcl=%p "
+           "hrgn=%08lX, op=%ld flags=%08lX",
+           qStrHWND(hwnd).toUtf8().constData(), prcl, hrgn, op, flags);
 #endif
 
@@ -313,6 +311,6 @@
                 WinQueryWindowPos(relative, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-                qDebug(" child=%08lX [fl=%08lX] [%s]", relative, swp.fl,
-                       QWidgetPrivate::name(relative).constData());
+                qDebug(" child=%s [fl=%08lX]",
+                       qStrHWND(relative).toUtf8().constData(), swp.fl);
 #endif
                 // skip if hidden
@@ -353,6 +351,6 @@
             WinQueryWindowPos(relative, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-            qDebug(" sibling=%08lX [fl=%08lX] [%s]", relative, swp.fl,
-                   QWidgetPrivate::name(relative).constData());
+            qDebug(" sibling=%s [fl=%08lX]",
+                   qStrHWND(relative).toUtf8().constData(), swp.fl);
 #endif
             // skip if hidden
@@ -403,6 +401,6 @@
             WinQueryWindowPos(parent, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-            qDebug(" parent=%08lX [fl=%08lX] [%s]", parent, swp.fl,
-                   QWidgetPrivate::name(parent).constData());
+            qDebug(" parent=%s [fl=%08lX]",
+                   qStrHWND(parent).toUtf8().constData(), swp.fl);
 #endif
             delta.x += swp.x;
@@ -412,6 +410,6 @@
                 WinQueryWindowPos(relative, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-                qDebug(" ancestor=%08lX [fl=%08lX] [%s]", relative, swp.fl,
-                       QWidgetPrivate::name(parent).constData());
+                qDebug(" ancestor=%s [fl=%08lX]",
+                       qStrHWND(relative).toUtf8().constData(), swp.fl);
 #endif
                 // skip if hidden
@@ -452,8 +450,10 @@
 
     Partial reimplementation of the WinSetWindowPos() API that obeys window clip
-    regions. Currently supported flags are SWP_ZORDER, SWP_SHOW, SWP_HIDE and
-    SWP_ACTIVATE. Other flags should not be used. Note that if any other flag is
-    specified (alone or in addition to the supported ones), or if the given
-    window is a top-level window, this function acts exactly like the original
+    regions. Currently supported flags are SWP_ZORDER, SWP_SHOW, SWP_HIDE,
+    SWP_ACTIVATE, SWP_MOVE, SWP_SIZE and SWP_NOREDRAW; other flags should no be
+    used.
+
+    Note that if the above restrictions are not met or if the given window is a
+    top-level window, this function acts exactly like the original
     WinSetWindowPos() function.
  */
@@ -463,14 +463,16 @@
 {
 #if defined(QT_DEBUGWIDGETMASK)
-    qDebug("qt_WinSetWindowPos: hwnd=%08lX [%s] fl=%08lX", hwnd,
-           QWidgetPrivate::name(hwnd).constData(), fl);
+    qDebug("qt_WinSetWindowPos: hwnd=%s fl=%08lX",
+           qStrHWND(hwnd).toUtf8().constData(), fl);
 #endif
 
     HWND desktop = WinQueryDesktopWindow(0, 0);
 
-    Q_ASSERT(((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0) ||
+    Q_ASSERT(((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE | SWP_ACTIVATE |
+                      SWP_MOVE | SWP_SIZE | SWP_NOREDRAW)) == 0) ||
              hwnd == desktop || WinQueryWindow(hwnd, QW_PARENT) == desktop);
 
-    if ((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE)) != 0 ||
+    if ((fl & ~(SWP_ZORDER | SWP_SHOW | SWP_HIDE | SWP_ACTIVATE |
+                SWP_MOVE | SWP_SIZE | SWP_NOREDRAW)) != 0 ||
          hwnd == desktop || WinQueryWindow(hwnd, QW_PARENT) == desktop) {
         return WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy, fl);
@@ -490,4 +492,5 @@
         fl &= ~SWP_HIDE;
 
+    // do the job but not invalidate or redraw
     BOOL rc = WinSetWindowPos(hwnd, hwndInsertBehind, x, y, cx, cy,
                               fl | SWP_NOREDRAW);
@@ -501,5 +504,5 @@
         fl &= ~SWP_ZORDER;
 
-    if ((fl & (SWP_ZORDER | SWP_SHOW | SWP_HIDE)) == 0)
+    if ((fl & (SWP_ZORDER | SWP_SHOW | SWP_HIDE | SWP_MOVE | SWP_SIZE)) == 0)
         return rc;
 
@@ -520,118 +523,250 @@
         qt_WinInvalidateRegionEx(hwndParent, hrgnSelf,
                                   WinQueryWindow(hwnd, QW_NEXT), HWND_BOTTOM);
-    } else { // fl & SWP_ZORDER
-        // below we assume that WinSetWindowPos() returns FALSE if
-        // an incorrect (unrelated) hwndInsertBehind is passed when SWP_ZORDER
-        // is set
-
-        // first, detect whether we are moving up or down
-        BOOL up;
-        HWND hwndFrom, hwndTo;
-        if (swpOld.hwndInsertBehind == HWND_TOP) {
-            up = FALSE;
-            hwndFrom = WinQueryWindow(hwndParent, QW_TOP);
-            hwndTo = swpNew.hwndInsertBehind;
-        } else {
-            up = TRUE;
-            for (HWND hwndAbove = hwnd;
-                  (hwndAbove = WinQueryWindow(hwndAbove, QW_PREV)) != 0;) {
-                if (hwndAbove == swpOld.hwndInsertBehind) {
-                    up = FALSE;
-                    break;
+    } else {
+        // SWP_ZORDER or SWP_MOVE or SWP_SIZE
+
+        if (fl & SWP_ZORDER) {
+            // below we assume that WinSetWindowPos() returns FALSE if
+            // an incorrect (unrelated) hwndInsertBehind is passed when SWP_ZORDER
+            // is set
+
+            // first, detect whether we are moving up or down
+            BOOL up;
+            HWND hwndFrom, hwndTo;
+            if (swpOld.hwndInsertBehind == HWND_TOP) {
+                up = FALSE;
+                hwndFrom = WinQueryWindow(hwndParent, QW_TOP);
+                hwndTo = swpNew.hwndInsertBehind;
+            } else {
+                up = TRUE;
+                for (HWND hwndAbove = hwnd;
+                      (hwndAbove = WinQueryWindow(hwndAbove, QW_PREV)) != 0;) {
+                    if (hwndAbove == swpOld.hwndInsertBehind) {
+                        up = FALSE;
+                        break;
+                    }
                 }
-            }
+                if (up) {
+                    hwndFrom = swpOld.hwndInsertBehind;
+                    hwndTo = WinQueryWindow(hwnd, QW_NEXT);
+                } else {
+                    hwndFrom = WinQueryWindow(swpOld.hwndInsertBehind, QW_NEXT);
+                    hwndTo = swpNew.hwndInsertBehind;
+                }
+            }
+#if defined(QT_DEBUGWIDGETMASK)
+            qDebug(" moving up? %ld", up);
+            qDebug(" hwndFrom=%s", qStrHWND(hwndFrom).toUtf8().constData());
+            qDebug(" hwndTo=%s", qStrHWND(hwndTo).toUtf8().constData());
+#endif
+
+            SWP swp;
+            HWND sibling = hwndFrom;
+            HRGN hrgn = GpiCreateRegion(hps, 0, NULL);
+            HRGN hrgnUpd = GpiCreateRegion(hps, 0, NULL);
+
             if (up) {
-                hwndFrom = swpOld.hwndInsertBehind;
-                hwndTo = WinQueryWindow(hwnd, QW_NEXT);
+                // go upwards in z-order
+                while (1) {
+                    WinQueryWindowPos(sibling, &swp);
+#if defined(QT_DEBUGWIDGETMASK)
+                    qDebug(" sibling=%s [fl=%08lX]",
+                           qStrHWND(sibling).toUtf8().constData(), swp.fl);
+#endif
+                    // proceed only if not hidden
+                    if (swp.fl & SWP_SHOW) {
+                        // get sibling's bounds (clip region or rect)
+                        qt_WinQueryClipRegionOrRect(sibling, hrgn);
+                        // translate the region to this window's coordinate system
+                        POINTL ptl = { swp.x - swpNew.x, swp.y - swpNew.y };
+                        GpiOffsetRegion(hps, hrgn, &ptl);
+                        // add to the region of siblings we're moving on top of
+                        GpiCombineRegion(hps, hrgnUpd, hrgnUpd, hrgn, CRGN_OR);
+#if defined(QT_DEBUGWIDGETMASK)
+                        qDebug("  processed");
+#endif
+                    }
+                    // iterate to the prev window (above)
+                    if (sibling == hwndTo)
+                        break;
+                    sibling = swp.hwndInsertBehind;
+                }
+                // intersect the resulting region with the widget region and
+                // invalidate
+                GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgnUpd, CRGN_AND);
+                WinInvalidateRegion(hwnd, hrgnUpd, TRUE);
             } else {
-                hwndFrom = WinQueryWindow(swpOld.hwndInsertBehind, QW_NEXT);
-                hwndTo = swpNew.hwndInsertBehind;
-            }
-        }
+                // go downwards in reverse z-order
+                POINTL ptl = { 0, 0 };
+                while (1) {
+                    WinQueryWindowPos(sibling, &swp);
 #if defined(QT_DEBUGWIDGETMASK)
-        qDebug(" moving up? %ld", up);
-        qDebug(" hwndFrom=%08lX [%s]", hwndFrom,
-               QWidgetPrivate::name(hwndFrom).constData());
-        qDebug(" hwndTo=%08lX [%s]", hwndTo,
-               QWidgetPrivate::name(hwndTo).constData());
-#endif
-
-        SWP swp;
-        HWND sibling = hwndFrom;
-        HRGN hrgn = GpiCreateRegion(hps, 0, NULL);
-        HRGN hrgnUpd = GpiCreateRegion(hps, 0, NULL);
-
-        if (up) {
-            // go upwards in z-order
-            while (1) {
-                WinQueryWindowPos(sibling, &swp);
+                    qDebug(" sibling=%s [fl=%08lX]",
+                           qStrHWND(sibling).toUtf8().constData(), swp.fl);
+#endif
+                    // proceed only if not hidden
+                    if (swp.fl & SWP_SHOW) {
+                        // get sibling's bounds (clip region or rect)
+                        qt_WinQueryClipRegionOrRect(sibling, hrgn);
+                        // undo the previous translation and translate this window's
+                        // region to the siblings's coordinate system
+                        ptl.x += swpNew.x - swp.x;
+                        ptl.y += swpNew.y - swp.y;
+                        GpiOffsetRegion(hps, hrgnSelf, &ptl);
+                        // intersect the sibling's region with the translated one
+                        // and invalidate the sibling
+                        GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgn, CRGN_AND);
+                        WinInvalidateRegion(sibling, hrgnUpd, TRUE);
+                        // substract the invalidated area from the widget's region
+                        // (no need to invalidate it any more)
+                        GpiCombineRegion(hps, hrgnSelf, hrgnSelf, hrgnUpd, CRGN_DIFF);
+                        // prepare the translation from the sibling's
+                        // coordinates back to this window's coordinates
+                        ptl.x = swp.x - swpNew.x;
+                        ptl.y = swp.y - swpNew.y;
 #if defined(QT_DEBUGWIDGETMASK)
-                qDebug(" sibling=%08lX [fl=%08lX] [%s]", sibling, swp.fl,
-                       QWidgetPrivate::name(sibling).constData());
-#endif
-                // proceed only if not hidden
-                if (swp.fl & SWP_SHOW) {
-                    // get sibling's bounds (clip region or rect)
-                    qt_WinQueryClipRegionOrRect(sibling, hrgn);
-                    // translate the region to this window's coordinate system
-                    POINTL ptl = { swp.x - swpNew.x, swp.y - swpNew.y };
-                    GpiOffsetRegion(hps, hrgn, &ptl);
-                    // add to the region of siblings we're moving on top of
-                    GpiCombineRegion(hps, hrgnUpd, hrgnUpd, hrgn, CRGN_OR);
-#if defined(QT_DEBUGWIDGETMASK)
-                    qDebug("  processed");
-#endif
+                        qDebug("  processed");
+#endif
+                    }
+                    // iterate to the next window (below)
+                    if (sibling == hwndTo)
+                        break;
+                    sibling = WinQueryWindow(sibling, QW_NEXT);
                 }
-                // iterate to the prev window (above)
-                if (sibling == hwndTo)
-                    break;
-                sibling = swp.hwndInsertBehind;
-            }
-            // intersect the resulting region with the widget region and
-            // invalidate
-            GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgnUpd, CRGN_AND);
-            WinInvalidateRegion(hwnd, hrgnUpd, TRUE);
-        } else {
-            // go downwards in reverse z-order
-            POINTL ptl = { 0, 0 };
-            while (1) {
-                WinQueryWindowPos(sibling, &swp);
-#if defined(QT_DEBUGWIDGETMASK)
-                qDebug(" sibling=%08lX [fl=%08lX] [%s]", sibling, swp.fl,
-                       QWidgetPrivate::name(sibling).constData());
-#endif
-                // proceed only if not hidden
-                if (swp.fl & SWP_SHOW) {
-                    // get sibling's bounds (clip region or rect)
-                    qt_WinQueryClipRegionOrRect(sibling, hrgn);
-                    // undo the previous translation and translate this window's
-                    // region to the siblings's coordinate system
-                    ptl.x += swpNew.x - swp.x;
-                    ptl.y += swpNew.y - swp.y;
-                    GpiOffsetRegion(hps, hrgnSelf, &ptl);
-                    // intersect the sibling's region with the translated one
-                    // and invalidate the sibling
-                    GpiCombineRegion(hps, hrgnUpd, hrgnSelf, hrgn, CRGN_AND);
-                    WinInvalidateRegion(sibling, hrgnUpd, TRUE);
-                    // substract the invalidated area from the widget's region
-                    // (no need to invalidate it any more)
-                    GpiCombineRegion(hps, hrgnSelf, hrgnSelf, hrgnUpd, CRGN_DIFF);
-                    // prepare the translation from the sibling's
-                    // coordinates back to this window's coordinates
-                    ptl.x = swp.x - swpNew.x;
-                    ptl.y = swp.y - swpNew.y;
-#if defined(QT_DEBUGWIDGETMASK)
-                    qDebug("  processed");
-#endif
+            }
+
+            GpiDestroyRegion(hps, hrgnUpd);
+            GpiDestroyRegion(hps, hrgn);
+        }
+
+        if (fl & (SWP_MOVE | SWP_SIZE)) {
+            // Since we don't use WS_CLIPCHILDREN and WS_CLIPSIBLINGS,
+            // WinSetWindowPos() does not correctly update involved windows.
+            // The fix is to do it ourselves, taking clip regions into account.
+            // set new and old rectangles
+            const RECTL rcls [2] = {
+                // new (relative to parent)
+                { swpNew.x, swpNew.y, swpNew.x + swpNew.cx, swpNew.y + swpNew.cy },
+                // old (relative to parent)
+                { swpOld.x, swpOld.y, swpOld.x + swpOld.cx, swpOld.y + swpOld.cy }
+            };
+            const RECTL &rclNew = rcls [0];
+            const RECTL &rclOld = rcls [1];
+            // delta to shift coordinate space from parent to this widget
+            POINTL ptlToSelf = { -swpNew.x, -swpNew.y };
+            // use parent PS for blitting
+            HPS hps = WinGetPS(hwndParent);
+            // get old and new clip regions (relative to parent)
+            HRGN hrgnOld = GpiCreateRegion(hps, 1, &rclOld);
+            HRGN hrgnNew = GpiCreateRegion(hps, 1, &rclNew);
+            if (WinQueryClipRegion(hwnd, 0) != QCRGN_NO_CLIP_REGION) {
+                HRGN hrgnTemp = GpiCreateRegion(hps, 0, NULL);
+                // old (clipped to the old rect)
+                WinQueryClipRegion(hwnd, hrgnTemp);
+                GpiOffsetRegion(hps, hrgnTemp, (PPOINTL) &rclOld);
+                GpiCombineRegion(hps, hrgnOld, hrgnTemp, hrgnOld, CRGN_AND);
+                // new (clipped to the new rect)
+                WinQueryClipRegion(hwnd, hrgnTemp);
+                if (swpOld.cy != swpNew.cy) {
+                    // keep the clip region top-left aligned by adding the
+                    // height delta (new size - old size)
+                    POINTL ptl = {0, swpNew.cy - swpOld.cy };
+                    GpiOffsetRegion(hps, hrgnTemp, &ptl);
+                    WinSetClipRegion(hwnd, hrgnTemp);
                 }
-                // iterate to the next window (below)
-                if (sibling == hwndTo)
-                    break;
-                sibling = WinQueryWindow(sibling, QW_NEXT);
-            }
-        }
-
-        GpiDestroyRegion(hps, hrgnUpd);
-        GpiDestroyRegion(hps, hrgn);
+                GpiOffsetRegion(hps, hrgnTemp, (PPOINTL) &rclNew);
+                GpiCombineRegion(hps, hrgnNew, hrgnTemp, hrgnNew, CRGN_AND);
+                GpiDestroyRegion(hps, hrgnTemp);
+            }
+            // the rest is useful only when the widget is visible
+            if (swpNew.fl & SWP_SHOW) {
+                // create affected region (old + new, relative to widget)
+                HRGN hrgnAff = GpiCreateRegion(hps, 0, NULL);
+                GpiCombineRegion(hps, hrgnAff, hrgnOld, hrgnNew, CRGN_OR);
+                GpiOffsetRegion(hps, hrgnAff, &ptlToSelf);
+                // get bounding rectangle of affected region
+                RECTL rclAff;
+                GpiQueryRegionBox(hps, hrgnAff, &rclAff);
+                // get region of obstacles limited to affected rectangle
+                HRGN hrgnObst = GpiCreateRegion(hps, 0, NULL);
+                qt_WinProcessWindowObstacles(hwnd, &rclAff, hrgnObst, CRGN_OR,
+                                             PWO_Sibings | PWO_Ancestors |
+                                             PWO_Screen | PWO_TopLevel);
+                // shift region of obstacles and affected region back to
+                // parent coords
+                GpiOffsetRegion(hps, hrgnObst, (PPOINTL) &rclNew);
+                GpiOffsetRegion(hps, hrgnAff, (PPOINTL) &rclNew);
+                // get parent bounds (clip region or rect)
+                HRGN hrgnUpd = GpiCreateRegion(hps, 0, NULL);
+                qt_WinQueryClipRegionOrRect(hwndParent, hrgnUpd);
+                // add parts of old region beyond parent bounds to
+                // region of obstacles
+                GpiCombineRegion(hps, hrgnOld, hrgnOld, hrgnUpd, CRGN_DIFF);
+                GpiCombineRegion(hps, hrgnObst, hrgnObst, hrgnOld, CRGN_OR);
+                // substract region of obstacles from affected region
+                GpiCombineRegion(hps, hrgnAff, hrgnAff, hrgnObst, CRGN_DIFF);
+                // remember it as parent update region (need later)
+                GpiCombineRegion(hps, hrgnUpd, hrgnAff, 0, CRGN_COPY);
+                // copy region of obstacles to delta region and shift it by
+                // delta (note: movement is considered to be top-left aligned)
+                HRGN hrgnDelta = GpiCreateRegion(hps, 0, NULL);
+                GpiCombineRegion(hps, hrgnDelta, hrgnObst, 0, CRGN_COPY);
+                POINTL ptlDelta = { rclNew.xLeft - rclOld.xLeft,
+                                    rclNew.yTop - rclOld.yTop };
+                GpiOffsetRegion(hps, hrgnDelta, &ptlDelta);
+                // substract region of obstacles from delta region to get
+                // pure delta
+                GpiCombineRegion(hps, hrgnDelta, hrgnDelta, hrgnObst, CRGN_DIFF);
+                // calculate minimal rectangle to blit (top-left aligned)
+                int minw = qMin(swpOld.cx, swpNew.cx);
+                int minh = qMin(swpOld.cy, swpNew.cy);
+                POINTL blitPtls [4] = {
+                    // target (new)
+                    { rclNew.xLeft, rclNew.yTop - minh },
+                    { rclNew.xLeft + minw, rclNew.yTop },
+                    // source (old)
+                    { rclOld.xLeft, rclOld.yTop - minh },
+                };
+                // proceed with blitting only if target and source rects differ
+                if (blitPtls[0].x !=  blitPtls[2].x ||
+                    blitPtls[0].y !=  blitPtls[2].y)
+                {
+                    // Substract delta region from affected region (to minimize
+                    // flicker)
+                    GpiCombineRegion(hps, hrgnAff, hrgnAff, hrgnDelta, CRGN_DIFF);
+                    // set affected region to parent PS
+                    GpiSetClipRegion(hps, hrgnAff, NULL);
+                    // blit minimal rectangle
+                    GpiBitBlt(hps, hps, 3, blitPtls, ROP_SRCCOPY, BBO_IGNORE);
+                    GpiSetClipRegion(hps, 0, NULL);
+                }
+                // substract new widget region from the parent update region
+                // and invalidate it (with underlying children)
+                GpiCombineRegion(hps, hrgnUpd, hrgnUpd, hrgnNew, CRGN_DIFF );
+                qt_WinInvalidateRegionEx(hwndParent, hrgnUpd,
+                                         WinQueryWindow(hwnd, QW_NEXT),
+                                         HWND_BOTTOM);
+                // intersect pure delta region with new region
+                // (to detect areas clipped off to minimize flicker when blitting)
+                GpiCombineRegion(hps, hrgnDelta, hrgnDelta, hrgnNew, CRGN_AND);
+                // substract blitted rectangle from new region
+                GpiSetRegion(hps, hrgnAff, 1, (PRECTL) &blitPtls);
+                GpiCombineRegion(hps, hrgnNew, hrgnNew, hrgnAff, CRGN_DIFF);
+                // combine the rest with intersected delta region
+                GpiCombineRegion(hps, hrgnNew, hrgnNew, hrgnDelta, CRGN_OR);
+                // shift the result back to widget coords and invalidate
+                GpiOffsetRegion(hps, hrgnNew, &ptlToSelf);
+                WinInvalidateRegion(hwnd, hrgnNew, TRUE);
+                // free resources
+                GpiDestroyRegion(hps, hrgnDelta);
+                GpiDestroyRegion(hps, hrgnUpd);
+                GpiDestroyRegion(hps, hrgnObst);
+                GpiDestroyRegion(hps, hrgnAff);
+            }
+            // free resources
+            GpiDestroyRegion(hps, hrgnOld);
+            GpiDestroyRegion(hps, hrgnNew);
+            WinReleasePS(hps);
+        }
     }
 
@@ -879,5 +1014,5 @@
                    "|  style = %08lX\n"
                    "|  fcFlags = %08lX",
-                   QWidgetPrivate::name(q).constData(), ownerw,
+                   qWidgetName(q).toUtf8().constData(), ownerw,
                    title.constData(), fStyle, fcFlags);
 #endif
@@ -907,5 +1042,5 @@
                    "|  title = '%s'\n"
                    "|  style = %08lX",
-                   QWidgetPrivate::name(q).constData(), fId, className.constData(),
+                   qWidgetName(q).toUtf8().constData(), fId, className.constData(),
                    title.constData(), style);
 #endif
@@ -920,5 +1055,5 @@
                    "|  title = '%s'\n"
                    "|  style = %08lX",
-                   QWidgetPrivate::name(q).constData(), className.constData(),
+                   qWidgetName(q).toUtf8().constData(), className.constData(),
                    title.constData(), style);
 #endif
@@ -995,6 +1130,9 @@
                 // because we didn't know the frame dimensions yet)
                 if (wasMoved) {
-                    swp.x = data.crect.left() - fs.left();
-                    swp.y = data.crect.top() - fs.top();
+                    // QWidget::move() includes frame strut so no correction is
+                    // necessary (crect was abused to store the frame position
+                    // until window creation)
+                    swp.x = data.crect.x();
+                    swp.y = data.crect.y();
                 }
                 if (wasResized) {
@@ -1034,5 +1172,5 @@
                "|  title = '%s'\n"
                "|  style = %08lX",
-               QWidgetPrivate::name(q).constData(), parentw, className.constData(),
+               qWidgetName(q).toUtf8().constData(), parentw, className.constData(),
                title.constData(), style);
 #endif
@@ -1108,5 +1246,5 @@
 #if defined(QT_DEBUGWINCREATEDESTROY)
             qDebug("|Destroying window [%s]:\n"
-                   "|  hwnd = %08lX", QWidgetPrivate::name(this).constData(), id);
+                   "|  hwnd = %08lX", qWidgetName(this).toUtf8().constData(), id);
 #endif
 
@@ -1241,5 +1379,90 @@
 void QWidget::setWindowState(Qt::WindowStates newstate)
 {
-    // @todo implement
+    Q_D(QWidget);
+    Qt::WindowStates oldstate = windowState();
+    if (oldstate == newstate)
+        return;
+
+    ULONG fl = (newstate & Qt::WindowActive) ? SWP_ACTIVATE : 0;
+
+    if (isWindow()) {
+        createWinId();
+        Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+
+        HWND fId = d->frameWinId();
+        Q_ASSERT(fId != NULLHANDLE);
+
+        // set flag for the WM_WINDOWPOSCHANGED handler in QtFrameProc
+        d->topData()->inSetWindowState = true;
+
+        // 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 && !(oldstate & Qt::WindowFullScreen))
+                d->topData()->normalGeometry = geometry();
+            if (isVisible() && !(newstate & Qt::WindowMinimized)) {
+                fl |= (newstate & Qt::WindowMaximized) ? SWP_MAXIMIZE : SWP_RESTORE;
+                WinSetWindowPos(fId, 0, 0, 0, 0, 0, fl);
+                if (!(newstate & Qt::WindowFullScreen)) {
+                    QRect r = d->topData()->normalGeometry;
+                    if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) {
+                        if (pos() != r.topLeft() || size() !=r.size()) {
+                            d->topData()->normalGeometry = QRect(0,0,-1,-1);
+                            setGeometry(r);
+                        }
+                    }
+                } else {
+                    d->updateFrameStrut();
+                }
+            }
+        }
+
+        if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+            if (newstate & Qt::WindowFullScreen) {
+                if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
+                    d->topData()->normalGeometry = geometry();
+                QRect r = QApplication::desktop()->screenGeometry(this);
+                QRect fs(d->frameStrut());
+                r.rLeft() -= fs.left();
+                r.rRight() += fs.right();
+                r.rTop() -= fs.top();
+                r.rBottom() += fs.bottom();
+                fl |= SWP_ZORDER | SWP_MOVE | SWP_SIZE;
+                WinSetWindowPos(fId, HWND_TOP, r.left(),
+                                // flip y coodrinate
+                                QApplication::desktop()->height() - (r.top() + r.width()),
+                                r.width(), r.height(), fl);
+            } else {
+                // preserve maximized state
+                if (isVisible()) {
+                    fl |= (newstate & Qt::WindowMaximized) ? SWP_MAXIMIZE : SWP_RESTORE;
+                    WinSetWindowPos(fId, 0, 0, 0, 0, 0, fl);
+                }
+
+                if (!(newstate & Qt::WindowMaximized)) {
+                    QRect r = d->topData()->normalGeometry;
+                    d->topData()->normalGeometry = QRect(0,0,-1,-1);
+                    if (r.isValid())
+                        setGeometry(r);
+                }
+            }
+        }
+
+        if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+            if (isVisible()) {
+                fl |= (newstate & Qt::WindowMinimized) ? SWP_MINIMIZE :
+                      (newstate & Qt::WindowMaximized) ? SWP_MAXIMIZE : SWP_RESTORE;
+                WinSetWindowPos(fId, 0, 0, 0, 0, 0, fl);
+            }
+        }
+
+        // set flag for the WM_WINDOWPOSCHANGED handler in QtFrameProc
+        d->topData()->inSetWindowState = false;
+    }
+    data->window_state = newstate;
+    QWindowStateChangeEvent e(oldstate);
+    QApplication::sendEvent(this, &e);
 }
 
@@ -1276,7 +1499,4 @@
 {
     Q_Q(QWidget);
-#if defined(QT_NON_COMMERCIAL)
-    QT_NC_SHOW_WINDOW
-#endif
     if (q->testAttribute(Qt::WA_OutsideWSRange))
         return;
@@ -1368,7 +1588,10 @@
 }
 
+#define XCOORD_MAX 32767
+#define WRECT_MAX 32767
+
 /*
   Helper function for non-toplevel widgets. Helps to map Qt's 32bit
-  coordinate system to Windpws's 16bit coordinate system.
+  coordinate system to PM 16bit coordinate system.
 
   This code is duplicated from the X11 code, so any changes there
@@ -1380,10 +1603,304 @@
 void QWidgetPrivate::setWSGeometry(bool dontShow)
 {
-    // @todo implement
-}
+    Q_Q(QWidget);
+    Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+    /*
+      There are up to four different coordinate systems here:
+      Qt coordinate system for this widget.
+      X coordinate system for this widget (relative to wrect).
+      Qt coordinate system for parent
+      X coordinate system for parent (relative to parent's wrect).
+     */
+    QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
+    QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
+    QRect wrect;
+    //xrect is the X geometry of my X widget. (starts out in  parent's Qt coord sys, and ends up in parent's X coord sys)
+    QRect xrect = data.crect;
+
+    const QWidget *const parent = q->parentWidget();
+    QRect parentWRect = parent->data->wrect;
+
+    if (parentWRect.isValid()) {
+        // parent is clipped, and we have to clip to the same limit as parent
+        if (!parentWRect.contains(xrect)) {
+            xrect &= parentWRect;
+            wrect = xrect;
+            //translate from parent's to my Qt coord sys
+            wrect.translate(-data.crect.topLeft());
+        }
+        //translate from parent's Qt coords to parent's X coords
+        xrect.translate(-parentWRect.topLeft());
+
+    } else {
+        // parent is not clipped, we may or may not have to clip
+
+        if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
+            // This is where the main optimization is: we are already
+            // clipped, and if our clip is still valid, we can just
+            // move our window, and do not need to move or clip
+            // children
+
+            QRect vrect = xrect & parent->rect();
+            vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
+            if (data.wrect.contains(vrect)) {
+                xrect = data.wrect;
+                xrect.translate(data.crect.topLeft());
+                if (q->internalWinId() != NULLHANDLE) {
+                    Q_ASSERT(parent->internalWinId() != NULLHANDLE);
+                    int h = parent->height();
+                    qt_WinSetWindowPos(q->internalWinId(), 0, xrect.x(),
+                                       // flip y coordinate
+                                       h - (xrect.y() + 1),
+                                       xrect.width(), xrect.height(),
+                                       SWP_MOVE | SWP_SIZE);
+                }
+                return;
+            }
+        }
+
+        if (!validRange.contains(xrect)) {
+            // we are too big, and must clip
+            xrect &=wrectRange;
+            wrect = xrect;
+            wrect.translate(-data.crect.topLeft());
+            //parent's X coord system is equal to parent's Qt coord
+            //sys, so we don't need to map xrect.
+        }
+
+    }
+
+
+    // unmap if we are outside the valid window system coord system
+    bool outsideRange = !xrect.isValid();
+    bool mapWindow = false;
+    if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
+        q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
+        if (outsideRange) {
+            if (q->internalWinId() != NULLHANDLE)
+                qt_WinSetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, SWP_HIDE);
+            q->setAttribute(Qt::WA_Mapped, false);
+        } else if (!q->isHidden()) {
+            mapWindow = true;
+        }
+    }
+
+    if (outsideRange)
+        return;
+
+    bool jump = (data.wrect != wrect);
+    data.wrect = wrect;
+
+    // and now recursively for all children...
+    for (int i = 0; i < children.size(); ++i) {
+        QObject *object = children.at(i);
+        if (object->isWidgetType()) {
+            QWidget *w = static_cast<QWidget *>(object);
+            if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
+                w->d_func()->setWSGeometry();
+        }
+    }
+
+    // move ourselves to the new position and map (if necessary) after
+    // the movement. Rationale: moving unmapped windows is much faster
+    // than moving mapped windows
+    if (q->internalWinId() != NULLHANDLE) {
+        int h = parent->height();
+        if (parent->internalWinId() == NULLHANDLE) {
+            xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
+            h = q->nativeParentWidget()->height();
+        }
+        qt_WinSetWindowPos(q->internalWinId(), 0, xrect.x(),
+                           // flip y coordinate
+                           h - (xrect.y() + 1),
+                           xrect.width(), xrect.height(), SWP_MOVE | SWP_SIZE);
+    }
+    if (mapWindow && !dontShow) {
+        q->setAttribute(Qt::WA_Mapped);
+        if (q->internalWinId() != NULLHANDLE)
+            qt_WinSetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, SWP_SHOW);
+    }
+
+    if (jump && q->internalWinId() != NULLHANDLE)
+        WinInvalidateRect(q->internalWinId(), NULL, FALSE);
+}
+
+//
+// The internal qPMRequestConfig, defined in qapplication_pm.cpp, stores move,
+// resize and setGeometry requests for a widget that is already
+// processing a config event. The purpose is to avoid recursion.
+//
+void qPMRequestConfig(WId, int, int, int, int, int);
 
 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
 {
-    // @todo implement
+    Q_Q(QWidget);
+    Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+    if (extra) { // any size restrictions?
+        w = qMin(w,extra->maxw);
+        h = qMin(h,extra->maxh);
+        w = qMax(w,extra->minw);
+        h = qMax(h,extra->minh);
+    }
+    if (q->isWindow())
+        topData()->normalGeometry = QRect(0, 0, -1, -1);
+
+    QSize  oldSize(q->size());
+    QPoint oldPos(q->pos());
+
+    if (!q->isWindow())
+        isMove = (data.crect.topLeft() != QPoint(x, y));
+    bool isResize = w != oldSize.width() || h != oldSize.height();
+
+    if (!isMove && !isResize)
+        return;
+
+    HWND fId = frameWinId();
+
+    if (isResize && !q->testAttribute(Qt::WA_StaticContents) &&
+        q->internalWinId() != NULLHANDLE) {
+        RECTL rcl = { 0, 0, data.crect.width(), data.crect.height() };
+        WinValidateRect(q->internalWinId(), &rcl, FALSE);
+    }
+
+    if (isResize)
+        data.window_state &= ~Qt::WindowMaximized;
+
+    if (data.window_state & Qt::WindowFullScreen) {
+        data.window_state &= ~Qt::WindowFullScreen;
+    }
+
+    QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+    const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
+
+    if (q->testAttribute(Qt::WA_WState_ConfigPending)) {        // processing config event
+        if (q->internalWinId() != NULLHANDLE)
+            qPMRequestConfig(q->internalWinId(), isMove ? 2 : 1, x, y, w, h);
+    } else {
+        if (!q->testAttribute(Qt::WA_DontShowOnScreen))
+            q->setAttribute(Qt::WA_WState_ConfigPending);
+        if (q->windowType() == Qt::Desktop) {
+            data.crect.setRect(x, y, w, h);
+        } else if (q->isWindow()) {
+            int sh = QApplication::desktop()->height();
+            QRect fs(frameStrut());
+            if (extra) {
+                fs.setLeft(x - fs.left());
+                fs.setTop(y - fs.top());
+                fs.setRight((x + w - 1) + fs.right());
+                fs.setBottom((y + h - 1) + fs.bottom());
+            }
+            if (w == 0 || h == 0) {
+                q->setAttribute(Qt::WA_OutsideWSRange, true);
+                if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+                    hide_sys();
+                data.crect = QRect(x, y, w, h);
+            } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+                q->setAttribute(Qt::WA_OutsideWSRange, false);
+
+                // put the window in its place and show it
+                WinSetWindowPos(fId, 0, fs.x(),
+                                // flip y coordinate
+                                sh - (fs.y() + fs.height()),
+                                fs.width(), fs.height(), SWP_MOVE | SWP_SIZE);
+                data.crect.setRect(x, y, w, h);
+
+                show_sys();
+            } else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
+                q->setAttribute(Qt::WA_OutsideWSRange, false);
+                // If the window is hidden and in maximized state or minimized, instead of moving the
+                // window, set the normal position of the window.
+                SWP swp;
+                WinQueryWindowPos(fId, &swp);
+                if (((swp.fl & SWP_MAXIMIZE) && !WinIsWindowVisible(fId)) ||
+                    (swp.fl & SWP_MINIMIZE)) {
+                    WinSetWindowUShort(fId, QWS_XRESTORE, fs.x());
+                    WinSetWindowUShort(fId, QWS_YRESTORE, // flip y coordinate
+                                       sh - (fs.y() + fs.height()));
+                    WinSetWindowUShort(fId, QWS_CXRESTORE, fs.width());
+                    WinSetWindowUShort(fId, QWS_CYRESTORE, fs.height());
+                } else {
+                    WinSetWindowPos(fId, 0, fs.x(),
+                                    // flip y coordinate
+                                    sh - (fs.y() + fs.height()),
+                                    fs.width(), fs.height(), SWP_MOVE | SWP_SIZE);
+                }
+                if (!q->isVisible())
+                    WinInvalidateRect(q->internalWinId(), NULL, FALSE);
+
+                // If the layout has heightForWidth, the WinSetWindowPos() above can
+                // change the size/position, so refresh them.
+                WinQueryWindowPos(fId, &swp);
+                // flip y coordinate
+                swp.y = sh - (swp.y + swp.cy);
+                QRect fs(frameStrut());
+                data.crect.setRect(swp.x + fs.left(),
+                                   swp.y + fs.top(),
+                                   swp.cx - fs.left() - fs.right(),
+                                   swp.cy - fs.top() - fs.bottom());
+                isResize = data.crect.size() != oldSize;
+            } else {
+                q->setAttribute(Qt::WA_OutsideWSRange, false);
+                data.crect.setRect(x, y, w, h);
+            }
+        } else {
+            QRect oldGeom(data.crect);
+            data.crect.setRect(x, y, w, h);
+            if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
+                // Top-level resize optimization does not work for native child widgets;
+                // disable it for this particular widget.
+                if (inTopLevelResize)
+                    tlwExtra->inTopLevelResize = false;
+
+                if (!isResize)
+                    moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
+                else
+                    invalidateBuffer_resizeHelper(oldPos, oldSize);
+
+                if (inTopLevelResize)
+                    tlwExtra->inTopLevelResize = true;
+            }
+            if (q->testAttribute(Qt::WA_WState_Created))
+                setWSGeometry();
+        }
+        q->setAttribute(Qt::WA_WState_ConfigPending, false);
+    }
+
+    if (q->isWindow() && q->isVisible() && isResize && !inTopLevelResize) {
+        invalidateBuffer(q->rect()); //after the resize
+    }
+
+    // Process events immediately rather than in translateConfigEvent to
+    // avoid windows message process delay.
+    if (q->isVisible()) {
+        if (isMove && q->pos() != oldPos) {
+            // in QMoveEvent, pos() and oldPos() exclude the frame, adjust them
+            QRect fs(frameStrut());
+            QMoveEvent e(q->pos() + fs.topLeft(), oldPos + fs.topLeft());
+            QApplication::sendEvent(q, &e);
+        }
+        if (isResize) {
+            static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+            // If we have a backing store with static contents, we have to disable the top-level
+            // resize optimization in order to get invalidated regions for resized widgets.
+            // The optimization discards all invalidateBuffer() calls since we're going to
+            // repaint everything anyways, but that's not the case with static contents.
+            const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
+                                           && !extra->topextra->inTopLevelResize
+                                           && (!extra->topextra->backingStore
+                                               || !extra->topextra->backingStore->hasStaticContents());
+            if (setTopLevelResize)
+                extra->topextra->inTopLevelResize = true;
+            QResizeEvent e(q->size(), oldSize);
+            QApplication::sendEvent(q, &e);
+            if (setTopLevelResize)
+                extra->topextra->inTopLevelResize = false;
+        }
+    } else {
+        if (isMove && q->pos() != oldPos)
+            q->setAttribute(Qt::WA_PendingMoveEvent, true);
+        if (isResize)
+            q->setAttribute(Qt::WA_PendingResizeEvent, true);
+    }
 }
 
@@ -1423,4 +1940,5 @@
     extra->topextra->fId = NULLHANDLE;
     extra->topextra->swEntry = NULLHANDLE;
+    extra->topextra->inSetWindowState = false;
 }
 
@@ -1540,37 +2058,3 @@
 }
 
-/*!
-    Returns a QWidget pointer or 0 if there is no widget corresponding to the
-    given HWND. As opposed to QWidget::find(), correctly handles WC_FRAME
-    windows created for top level widgets. Used for debugging.
- */
-// static
-QWidget *QWidgetPrivate::fromHWND(HWND hwnd)
-{
-    char buf[10];
-    if (WinQueryClassName(hwnd, sizeof(buf), buf)) {
-        if (!strcmp(buf, "#1")) // WC_FRAME
-            hwnd = WinWindowFromID(hwnd, FID_CLIENT);
-        return QWidget::find(hwnd);
-    }
-    return 0;
-}
-
-/*!
-    \internal
-
-    Returns a human readable widget name in the form "class/name". Used for
-    debugging.
- */
-// static
-QByteArray QWidgetPrivate::name(QWidget *w)
-{
-    if (w)
-        return QString()
-            .sprintf("%s/%s", w->metaObject()->className(),
-                     w->objectName().toLocal8Bit().constData()).toLocal8Bit();
-    return QByteArray("<no-widget>");
-}
-
-
 QT_END_NAMESPACE
Index: /trunk/src/gui/kernel/qwindowdefs_pm.h
===================================================================
--- /trunk/src/gui/kernel/qwindowdefs_pm.h	(revision 119)
+++ /trunk/src/gui/kernel/qwindowdefs_pm.h	(revision 120)
@@ -68,6 +68,4 @@
 #define NULLHANDLE ((LHANDLE)0)
 
-Q_GUI_EXPORT HPS qt_display_ps();
-
 // constants to address extra window data
 #define QWL_QTCLIPRGN       (QWL_USER)
@@ -77,4 +75,47 @@
 QT_BEGIN_NAMESPACE
 
+class QWidget;
+
+Q_GUI_EXPORT HPS qt_display_ps();
+
+Q_GUI_EXPORT QWidget *qWidgetFromHWND(HWND hwnd);
+
+// For printing non-quoted QString's with QDebug
+struct Q_CORE_EXPORT QDbgStr: public QString
+{
+    inline QDbgStr(const QString &str) : QString(str) {}
+};
+
+Q_GUI_EXPORT QDbgStr qWidgetName(QWidget *w);
+inline QDbgStr qWidgetName(HWND hwnd)
+{ return qWidgetName(qWidgetFromHWND(hwnd)); }
+
+Q_CORE_EXPORT QDbgStr qStrHWND(HWND hwnd);
+Q_CORE_EXPORT QDbgStr qStrHPS(HPS hps);
+Q_CORE_EXPORT QDbgStr qStrHPOINTER(HPOINTER hptr);
+Q_CORE_EXPORT QDbgStr qStrHRGN(HRGN hrgn);
+
+Q_CORE_EXPORT QDbgStr qStrQMSG(const QMSG &qmsg);
+
+// the following declarations require OS/2 types not defined here,
+// we don't drag them in but require qt_os2.h to be included before
+#if defined(QT_OS2_H)
+
+Q_CORE_EXPORT QDbgStr qStrRECTL(const RECTL &rcl);
+
+#endif // defined(QT_OS2_H)
+
+// don't drag qdebug.h as well but require it to be included before
+#if defined(QDEBUG_H) && !defined(QT_NO_DEBUG_STREAM)
+
+// Prints a non-quoted QString
+inline QDebug operator<<(QDebug dbg, const QDbgStr &str)
+{ dbg << str.utf8().constData(); return dbg; }
+
+inline QDebug operator<<(QDebug dbg, const RECTL &rcl)
+{ dbg << qStrRECTL(rcl); return dbg; }
+
+#endif // defined(QDEBUG_H) && !defined(QT_NO_DEBUG_STREAM)
+
 QT_END_NAMESPACE
 
Index: /trunk/src/gui/painting/qwindowsurface_raster.cpp
===================================================================
--- /trunk/src/gui/painting/qwindowsurface_raster.cpp	(revision 119)
+++ /trunk/src/gui/painting/qwindowsurface_raster.cpp	(revision 120)
@@ -205,5 +205,5 @@
 #if 1
     qDebug("QRasterWindowSurface::flush: [%s] br=%d,%d/%d,%d",
-           QWidgetPrivate::name(widget).constData(),
+           qWidgetName(widget).toUtf8().constData(),
            br.x(), br.y(), br.width(), br.height());
 #endif
