Index: /trunk/src/gui/kernel/qapplication_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 111)
+++ /trunk/src/gui/kernel/qapplication_pm.cpp	(revision 112)
@@ -127,5 +127,5 @@
 #endif
     bool        translatePaintEvent(const QMSG &qmsg);
-//  bool        translateConfigEvent(const QMSG &msg);
+    bool        translateConfigEvent(const QMSG &qmsg);
     bool        translateCloseEvent(const QMSG &qmsg);
 //  void        repolishStyle(QStyle &style);
@@ -556,4 +556,38 @@
         } else {
             switch(msg) {
+
+            case WM_PAINT: { // paint event
+                if (widget->translatePaintEvent(qmsg))
+                    return (MRESULT)TRUE;
+                break;
+            }
+
+            case WM_ERASEBACKGROUND: { // erase window background
+                // flush WM_PAINT messages here to update window contents
+                // instantly while tracking the resize frame (normally these
+                // messages are delivered after the user has stopped resizing
+                // for some time). this slows down resizing slightly but gives a
+                // better look (no invalid window contents can be seen during
+                // resize). the alternative could be to erase the background only,
+                // but we need to do it for every non-toplevel window, which can
+                // also be time-consuming (WM_ERASEBACKGROUND is sent to WC_FRAME
+                // clients only, so we would have to do all calculations ourselves).
+                WinUpdateWindow(widget->effectiveWinId());
+                return FALSE;
+            }
+
+            case WM_CALCVALIDRECTS: {
+                // we must always return this value here to cause PM to reposition
+                // our children accordingly (othwerwise we would have to do it
+                // ourselves to keep them top-left aligned).
+                return (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
+            }
+
+            case WM_MOVE:   // move window
+            case WM_SIZE: { // resize window
+                if (widget->translateConfigEvent(qmsg))
+                    return (MRESULT)TRUE;
+                break;
+            }
 
             case WM_SHOW: {
@@ -1400,4 +1434,90 @@
 
 //
+// Paint event translation
+//
+bool QETWidget::translatePaintEvent(const QMSG &qmsg)
+{
+    if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
+        Q_ASSERT(internalWinId());
+
+    HPS displayPS = qt_display_ps();
+
+    // Since we don't use WS_CLIPSIBLINGS and WS_CLIPCHILDREN bits (see
+    // qwidget_pm.cpp), we have to validate areas that intersect with our
+    // children and siblings, taking their clip regions into account.
+//    validateObstacles();
+
+    Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+
+    HRGN hrgn = GpiCreateRegion(displayPS, 0, NULL);
+    LONG rc = WinQueryUpdateRegion(internalWinId(), hrgn);
+    if (rc == RGN_ERROR) { // The update bounding rect is invalid
+        GpiDestroyRegion(displayPS, hrgn);
+        d_func()->hd = NULLHANDLE;
+        setAttribute(Qt::WA_PendingUpdate, false);
+        return false;
+    }
+
+    setAttribute(Qt::WA_PendingUpdate, false);
+
+    // @todo not sure we need it
+//  const QRegion dirtyInBackingStore(qt_dirtyRegion(this));
+//  // Make sure the invalidated region contains the region we're about to repaint.
+//  // BeginPaint will set the clip to the invalidated region and it is impossible
+//  // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient
+//  // as it may return an invalid context (especially on Windows Vista).
+//  if (!dirtyInBackingStore.isEmpty())
+//      InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false);
+
+    RECTL rcl;
+    d_func()->hd = WinBeginPaint(internalWinId(), 0, &rcl);
+
+    // it's possible that the update rectangle is empty
+    if (rcl.xRight <= rcl.xLeft || rcl.yTop <= rcl.yBottom) {
+        WinEndPaint(d_func()->hd);
+        GpiDestroyRegion(displayPS, hrgn);
+        d_func()->hd = NULLHANDLE;
+        setAttribute(Qt::WA_PendingUpdate, false);
+        return true;
+    }
+
+    if (WinQueryClipRegion( internalWinId(), 0) != QCRGN_NO_CLIP_REGION) {
+        // Correct the update region by intersecting it with the clip
+        // region (PM doesn't do that itself). It is necessary
+        // to have a correct QRegion in QPaintEvent.
+        HRGN hcrgn = GpiCreateRegion(displayPS, 0, NULL);
+        WinQueryClipRegion(internalWinId(), hcrgn);
+        GpiCombineRegion(displayPS, hrgn, hrgn, hcrgn, CRGN_AND);
+        GpiDestroyRegion(displayPS, hcrgn);
+    }
+
+    // flip y coordinate
+    rcl.yBottom = height() - (rcl.yBottom + 1);
+    rcl.yTop = height() - (rcl.yTop + 1);
+
+    const QRect updateRect(QPoint(rcl.xLeft, rcl.yBottom),
+                           QPoint(rcl.xRight, rcl.yTop));
+
+    // Mapping region from system to qt (32 bit) coordinate system.
+    // @todo use hrgn here once we implement QRegion<->HRGN relationship
+    d_func()->syncBackingStore(updateRect.translated(data->wrect.topLeft()));
+
+    WinEndPaint(d_func()->hd);
+    d_func()->hd = NULLHANDLE;
+
+    return true;
+}
+
+//
+// Window move and resize (configure) events
+//
+
+bool QETWidget::translateConfigEvent(const QMSG &qmsg)
+{
+    // @todo implement
+    return false;
+}
+
+//
 // Close window event translation.
 //
Index: /trunk/src/gui/kernel/qwidget.cpp
===================================================================
--- /trunk/src/gui/kernel/qwidget.cpp	(revision 111)
+++ /trunk/src/gui/kernel/qwidget.cpp	(revision 112)
@@ -184,5 +184,5 @@
         ,isScrolled(0)
         ,isMoved(0)
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_WS_PM)
         ,noPaintOnScreen(0)
 #endif
@@ -9675,7 +9675,7 @@
                "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute");
 
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_WS_PM)
     if (attribute == Qt::WA_PaintOnScreen && on) {
-        // see qwidget_win.cpp, ::paintEngine for details
+        // see qwidget_[win|pm].cpp, ::paintEngine for details
         paintEngine();
         if (d->noPaintOnScreen)
Index: /trunk/src/gui/kernel/qwidget_p.h
===================================================================
--- /trunk/src/gui/kernel/qwidget_p.h	(revision 111)
+++ /trunk/src/gui/kernel/qwidget_p.h	(revision 112)
@@ -551,6 +551,6 @@
     uint isMoved : 1;
 
-#ifdef Q_WS_WIN
-    uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+#if defined(Q_WS_WIN) || defined(Q_WS_PM)
+    uint noPaintOnScreen : 1; // see qwidget_[win|pm].cpp ::paintEngine()
 #endif
 
Index: /trunk/src/gui/kernel/qwidget_pm.cpp
===================================================================
--- /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 111)
+++ /trunk/src/gui/kernel/qwidget_pm.cpp	(revision 112)
@@ -1467,5 +1467,5 @@
     fs.setCoords(cswp.x, cswp.y, swp.cx - cswp.x - cswp.cx,
                                  swp.cy - cswp.y - cswp.cy);
-    // @todo need this??
+    // @todo do we really need to update crect here??
     //data.crect.setRect(swp.x + cswp.x, swp.y + cswp.y, cswp.cx, cswp.cy);
 
@@ -1480,5 +1480,23 @@
 QPaintEngine *QWidget::paintEngine() const
 {
-    // @todo implement
+    // @todo this is a place to return some direct on-screen PaintEngine once
+    // we decide to support it
+
+    // We set this bit which is checked in setAttribute for
+    // Qt::WA_PaintOnScreen. We do this to allow these two scenarios:
+    //
+    // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to
+    // OS/2 which would mean suddenly their widgets stop working.
+    //
+    // 2. Users set paint on screen and subclass paintEngine() to
+    // return 0, in which case we have a "hole" in the backingstore
+    // allowing use of GPI directly.
+    //
+    // 1 is WRONG, but to minimize silent failures, we have set this
+    // bit to ignore the setAttribute call. 2. needs to be
+    // supported because its our only means of embeddeding native
+    // graphics stuff.
+    const_cast<QWidgetPrivate *>(d_func())->noPaintOnScreen = 1;
+
     return 0;
 }
