Index: /trunk/src/gui/kernel/qapplication_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 98)
+++ /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 99)
@@ -91,9 +91,7 @@
 static void releaseAutoCapture();
 
-static void unregWinClasses();
-
 extern QCursor *qt_grab_cursor();
 
-extern "C" MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
+MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
 
 class QETWidget : public QWidget                // event translator widget
@@ -189,5 +187,4 @@
 void qt_cleanup()
 {
-    unregWinClasses();
     QPixmapCache::clear();
 
@@ -224,45 +221,4 @@
     return false;
 #endif
-}
-
-typedef QSet<QString> WinClassNameHash;
-Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
-
-// register window class
-const QString qt_reg_winclass(QWidget *w)
-{
-    int flags = w->windowFlags();
-    int type = flags & Qt::WindowType_Mask;
-
-    QString cname;
-    ULONG style = 0;
-
-    if (type == Qt::Window) {
-        // this class is for frame window clients when WC_FRAME is used.
-        cname = QLatin1String("QWindow");
-        style |= CS_MOVENOTIFY;
-    } else if (type == Qt::Popup || type == Qt::Tool || type == Qt::ToolTip) {
-        cname = QLatin1String("QPopup");
-        // @todo do we really want SAVEBITS here?
-        style |= CS_SAVEBITS;
-    } else {
-        cname = QLatin1String("QWidget");
-    }
-
-    if (winclassNames()->contains(cname)) // already registered in our list
-        return cname;
-
-    // QT_EXTRAWINDATASIZE is defined in qwindowdefs_pm.h
-    WinRegisterClass(0, cname.toLatin1(), QtWndProc, style, QT_EXTRAWINDATASIZE);
-
-    winclassNames()->insert(cname);
-    return cname;
-}
-
-static void unregWinClasses()
-{
-    // there is no need to unregister private window classes -- it is done
-    // automatically upon process termination.
-    winclassNames()->clear();
 }
 
@@ -466,6 +422,13 @@
 // QtWndProc() receives all messages from the main event loop
 
-extern "C"
 MRESULT EXPENTRY QtWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+    // @todo implement
+    return FALSE;
+}
+
+PFNWP QtOldFrameProc = 0;
+
+MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 {
     // @todo implement
Index: /trunk/src/gui/kernel/qwidget_p.h
===================================================================
--- /trunk/src/gui/kernel/qwidget_p.h	(revision 98)
+++ /trunk/src/gui/kernel/qwidget_p.h	(revision 99)
@@ -67,4 +67,8 @@
 #endif // Q_WS_WIN
 
+#ifdef Q_WS_PM
+#include "QtCore/qt_os2.h"
+#endif
+
 #ifdef Q_WS_X11
 #include "QtGui/qx11info_x11.h"
@@ -150,4 +154,7 @@
     HICON winIconSmall; // internal small Windows icon
 #endif
+#if defined(Q_WS_PM)
+    HWND fId;
+#endif
     QRect normalGeometry; // used by showMin/maximized/FullScreen
     QWindowSurface *windowSurface;
@@ -460,4 +467,10 @@
 
     QInputContext *inputContext() const;
+
+#if defined(Q_WS_PM)
+    HWND frameWinId() const
+    { return maybeTopData() && maybeTopData()->fId != NULLHANDLE ?
+             maybeTopData()->fId : data.winid; }
+#endif
 
 #if defined(Q_WS_QWS)
Index: /trunk/src/gui/kernel/qwidget_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 98)
+++ /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 99)
@@ -48,4 +48,5 @@
 
 #include "qapplication.h"
+#include "qdesktopwidget.h"
 
 #include "private/qapplication_p.h"
@@ -53,10 +54,134 @@
 #include <qdebug.h>
 
+#define QT_DEBUGWINCREATEDESTROY
+
 QT_BEGIN_NAMESPACE
+
+static QWidget *mouseGrb    = 0;
+static QCursor *mouseGrbCur = 0;
+static QWidget *keyboardGrb = 0;
 
 // defined in qapplication_pm.cpp
 extern bool qt_nograb();
-extern const QString qt_reg_winclass(QWidget *w);
-extern "C" MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
+extern MRESULT EXPENTRY QtWndProc(HWND, ULONG, MPARAM, MPARAM);
+extern PFNWP QtOldFrameProc;
+extern MRESULT EXPENTRY QtFrameProc(HWND, ULONG, MPARAM, MPARAM);
+
+typedef QSet<QString> WinClassNameHash;
+Q_GLOBAL_STATIC(WinClassNameHash, winclassNames)
+
+// register window class
+static const QString qt_reg_winclass(QWidget *w)
+{
+    int flags = w->windowFlags();
+    int type = flags & Qt::WindowType_Mask;
+
+    QString cname;
+    ULONG style = 0;
+
+    if (type == Qt::Popup || type == Qt::ToolTip) {
+        cname = QLatin1String("QPopup");
+        style |= CS_SAVEBITS;
+    } else if (w->isWindow()) {
+        // this class is for top level widgets which are client HWNDs of a
+        // WC_FRAME parent HWND internally maintaned for them
+        cname = QLatin1String("QWindow");
+        style |= CS_MOVENOTIFY;
+    } else {
+        cname = QLatin1String("QWidget");
+    }
+
+    if (winclassNames()->contains(cname)) // already registered in our list
+        return cname;
+
+    // QT_EXTRAWINDATASIZE is defined in qwindowdefs_pm.h
+    WinRegisterClass(0, cname.toLatin1(), QtWndProc, style, QT_EXTRAWINDATASIZE);
+
+    winclassNames()->insert(cname);
+    return cname;
+
+    // Note: there is no need to unregister private window classes registered by
+    // this function -- it is done automatically upon process termination.
+}
+
+/*!
+ * \internal
+ * For some unknown reason, PM sends WM_SAVEAPPLICATION to every window
+ * being destroyed, which makes it indistinguishable from WM_SAVEAPPLICATION
+ * sent to top level windows during system shutdown. We use our own version of
+ * WinDestroyWindow() and a special flag (qt_about_to_destroy_wnd) to
+ * distinguish it in qapplication_pm.cpp.
+ */
+static BOOL qt_WinDestroyWindow(HWND hwnd)
+{
+#if !defined (QT_NO_SESSIONMANAGER)
+    qt_about_to_destroy_wnd = true;
+#endif
+    BOOL rc = WinDestroyWindow(hwnd);
+#if !defined (QT_NO_SESSIONMANAGER)
+    qt_about_to_destroy_wnd = false;
+#endif
+    return rc;
+}
+
+static PFNWP QtOldSysMenuProc;
+static MRESULT EXPENTRY QtSysMenuProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+    if (msg == WM_MENUEND) {
+        // the pull-down menu is closed, always dismiss the system menu itself
+        WinPostMsg(hwnd, MM_ENDMENUMODE, MPFROMSHORT(TRUE), 0);
+    }
+    return QtOldSysMenuProc(hwnd, msg, mp1, mp2);
+}
+
+static void removeSysMenuAccels(HWND frame)
+{
+    HWND sysMenu = WinWindowFromID(frame, FID_SYSMENU);
+    if (!sysMenu)
+        return;
+
+    SHORT subId = SHORT1FROMMR(WinSendMsg(sysMenu, MM_ITEMIDFROMPOSITION, 0, 0));
+    if (subId != MIT_ERROR) {
+        MENUITEM item;
+        WinSendMsg(sysMenu, MM_QUERYITEM, MPFROM2SHORT(subId, FALSE), MPFROMP(&item));
+        HWND subMenu = item.hwndSubMenu;
+        if (subMenu) {
+            USHORT cnt = SHORT1FROMMR(WinSendMsg(subMenu, MM_QUERYITEMCOUNT, 0, 0));
+            for (int i = 0; i < cnt; i++) {
+                USHORT id = SHORT1FROMMR(
+                    WinSendMsg(subMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(i), 0));
+                if (id == SC_TASKMANAGER || id == SC_CLOSE) {
+                    // accels for these entries always work in Qt, skip them
+                    continue;
+                }
+                USHORT len = SHORT1FROMMR(
+                    WinSendMsg(subMenu, MM_QUERYITEMTEXTLENGTH, MPFROMSHORT(id), 0));
+                if (len++) {
+                    char *text = new char[len];
+                    WinSendMsg(subMenu, MM_QUERYITEMTEXT,
+                        MPFROM2SHORT(id, len), MPFROMP(text));
+                    char *tab = strrchr(text, '\t');
+                    if (tab) {
+                        *tab = 0;
+                        WinSendMsg(subMenu, MM_SETITEMTEXT,
+                            MPFROMSHORT(id), MPFROMP(text));
+                    }
+                    delete[] text;
+                }
+            }
+            // sublclass the system menu to leave the menu mode completely
+            // when the user presses the ESC key. by default, pressing ESC
+            // while the pull-down menu is showing brings us to the menu bar,
+            // which is confusing in the case of the system menu, because
+            // there is only one item on the menu bar, and we cannot see
+            // that it is active when the frame window has an icon.
+            PFNWP oldProc = WinSubclassWindow(sysMenu, QtSysMenuProc);
+            // set QtOldSysMenuProc only once: it must be the same for
+            // all FID_SYSMENU windows.
+            if (!QtOldSysMenuProc)
+                QtOldSysMenuProc = oldProc;
+        }
+    }
+}
 
 /*****************************************************************************
@@ -66,10 +191,398 @@
 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
 {
-    // @todo implement
+    // @todo when window is not zero, it represents an existing (external)
+    // window handle we should create a QWidget "wrapper" for to incorporate it
+    // to the Qt widget hierarchy. This functionality isn't really necessary on
+    // OS/2 at the moment, so it is not currently supported (and the window
+    // argument is simply ignored). Note that destroyOldWindow only makes
+    //  sense when window is != 0 so it is also ignored.
+
+    Q_ASSERT(window == 0);
+    Q_UNUSED(destroyOldWindow);
+
+    Q_Q(QWidget);
+    static int sw = -1, sh = -1;
+
+    Qt::WindowType type = q->windowType();
+    Qt::WindowFlags flags = data.window_flags;
+
+    bool topLevel = q->isWindow();
+    bool popup = (type == Qt::Popup);
+    bool dialog = (type == Qt::Dialog
+                   || type == Qt::Sheet
+                   || (flags & Qt::MSWindowsFixedSizeDialogHint));
+    bool desktop = (type == Qt::Desktop);
+    bool tool = (type == Qt::Tool || type == Qt::Drawer);
+
+    WId id;
+
+    QByteArray className = qt_reg_winclass(q).toLatin1();
+
+    // @todo WindowStaysOnTopHint is ignored for now (does nothing)
+    if (popup)
+        flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
+
+    if (sw < 0) { // get the screen size
+        sw = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
+        sh = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
+    }
+
+    if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget
+        popup = false; // force this flags off
+        // @todo use WinGetMaxPositionto take into account such things as XCenter?
+        data.crect.setRect(0, 0, sw, sh);
+    }
+
+    QByteArray title;
+    ULONG style = 0;
+    ULONG fId = 0, fStyle = 0, fcFlags = 0;
+
+    if (!desktop) {
+        // @todo testing for Qt::WA_PaintUnclipped is commented out because it
+        // is said that it causes some problems on Win32 and we also saw the
+        // problems with this line enabled in Qt3 on OS/2 in QT_PM_NO_WIDGETMASK
+        // mode (terrible flicker in QFileDialog because QSplitter used there
+        // sets WA_PaintUnclipped). This however doesn't make a big difference
+        // now since we don't support QT_PM_NO_WIDGETMASK anymore (read below
+        // about clipping) and is left here just to show where WA_PaintUnclipped
+        // was originally intended to be used.
+#if 0
+        if (!testAttribute(Qt::WA_PaintUnclipped))
+#endif
+        {
+            // We don't use WS_CLIPSIBLINGS and WS_CLIPCHILDREN because when these
+            // styles are set and the child (sibling) window has a non-NULL clip region,
+            // PM still continues to exclude the entire child's rectangle from the
+            // parent window's update region, ignoring its clip region. As a result,
+            // areas outside the clip region are left unpainted. Instead, we correct
+            // the update region of the window ourselves, on every WM_PAINT event.
+            // Note: for top-level widgets, we specify WS_CLIPSIBLINGS anyway to let
+            // the system do correct clipping for us (qt_WinProcessWindowObstacles()
+            // relies on this). It's ok because top-level widgets cannot be non-
+            // rectangular and therefore don't require our magic clipping procedure.
+            if (topLevel)
+                style |= WS_CLIPSIBLINGS;
+        }
+
+        // for all top-level windows except popups we create a WC_FRAME
+        // as a parent and owner.
+    	if (topLevel && !popup) {
+            if ((type == Qt::Window || dialog || tool)) {
+                if (!(flags & Qt::FramelessWindowHint)) {
+                    if (flags & Qt::MSWindowsFixedSizeDialogHint) {
+                        fcFlags |= FCF_DLGBORDER;
+                    } else if (tool) {
+                        fcFlags |= FCF_BORDER;
+                    } else {
+                        fcFlags |= FCF_SIZEBORDER;
+                    }
+                }
+                if (flags & Qt::WindowTitleHint)
+                    fcFlags |= FCF_TITLEBAR;
+                if (flags & Qt::WindowSystemMenuHint)
+                    fcFlags |= FCF_SYSMENU | FCF_CLOSEBUTTON;
+                if (flags & Qt::WindowMinimizeButtonHint)
+                    fcFlags |= FCF_MINBUTTON;
+                if (flags & Qt::WindowMaximizeButtonHint)
+                    fcFlags |= FCF_MAXBUTTON;
+            } else {
+                fcFlags |= FCF_BORDER;
+            }
+
+            fStyle |= FS_NOMOVEWITHOWNER | FS_NOBYTEALIGN;
+            fStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+    	}
+    }
+
+    if (flags & Qt::WindowTitleHint) {
+        title = topLevel ? qAppName().toLocal8Bit() : q->objectName().toLocal8Bit();
+    }
+
+    // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in
+    // qapplication_pm.cpp. We switch it off temporarily to avoid move
+    // and resize events during creation
+    q->setAttribute(Qt::WA_WState_Created, false);
+
+    if (desktop) { // desktop widget
+        id = WinQueryDesktopWindow(0, 0);
+        // @todo commented out on Win32 too
+//      QWidget *otherDesktop = QWidget::find(id); // is there another desktop?
+//      if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
+//          otherDesktop->d_func()->setWinId(0); // remove id from widget mapper
+//          setWinId(id); // make sure otherDesktop is found first
+//          otherDesktop->d_func()->setWinId(id);
+//      } else {
+            setWinId(id);
+//      }
+    } else if (topLevel) {
+        // create top-level widget
+        if (!popup) {
+            HWND ownerw = NULLHANDLE;
+            QWidget *parent = q->parentWidget();
+
+QWidgetPrivate *ppp;
+ppp->frameWinId();
+            if (parent && !(parent->windowType() == Qt::Desktop))
+                ownerw = parent->window()->d_func()->frameWinId();
+            // create WC_FRAME
+            FRAMECDATA fcData;
+            fcData.cb = sizeof(FRAMECDATA);
+            fcData.flCreateFlags = fcFlags;
+            fcData.hmodResources = NULL;
+            fcData.idResources = 0;
+            // check whether a default icon is present in .EXE and use it if so
+            ULONG sz = 0;
+            if (DosQueryResourceSize(NULL, RT_POINTER, 1, &sz) == 0) {
+                fcData.flCreateFlags |= FCF_ICON;
+                fcData.idResources = 1;
+            }
+#if defined(QT_DEBUGWINCREATEDESTROY)
+            qDebug("|Creating top level window (frame) [%s/%s]:\n"
+                   "|  owner = %08lX\n"
+                   "|  title = '%s'\n"
+                   "|  style = %08lX\n"
+                   "|  fcFlags = %08lX",
+                   q->objectName().toLocal8Bit().constData(),
+                   q->metaObject()->className(),
+                   ownerw, title.constData(), fStyle, fcFlags);
+#endif
+            fId = WinCreateWindow(HWND_DESKTOP, WC_FRAME, title, fStyle,
+                                  0, 0, 0, 0, ownerw, HWND_TOP, 0,
+                                  &fcData, NULL);
+#if defined(QT_DEBUGWINCREATEDESTROY)
+            qDebug("|  hwnd = %08lX", fId);
+#endif
+            if (fId == NULLHANDLE)
+                qWarning("QWidget::create(): WinCreateWindow(WC_FRAME) "
+                         "failed with 0x%08lX", WinGetLastError(0));
+
+            PFNWP oldProc = WinSubclassWindow(fId, QtFrameProc);
+            // remember QtOldFrameProc only once: it's the same for
+            // all WC_FRAME windows.
+            if (!QtOldFrameProc)
+                QtOldFrameProc = oldProc;
+
+            removeSysMenuAccels(fId);
+
+            // create client window
+#if defined(QT_DEBUGWINCREATEDESTROY)
+            qDebug("|Creating top level window (client) [%s/%s]:\n"
+                   "|  owner & parent = %08lX\n"
+                   "|  class = '%s'\n"
+                   "|  title = '%s'\n"
+                   "|  style = %08lX",
+                   q->objectName().toLocal8Bit().constData(),
+                   q->metaObject()->className(),
+                   fId, className.constData(), title.constData(), style);
+#endif
+            // note that we place the client on top (HWND_TOP) to exclude other
+            // frame controls from being analyzed in qt_WinProcessWindowObstacles
+            id = WinCreateWindow(fId, className, title, style, 0, 0, 0, 0,
+                                 fId, HWND_TOP, FID_CLIENT, NULL, NULL);
+        } else {
+#if defined(QT_DEBUGWINCREATEDESTROY)
+            qDebug("|Creating top level window (popup) [%s/%s]:\n"
+                   "|  class = '%s'\n"
+                   "|  title = '%s'\n"
+                   "|  style = %08lX",
+                   q->objectName().toLocal8Bit().constData(),
+                   q->metaObject()->className(),
+                   className.constData(), title.constData(), style);
+#endif
+            id = WinCreateWindow(HWND_DESKTOP, className, title, style,
+                                 0, 0, 0, 0, NULLHANDLE, HWND_TOP, 0, NULL, NULL);
+        }
+#if defined(QT_DEBUGWINCREATEDESTROY)
+        qDebug("|  hwnd = %08lX", id);
+#endif
+        if (id == NULLHANDLE)
+            qWarning("QWidget::create(): WinCreateWindow "
+                     "failed with 0x%08lX", WinGetLastError(0));
+        setWinId(id);
+
+        // it isn't mentioned in PMREF that PM is obliged to initialize window
+        // data with zeroes (although seems to), so do it ourselves
+        for (LONG i = 0; i <= (LONG) (QT_EXTRAWINDATASIZE - 4); i += 4)
+            WinSetWindowULong(id, i, 0);
+
+        SWP swp;
+        // Get the default window position and size. Note that when the
+        // FS_SHELLPOSITION flag is specified during WC_FRAME window
+        // creation its size and position remains zero until it is shown
+        // for the first time. So, we don't use FS_SHELLPOSITION but emulate
+        // its functionality here.
+        WinQueryTaskSizePos(0, 0, &swp);
+
+        //update position & initial size of POPUP window
+        const bool wasMoved = q->testAttribute(Qt::WA_Moved);
+        const bool wasResized = q->testAttribute(Qt::WA_Resized);
+        const bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen);
+        if (popup && initializeWindow && isVisibleOnScreen) {
+            if (!q->testAttribute(Qt::WA_Resized)) {
+                swp.cx = sw / 2;
+                swp.cy = 4 * sh / 10;
+            }
+            if (!wasMoved) {
+                swp.x = sw / 2 - swp.cx / 2;
+                swp.y = sh / 2 - swp.cy / 2;
+            }
+        }
+
+        ULONG fl = SWP_SIZE | SWP_MOVE;
+        HWND insertBehind = NULLHANDLE;
+        if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) {
+            insertBehind = HWND_TOP;
+            fl |= SWP_ZORDER;
+            if (flags & Qt::WindowStaysOnBottomHint)
+                qWarning() << "QWidget: Incompatible window flags: the window "
+                              "can't be on top and on bottom at the same time";
+        } else if (flags & Qt::WindowStaysOnBottomHint) {
+            insertBehind = HWND_BOTTOM;
+            fl |= SWP_ZORDER;
+        }
+        WinSetWindowPos(popup ? id : fId, insertBehind,
+                        swp.x, swp.y, swp.cx, swp.cy, fl);
+
+        if (!popup) {
+            QTLWExtra *top = topData();
+            top->fId = fId;
+            WinQueryWindowPos(fId, &swp);
+            SWP cswp;
+            WinQueryWindowPos(id, &cswp);
+            // flip y coordinates
+            swp.y = sh - (swp.y + swp.cy);
+            cswp.y = swp.cy - (cswp.y + cswp.cy);
+            // store frame dimensions
+            QRect &fs = top->frameStrut;
+            fs.setCoords(cswp.x, cswp.y, swp.cx - cswp.x - cswp.cx,
+                                         swp.cy - cswp.y - cswp.cy);
+            data.fstrut_dirty = false;
+            if (wasMoved || wasResized) {
+                // resize & move if necessary (we couldn't do it earlier
+                // 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();
+                }
+                if (wasResized) {
+                    swp.cx = data.crect.width() + fs.left() + fs.right();
+                    swp.cy = data.crect.height() + fs.top() + fs.bottom();
+                }
+                // flip y coordinate
+                swp.y = sh - (swp.y + swp.cy);
+                WinSetWindowPos(fId, NULLHANDLE, swp.x, swp.y, swp.cx, swp.cy,
+                                SWP_SIZE | SWP_MOVE);
+            }
+        }
+
+        if (!popup || (initializeWindow && isVisibleOnScreen)) {
+            // fetch the actual geometry
+            WinQueryWindowPos(popup ? id : fId, &swp);
+            // flip y coordinate
+            swp.y = sh - (swp.y + swp.cy);
+            if (popup) {
+                data.crect.setRect(swp.x, swp.y, swp.cx, swp.cy);
+            } else {
+                const QRect &fs = topData()->frameStrut;
+                data.crect.setRect(swp.x + fs.left(), swp.y + fs.top(),
+                                   swp.cx - fs.left() - fs.right(),
+                                   swp.cy - fs.top() - fs.bottom());
+            }
+        }
+    } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
+        // create child widget
+        Q_ASSERT(q->parentWidget());
+        HWND parentw = q->parentWidget()->effectiveWinId();
+
+#if defined(QT_DEBUGWINCREATEDESTROY)
+        qDebug("|Creating child window [%s/%s]:\n"
+               "|  owner & parent = %08lX\n"
+               "|  class = '%s'\n"
+               "|  title = '%s'\n"
+               "|  style = %08lX",
+               q->objectName().toLocal8Bit().constData(),
+               q->metaObject()->className(),
+               parentw, className.constData(), title.constData(), style);
+#endif
+        id = WinCreateWindow(parentw, className, title, style,
+                             data.crect.left(),
+                             // flip y coordinate
+                             q->parentWidget()->height() - data.crect.bottom() - 1,
+                             data.crect.width(), data.crect.height(),
+                             parentw, HWND_TOP, 0, NULL, NULL);
+#if defined(QT_DEBUGWINCREATEDESTROY)
+        qDebug("|  hwnd = %08lX", id);
+#endif
+        if (id == NULLHANDLE)
+            qWarning("QWidget::create(): WinCreateWindow "
+                     "failed with 0x%08lX", WinGetLastError(0));
+    	setWinId(id);
+    }
+
+    if (desktop) {
+        q->setAttribute(Qt::WA_WState_Visible);
+    }
+
+    q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
+
+    hd = 0; // no presentation space
+
+    if (extra && !extra->mask.isEmpty())
+        setMask_sys(extra->mask);
+
+    if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) {
+        q->setAttribute(Qt::WA_OutsideWSRange, true);
+    }
+
+    if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
+        Q_ASSERT(q->internalWinId() != NULLHANDLE);
+        WinShowWindow(q->internalWinId(), TRUE);
+    }
 }
 
 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
 {
-    // @todo implement
+    Q_D(QWidget);
+    if (!isWindow() && parentWidget())
+        parentWidget()->d_func()->invalidateBuffer(geometry());
+    d->deactivateWidgetCleanup();
+    if (testAttribute(Qt::WA_WState_Created)) {
+        setAttribute(Qt::WA_WState_Created, false);
+        for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children
+            register QObject *obj = d->children.at(i);
+            if (obj->isWidgetType())
+                ((QWidget*)obj)->destroy(destroySubWindows,
+                                         destroySubWindows);
+        }
+        if (mouseGrb == this)
+            releaseMouse();
+        if (keyboardGrb == this)
+            releaseKeyboard();
+        if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal
+            QApplicationPrivate::leaveModal(this);
+        else if ((windowType() == Qt::Popup))
+            qApp->d_func()->closePopup(this);
+        if (destroyWindow && !(windowType() == Qt::Desktop) &&
+            internalWinId() != NULLHANDLE) {
+            HWND id = internalWinId();
+            if (isWindow() && !(windowType() == Qt::Popup)) {
+                // extra data including extra->topextra has been already
+                // deleted at this point by deleteExtra() and therefore
+                // calling frameWinId() is useless -- it will return the
+                // client window handle. Use WinQueryWindow() instead.
+                id = WinQueryWindow(id, QW_PARENT);
+                Q_ASSERT(id != NULLHANDLE);
+            }
+#if defined(QT_DEBUGWINCREATEDESTROY)
+            qDebug("|Destroying window [%s/%s]:\n"
+                   "|  hwnd = %08lX",
+                   objectName().toLocal8Bit().constData(),
+                   metaObject()->className(), id);
+#endif
+
+            qt_WinDestroyWindow(id);
+        }
+        d->setWinId(0);
+    }
 }
 
@@ -250,10 +763,10 @@
 void QWidgetPrivate::createTLSysExtra()
 {
-    // @todo implement
+    extra->topextra->fId = NULLHANDLE;
 }
 
 void QWidgetPrivate::deleteTLSysExtra()
 {
-    // @todo implement
+    // Note: extra->topextra->fId is cleaned up in QWidget::destroy()
 }
 
@@ -270,5 +783,35 @@
 void QWidgetPrivate::updateFrameStrut()
 {
-    // @todo implement
+    Q_Q(QWidget);
+
+    if (!q->testAttribute(Qt::WA_WState_Created))
+        return;
+
+    if (q->internalWinId() == NULLHANDLE) {
+        data.fstrut_dirty = false;
+        return;
+    }
+
+    QTLWExtra *top = maybeTopData();
+    if (!top || top->fId == NULLHANDLE) {
+        data.fstrut_dirty = false;
+        return;
+    }
+
+    // this widget has WC_FRAME
+    SWP swp;
+    WinQueryWindowPos(top->fId, &swp);
+    SWP cswp;
+    WinQueryWindowPos(data.winid, &cswp);
+    // flip y coordinates
+    swp.y = QApplication::desktop()->height() - (swp.y + swp.cy);
+    cswp.y = swp.cy - (cswp.y + cswp.cy);
+    QRect &fs = top->frameStrut;
+    fs.setCoords(cswp.x, cswp.y, swp.cx - cswp.x - cswp.cx,
+                                 swp.cy - cswp.y - cswp.cy);
+    // @todo need this??
+    //data.crect.setRect(swp.x + cswp.x, swp.y + cswp.y, cswp.cx, cswp.cy);
+
+    data.fstrut_dirty = false;
 }
 
