Index: /trunk/include/Qt/private/qeventdispatcher_pm_p.h
===================================================================
--- /trunk/include/Qt/private/qeventdispatcher_pm_p.h	(revision 67)
+++ /trunk/include/Qt/private/qeventdispatcher_pm_p.h	(revision 67)
@@ -0,0 +1,1 @@
+#include "../../../src/corelib/kernel/qeventdispatcher_pm_p.h"
Index: /trunk/include/Qt/qwindowdefs_pm.h
===================================================================
--- /trunk/include/Qt/qwindowdefs_pm.h	(revision 67)
+++ /trunk/include/Qt/qwindowdefs_pm.h	(revision 67)
@@ -0,0 +1,1 @@
+#include "../../src/gui/kernel/qwindowdefs_pm.h"
Index: /trunk/include/QtCore/private/qeventdispatcher_pm_p.h
===================================================================
--- /trunk/include/QtCore/private/qeventdispatcher_pm_p.h	(revision 67)
+++ /trunk/include/QtCore/private/qeventdispatcher_pm_p.h	(revision 67)
@@ -0,0 +1,1 @@
+#include "../../../src/corelib/kernel/qeventdispatcher_pm_p.h"
Index: /trunk/include/QtGui/qwindowdefs_pm.h
===================================================================
--- /trunk/include/QtGui/qwindowdefs_pm.h	(revision 67)
+++ /trunk/include/QtGui/qwindowdefs_pm.h	(revision 67)
@@ -0,0 +1,1 @@
+#include "../../src/gui/kernel/qwindowdefs_pm.h"
Index: /trunk/src/corelib/kernel/qeventdispatcher_pm.cpp
===================================================================
--- /trunk/src/corelib/kernel/qeventdispatcher_pm.cpp	(revision 67)
+++ /trunk/src/corelib/kernel/qeventdispatcher_pm.cpp	(revision 67)
@@ -0,0 +1,1001 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Copyright (C) 2009 netlabs.org. OS/2 parts.
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_pm_p.h"
+
+#include "qcoreapplication.h"
+#include "qhash.h"
+#include "qlibrary.h"
+#include "qpair.h"
+#include "qset.h"
+#include "qsocketnotifier.h"
+#include "qvarlengtharray.h"
+
+#include "qabstracteventdispatcher_p.h"
+#include "qcoreapplication_p.h"
+
+#include <private/qthread_p.h>
+#include <private/qmutexpool_p.h>
+
+#include <Qt/qwindowdefs_pm.h> // for QPMObjectWindow declaration
+
+QT_BEGIN_NAMESPACE
+
+extern uint qGlobalPostedEventsCount();
+
+class QEventDispatcherPMPrivate;
+
+// @todo later: timers
+#if 0
+
+struct WinTimerInfo {                           // internal timer info
+    QObject *dispatcher;
+    int timerId;
+    int interval;
+    QObject *obj;                               // - object to receive events
+    bool inTimerEvent;
+    int fastTimerId;
+};
+
+class QZeroTimerEvent : public QTimerEvent
+{
+public:
+    inline QZeroTimerEvent(int timerId)
+        : QTimerEvent(timerId)
+    { t = QEvent::ZeroTimerEvent; }
+};
+
+typedef QList<WinTimerInfo*>  WinTimerVec;      // vector of TimerInfo structs
+typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
+
+#if !defined(DWORD_PTR) && !defined(Q_WS_WIN64)
+#define DWORD_PTR DWORD
+#endif
+
+typedef MMRESULT(WINAPI *ptimeSetEvent)(UINT, UINT, LPTIMECALLBACK, DWORD_PTR, UINT);
+typedef MMRESULT(WINAPI *ptimeKillEvent)(UINT);
+
+static ptimeSetEvent qtimeSetEvent = 0;
+static ptimeKillEvent qtimeKillEvent = 0;
+
+LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+
+static void resolveTimerAPI()
+{
+    static bool triedResolve = false;
+    if (!triedResolve) {
+#ifndef QT_NO_THREAD
+        QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+        if (triedResolve)
+            return;
+#endif
+        triedResolve = true;
+#if !defined(Q_OS_WINCE)
+        qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("winmm"), "timeSetEvent");
+        qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("winmm"), "timeKillEvent");
+#else
+        qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent");
+        qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent");
+#endif
+    }
+}
+
+#endif
+
+/*****************************************************************************
+  Auxiliary object window class for dedicated message processing.
+  Declared in qwindowdefs_pm.h
+ *****************************************************************************/
+
+/*!
+    \class QPMObjectWindow qwindowdefs.h
+
+    The QPMObjectWindow class is an auxiliary class for dedicated message
+    processing. Its functionality is based on PM object windows. Once an
+    instance of this class is created, PM window messages can be sent or posted
+    to it using send() or post() methods. Subclasses should override the
+    message() method to process sent or posted messages. The hwnd() method is
+    used whenever a PM window handle of this object window is necessary to be
+    passed as a HWND argument to other calls and/or messages.
+
+    Instances of this class may be created only on the main GUI thread or on a
+    thread that has created a PM message queue and runs the PM message loop
+    \b itself. If you create an instance on a thread other than main, make sure
+    you destroy it before destroying the thread's message queue.
+
+    \note WM_CREATE and WM_DESTROY messages are processed internally and not
+    delivered do the message() method. Instead, you can use the constructor and
+    the destructor of the subclass, respectively.
+
+    \note This class is OS/2 specific and not available in Qt for other
+    platforms!
+*/
+
+/// @todo remove?
+// returns HMQ of the current thread or NULL if no event queue has been created
+static HMQ qt_WinQueryQueue(HAB hab)
+{
+    PTIB ptib;
+    PPIB ppib;
+    DosGetInfoBlocks(&ptib, &ppib);
+    return WinQueueFromID(hab, ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
+}
+
+/*!
+    Constructs a new object window for the current thread.
+    If \a deferred is \c false, this method calls create() to create a PM object
+    window. Otherwise, you must call create() yourself before this object window
+    is able to process messages.
+*/
+QPMObjectWindow::QPMObjectWindow(bool deferred /* = false */) :
+    w(NULLHANDLE)
+{
+    if (!deferred)
+        create();
+}
+
+/*!
+    Destroys this object window.
+    This method calls destroy() to free the PM object window.
+*/
+QPMObjectWindow::~QPMObjectWindow()
+{
+    destroy();
+}
+
+/*!
+    Creates a PM object window.
+    Returns \c true on success or \c false otherwise.
+    The method does nothing but returns \c false if the window has been already
+    created. The handle of the successfully created object window can be obtained
+    using the hwnd() method.
+
+    \note Must be called on the same thread that cosnstructed this instance.
+*/
+bool QPMObjectWindow::create()
+{
+    if (w != NULLHANDLE)
+        return false;
+
+    static const char *ClassName = "QPMObjectWindow";
+    static bool classRegistered = FALSE;
+
+    if (!classRegistered) {
+        WinRegisterClass(0, ClassName, windowProc, 0, QWL_USER + sizeof(PVOID));
+        classRegistered = true;
+    }
+
+    w = WinCreateWindow(HWND_OBJECT, ClassName,
+                        NULL, 0, 0, 0, 0, 0, NULL,
+                        HWND_BOTTOM, 0, this, NULL);
+    if (w == NULLHANDLE)
+        qWarning("QPMObjectWindow::create: WinCreateWindow failed with 0x%08lX",
+                 WinGetLastError(0));
+
+    return w != NULLHANDLE;
+}
+
+/*!
+    Destroys the PM object window.
+    Returns \c TRUE on success or \c FALSE otherwise.
+    The method does nothing but returns \c FALSE  if the window has been
+    already destroyed (or never created).
+
+    \note Must be called on the same thread that cosnstructed this instance.
+*/
+bool QPMObjectWindow::destroy()
+{
+    if (w == NULLHANDLE)
+        return false;
+
+    HWND h = w;
+    w = NULLHANDLE; // tell windowProc() we're unsafe
+    WinDestroyWindow(h);
+
+    return true;
+}
+
+//static
+MRESULT EXPENTRY QPMObjectWindow::windowProc(HWND hwnd, ULONG msg,
+                                             MPARAM mp1, MPARAM mp2)
+{
+    if (msg == WM_CREATE) {
+        QPMObjectWindow *that = static_cast<QPMObjectWindow *>(mp1);
+        if (!that)
+            return (MRESULT) TRUE;
+        WinSetWindowPtr(hwnd, QWL_USER, that);
+        return (MRESULT) FALSE;
+    }
+
+    QPMObjectWindow *that =
+        static_cast<QPMObjectWindow *>(WinQueryWindowPtr(hwnd, QWL_USER));
+    Q_ASSERT(that);
+
+    // Note: before WinCreateWindow() returns to the constructor or after the
+    // destructor has been called, w is 0. We use this to determine that the
+    // object is in the unsafe state (VTBL is not yet initialized or has been
+    // already uninitialized), so message() points to never-never land.
+    if (!that || !that->w)
+        return (MRESULT) FALSE;
+
+    return that->message(msg, mp1, mp2);
+}
+
+/*!
+  \fn QPMObjectWindow::send(ULONG msg, MPARAM mp1, MPARAM mp2) const
+
+  Synchronously sends a message \a msg with the given parameters \a mp1 and
+  \a mp2 to this window handle and returns a reply from the message() function.
+
+  \note Must be called on the same thread that cosnstructed this instance.
+*/
+
+/*!
+  \fn QPMObjectWindow::post(ULONG msg, MPARAM mp1, MPARAM mp2) const
+
+  Asynchronously posts a message \a msg with the given parameters \a mp1 and
+  \a mp2 to this window handle. Returns \c TRUE on success and \c FALSE
+  otherwise.
+
+  \note Can be called on any thread.
+*/
+
+// socket select notification (highest priority)
+#define WM_U_SEM_SELECT     WM_SEM1
+// zero timer notification (lowest priority)
+#define WM_U_SEM_ZEROTIMER  WM_SEM4
+
+class QEventDispatcherPMPrivate : public QAbstractEventDispatcherPrivate
+{
+    Q_DECLARE_PUBLIC(QEventDispatcherPM)
+public:
+    QEventDispatcherPMPrivate();
+    ~QEventDispatcherPMPrivate();
+
+    void createMsgQueue();
+    void createAuxWnd();
+
+    // Auxiliary object window to process WM_U_SEM_SELECT and WM_TIMER messages.
+    // We need a dedicated window along with processing these messages directly in
+    // QEventLoop::processEvents() to make sure they are processed even if the
+    // current message loop is not run by Qt. This happens when a native modal
+    // dialog is shown or when a top-level Qt widget is being moved or resized
+    // using the mouse, or when a Qt-based DLL plugin is used by a non-Qt
+    // application.
+    class AuxWnd : public QPMObjectWindow
+    {
+    public:
+        AuxWnd() : QPMObjectWindow(true /* deferred */), dispatcher(0) {}
+        void setDispatcher(QEventDispatcherPMPrivate *d) { dispatcher = d; }
+        MRESULT message(ULONG msg, MPARAM mp1, MPARAM mp2);
+        QEventDispatcherPMPrivate *dispatcher;
+    } auxWnd;
+
+    HAB hab;
+    HMQ hmq;
+
+    bool interrupt;
+
+// @todo later
+//  DWORD threadId;
+//
+//  bool interrupt;
+//
+//  // internal window handle used for socketnotifiers/timers/etc
+//  HWND internalHwnd;
+//
+//  // timers
+//  WinTimerVec timerVec;
+//  WinTimerDict timerDict;
+//  void registerTimer(WinTimerInfo *t);
+//  void unregisterTimer(WinTimerInfo *t);
+//  void sendTimerEvent(int timerId);
+//
+//  // socket notifiers
+//  QSNDict sn_read;
+//  QSNDict sn_write;
+//  QSNDict sn_except;
+//  void doWsaAsyncSelect(int socket);
+//
+//  QList<QMSG> queuedUserInputEvents;
+//  QList<QMSG> queuedSocketEvents;
+};
+
+QEventDispatcherPMPrivate::QEventDispatcherPMPrivate()
+    : hab(NULLHANDLE), hmq(NULLHANDLE), interrupt(false)
+{
+}
+
+QEventDispatcherPMPrivate::~QEventDispatcherPMPrivate()
+{
+    auxWnd.setDispatcher(0);
+    auxWnd.destroy();
+    if (hmq != NULLHANDLE) {
+        WinDestroyMsgQueue(hmq);
+        WinTerminate(hab);
+    }
+}
+
+void QEventDispatcherPMPrivate::createMsgQueue()
+{
+    if (hmq == NULLHANDLE) {
+        // first, dynamically switch ("morph") to PM mode if we have been
+        // compiled as the console application. This is necessary to create the
+        // event queue, windows and other PM resources. As a side effect, the
+        // console remains attached after morphing which can be useful for
+        // debugging
+        PPIB ppib;
+        DosGetInfoBlocks(NULL, &ppib);
+        if (ppib->pib_ultype != 3)
+            ppib->pib_ultype = 3;
+        // then create the message queue
+        hab = WinInitialize(0);
+        hmq = WinCreateMsgQueue(hab, 0);
+        if (hmq == NULLHANDLE)
+            qWarning("QEventDispatcherPMPrivate::createMsgQueue: "
+                     "WinCreateMsgQueue failed with 0x%08lX",
+                     WinGetLastError(hab));
+    }
+}
+
+void QEventDispatcherPMPrivate::createAuxWnd()
+{
+    if (auxWnd.hwnd() == NULLHANDLE) {
+        createMsgQueue();
+        auxWnd.setDispatcher(this);
+        auxWnd.create();
+    }
+}
+
+MRESULT QEventDispatcherPMPrivate::AuxWnd::message(ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+    QMSG qmsg = { hwnd(), msg, mp1, mp2 };
+
+    QCoreApplication *app = QCoreApplication::instance();
+    MRESULT result;
+    if (app && app->filterEvent(&qmsg, reinterpret_cast<long *>(&result)))
+        return result;
+
+    switch (msg) {
+        case WM_U_SEM_SELECT: {
+// @todo later
+//          if (eventLoop)
+//              eventLoop->activateSocketNotifiers();
+            break;
+        }
+        case WM_U_SEM_ZEROTIMER: {
+// @todo later
+//          if (numZeroTimers) {
+//              activateZeroTimers();
+//              // repost the message if there are still zero timers left
+//              if (numZeroTimers)
+//                  WinPostMsg(hwnd(), WM_U_SEM_ZEROTIMER, 0, 0);
+//          }
+            break;
+        }
+        case WM_TIMER: {
+// @todo later
+//          USHORT id = SHORT1FROMMP(mp1);
+//          dispatchTimer((uint) id, &qmsg);
+            break;
+        }
+    }
+
+    return FALSE;
+}
+
+// @todo remove
+#if 0
+
+LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
+{
+    if (message == WM_NCCREATE) {
+            return true;
+    } else if (message == WM_USER) {
+
+        // socket notifier message
+        MSG msg;
+        msg.hwnd = hwnd;
+        msg.message = message;
+        msg.wParam = wp;
+        msg.lParam = lp;
+
+        QCoreApplication *app = QCoreApplication::instance();
+        long result;
+        if (app && app->filterEvent(&msg, &result))
+            return result;
+
+        int type = -1;
+        switch (WSAGETSELECTEVENT(lp)) {
+        case FD_READ:
+        case FD_CLOSE:
+        case FD_ACCEPT:
+            type = 0;
+            break;
+        case FD_WRITE:
+        case FD_CONNECT:
+            type = 1;
+            break;
+        case FD_OOB:
+            type = 2;
+            break;
+        }
+        if (type >= 0) {
+
+    #ifdef GWLP_USERDATA
+            QEventDispatcherPM *eventDispatcher =
+                (QEventDispatcherPM *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+    #else
+            QEventDispatcherPM *eventDispatcher =
+                (QEventDispatcherPM *) GetWindowLongA(hwnd, GWL_USERDATA);
+    #endif
+            if (eventDispatcher) {
+                QEventDispatcherPMPrivate *d = eventDispatcher->d_func();
+                QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+                QSNDict *dict = sn_vec[type];
+
+                QSockNot *sn = dict ? dict->value(wp) : 0;
+                if (sn) {
+                    QEvent event(QEvent::SockAct);
+                    QCoreApplication::sendEvent(sn->obj, &event);
+                }
+            }
+        }
+        return 0;
+
+    } else if (message == WM_TIMER) {
+
+        MSG msg;
+        msg.hwnd = hwnd;
+        msg.message = message;
+        msg.wParam = wp;
+        msg.lParam = lp;
+
+        QCoreApplication *app = QCoreApplication::instance();
+        Q_ASSERT_X(app, "qt_interal_proc", "Timer fired, but no QCoreApplication");
+        if (!app) {
+            KillTimer(hwnd, wp);
+            return 0;
+        }
+
+        long result;
+        if (app->filterEvent(&msg, &result))
+            return result;
+
+        QEventDispatcherPM *eventDispatcher =
+            qobject_cast<QEventDispatcherPM *>(QAbstractEventDispatcher::instance());
+        Q_ASSERT(eventDispatcher != 0);
+        QEventDispatcherPMPrivate *d = eventDispatcher->d_func();
+        d->sendTimerEvent(wp);
+        return 0;
+    }
+
+    return  DefWindowProc(hwnd, message, wp, lp);
+}
+
+void QEventDispatcherPMPrivate::registerTimer(WinTimerInfo *t)
+{
+    Q_ASSERT(internalHwnd);
+
+    Q_Q(QEventDispatcherPM);
+
+    int ok = 0;
+
+    if (t->interval > 10 || !t->interval || !qtimeSetEvent) {
+        ok = 1;
+        if (!t->interval)  // optimization for single-shot-zero-timer
+            QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
+        else
+            ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+    } else {
+        ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
+                                            TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
+        if (ok == 0) { // fall back to normal timer if no more multimedia timers avaiable
+            ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+        }
+    }
+
+    if (ok == 0)
+        qErrnoWarning("QEventDispatcherPM::registerTimer: Failed to create a timer");
+}
+
+void QEventDispatcherPMPrivate::unregisterTimer(WinTimerInfo *t)
+{
+    // mark timer as unused
+    if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+        QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId);
+
+    if (t->interval == 0) {
+        QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+    } else if (t->fastTimerId != 0) {
+        qtimeKillEvent(t->fastTimerId);
+        QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+    } else if (internalHwnd) {
+        KillTimer(internalHwnd, t->timerId);
+    }
+    delete t;
+}
+
+void QEventDispatcherPMPrivate::sendTimerEvent(int timerId)
+{
+    WinTimerInfo *t = timerDict.value(timerId);
+    if (t && !t->inTimerEvent) {
+        // send event, but don't allow it to recurse
+        t->inTimerEvent = true;
+
+        QTimerEvent e(t->timerId);
+        QCoreApplication::sendEvent(t->obj, &e);
+
+        // timer could have been removed
+        t = timerDict.value(timerId);
+        if (t) {
+            t->inTimerEvent = false;
+        }
+    }
+}
+
+void QEventDispatcherPMPrivate::doWsaAsyncSelect(int socket)
+{
+    Q_ASSERT(internalHwnd);
+    int sn_event = 0;
+    if (sn_read.contains(socket))
+        sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
+    if (sn_write.contains(socket))
+        sn_event |= FD_WRITE | FD_CONNECT;
+    if (sn_except.contains(socket))
+        sn_event |= FD_OOB;
+    // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
+    // This is a BoundsChecker bug and not a Qt bug
+    WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_USER : 0, sn_event);
+}
+
+void QEventDispatcherPM::createInternalHwnd()
+{
+    Q_D(QEventDispatcherPM);
+
+    Q_ASSERT(!d->internalHwnd);
+    if (d->internalHwnd)
+        return;
+    d->internalHwnd = qt_create_internal_window(this);
+
+    // register all socket notifiers
+    QList<int> sockets = (d->sn_read.keys().toSet()
+                          + d->sn_write.keys().toSet()
+                          + d->sn_except.keys().toSet()).toList();
+    for (int i = 0; i < sockets.count(); ++i)
+        d->doWsaAsyncSelect(sockets.at(i));
+
+    // start all normal timers
+    for (int i = 0; i < d->timerVec.count(); ++i)
+        d->registerTimer(d->timerVec.at(i));
+}
+
+#endif
+
+QEventDispatcherPM::QEventDispatcherPM(QObject *parent)
+    : QAbstractEventDispatcher(*new QEventDispatcherPMPrivate, parent)
+{
+}
+
+QEventDispatcherPM::~QEventDispatcherPM()
+{
+}
+
+bool QEventDispatcherPM::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+    Q_D(QEventDispatcherPM);
+
+// @todo later
+#if 0
+    if (!d->internalHwnd)
+        createInternalHwnd();
+
+    d->interrupt = false;
+    emit awake();
+
+    bool canWait;
+    bool retVal = false;
+    do {
+        QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+
+        DWORD waitRet = 0;
+        HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
+        QVarLengthArray<MSG> processedTimers;
+        while (!d->interrupt) {
+            MSG msg;
+            bool haveMessage;
+
+            if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
+                // process queued user input events
+                haveMessage = true;
+                msg = d->queuedUserInputEvents.takeFirst();
+            } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
+                // process queued socket events
+                haveMessage = true;
+                msg = d->queuedSocketEvents.takeFirst();
+            } else {
+                haveMessage = winPeekMessage(&msg, 0, 0, 0, PM_REMOVE);
+                if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
+                    && ((msg.message >= WM_KEYFIRST
+                         && msg.message <= WM_KEYLAST)
+                        || (msg.message >= WM_MOUSEFIRST
+                            && msg.message <= WM_MOUSELAST)
+                        || msg.message == WM_MOUSEWHEEL)) {
+                    // queue user input events for later processing
+                    haveMessage = false;
+                    d->queuedUserInputEvents.append(msg);
+                }
+                if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
+                    && (msg.message == WM_USER && msg.hwnd == d->internalHwnd)) {
+                    // queue socket events for later processing
+                    haveMessage = false;
+                    d->queuedSocketEvents.append(msg);
+                }
+            }
+            if (haveMessage) {
+                if (msg.message == WM_TIMER) {
+                    // avoid live-lock by keeping track of the timers we've already sent
+                    bool found = false;
+                    for (int i = 0; !found && i < processedTimers.count(); ++i) {
+                        const MSG processed = processedTimers.constData()[i];
+                        found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
+                    }
+                    if (found)
+                        continue;
+                    processedTimers.append(msg);
+                } else if (msg.message == WM_QUIT) {
+                    if (QCoreApplication::instance())
+                        QCoreApplication::instance()->quit();
+                    return false;
+                }
+
+                if (!filterEvent(&msg)) {
+                    TranslateMessage(&msg);
+                    QT_WA({
+                        DispatchMessage(&msg);
+                    } , {
+                        DispatchMessageA(&msg);
+                    });
+                }
+            } else {
+                // nothing todo so break
+                break;
+            }
+            retVal = true;
+        }
+
+        // still nothing - wait for message or signalled objects
+        QThreadData *data = d->threadData;
+        canWait = (!retVal
+                   && data->canWait
+                   && !d->interrupt
+                   && (flags & QEventLoop::WaitForMoreEvents));
+        if (canWait) {
+            emit aboutToBlock();
+            waitRet = WinGetMsg(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+            emit awake();
+        }
+    } while (canWait);
+
+    return retVal;
+#else
+    return false;
+#endif
+}
+
+bool QEventDispatcherPM::hasPendingEvents()
+{
+    QMSG msg;
+    return qGlobalPostedEventsCount() || WinPeekMsg(0, &msg, NULL, 0, 0, PM_NOREMOVE);
+}
+
+void QEventDispatcherPM::registerSocketNotifier(QSocketNotifier *notifier)
+{
+// @todo later
+#if 0
+    Q_ASSERT(notifier);
+    int sockfd = notifier->socket();
+    int type = notifier->type();
+#ifndef QT_NO_DEBUG
+    if (sockfd < 0) {
+        qWarning("QSocketNotifier: Internal error");
+        return;
+    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+        qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+        return;
+    }
+#endif
+
+    Q_D(QEventDispatcherPM);
+    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+    QSNDict *dict = sn_vec[type];
+
+    if (QCoreApplication::closingDown()) // ### d->exitloop?
+        return; // after sn_cleanup, don't reinitialize.
+
+    if (dict->contains(sockfd)) {
+        const char *t[] = { "Read", "Write", "Exception" };
+    /* Variable "socket" below is a function pointer. */
+        qWarning("QSocketNotifier: Multiple socket notifiers for "
+                 "same socket %d and type %s", sockfd, t[type]);
+    }
+
+    QSockNot *sn = new QSockNot;
+    sn->obj = notifier;
+    sn->fd  = sockfd;
+    dict->insert(sn->fd, sn);
+
+    if (d->internalHwnd)
+        d->doWsaAsyncSelect(sockfd);
+#endif
+}
+
+void QEventDispatcherPM::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+// @todo later
+#if 0
+    Q_ASSERT(notifier);
+    int sockfd = notifier->socket();
+    int type = notifier->type();
+#ifndef QT_NO_DEBUG
+    if (sockfd < 0) {
+        qWarning("QSocketNotifier: Internal error");
+        return;
+    } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+        qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+        return;
+    }
+#endif
+
+    Q_D(QEventDispatcherPM);
+    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+    QSNDict *dict = sn_vec[type];
+    QSockNot *sn = dict->value(sockfd);
+    if (!sn)
+        return;
+
+    dict->remove(sockfd);
+    delete sn;
+
+    if (d->internalHwnd)
+        d->doWsaAsyncSelect(sockfd);
+#endif
+}
+
+void QEventDispatcherPM::registerTimer(int timerId, int interval, QObject *object)
+{
+// @todo later
+#if 0
+    if (timerId < 1 || interval < 0 || !object) {
+        qWarning("QEventDispatcherPM::registerTimer: invalid arguments");
+        return;
+    } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+        qWarning("QObject::startTimer: timers cannot be started from another thread");
+        return;
+    }
+
+    Q_D(QEventDispatcherPM);
+
+    register WinTimerInfo *t = new WinTimerInfo;
+    t->dispatcher = this;
+    t->timerId  = timerId;
+    t->interval = interval;
+    t->obj  = object;
+    t->inTimerEvent = false;
+    t->fastTimerId = 0;
+
+    if (d->internalHwnd)
+        d->registerTimer(t);
+
+    d->timerVec.append(t);                      // store in timer vector
+    d->timerDict.insert(t->timerId, t);          // store timers in dict
+#endif
+}
+
+bool QEventDispatcherPM::unregisterTimer(int timerId)
+{
+// @todo later
+#if 0
+    if (timerId < 1) {
+        qWarning("QEventDispatcherPM::unregisterTimer: invalid argument");
+        return false;
+    }
+    QThread *currentThread = QThread::currentThread();
+    if (thread() != currentThread) {
+        qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+        return false;
+    }
+
+    Q_D(QEventDispatcherPM);
+    if (d->timerVec.isEmpty() || timerId <= 0)
+        return false;
+
+    WinTimerInfo *t = d->timerDict.value(timerId);
+    if (!t)
+        return false;
+
+    d->timerDict.remove(t->timerId);
+    d->timerVec.removeAll(t);
+    d->unregisterTimer(t);
+    return true;
+#else
+    return false;
+#endif
+}
+
+bool QEventDispatcherPM::unregisterTimers(QObject *object)
+{
+// @todo later
+#if 0
+    if (!object) {
+        qWarning("QEventDispatcherPM::unregisterTimers: invalid argument");
+        return false;
+    }
+    QThread *currentThread = QThread::currentThread();
+    if (object->thread() != thread() || thread() != currentThread) {
+        qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+        return false;
+    }
+
+    Q_D(QEventDispatcherPM);
+    if (d->timerVec.isEmpty())
+        return false;
+    register WinTimerInfo *t;
+    for (int i=0; i<d->timerVec.size(); i++) {
+        t = d->timerVec.at(i);
+        if (t && t->obj == object) {                // object found
+            d->timerDict.remove(t->timerId);
+            d->timerVec.removeAt(i);
+            d->unregisterTimer(t);
+            --i;
+        }
+    }
+    return true;
+#else
+    return false;
+#endif
+}
+
+QList<QEventDispatcherPM::TimerInfo>
+QEventDispatcherPM::registeredTimers(QObject *object) const
+{
+// @todo later
+#if 0
+    if (!object) {
+        qWarning("QEventDispatcherPM:registeredTimers: invalid argument");
+        return QList<TimerInfo>();
+    }
+
+    Q_D(const QEventDispatcherPM);
+    QList<TimerInfo> list;
+    for (int i = 0; i < d->timerVec.size(); ++i) {
+        const WinTimerInfo *t = d->timerVec.at(i);
+        if (t && t->obj == object)
+            list << TimerInfo(t->timerId, t->interval);
+    }
+    return list;
+#else
+    return QList<TimerInfo>();
+#endif
+}
+
+void QEventDispatcherPM::wakeUp()
+{
+    Q_D(QEventDispatcherPM);
+    PTIB ptib;
+    DosGetInfoBlocks(&ptib, NULL);
+    MQINFO mqinfo;
+    WinQueryQueueInfo(d->hmq, &mqinfo, sizeof(MQINFO));
+    if (ptib->tib_ptib2->tib2_ultid != mqinfo.tid)
+        WinPostQueueMsg(d->hmq, WM_NULL, 0, 0);
+}
+
+void QEventDispatcherPM::interrupt()
+{
+    Q_D(QEventDispatcherPM);
+    d->interrupt = true;
+    wakeUp();
+}
+
+void QEventDispatcherPM::flush()
+{
+}
+
+void QEventDispatcherPM::startingUp()
+{
+}
+
+void QEventDispatcherPM::closingDown()
+{
+    Q_D(QEventDispatcherPM);
+
+// @todo remove later
+#if 0
+    // clean up any socketnotifiers
+    while (!d->sn_read.isEmpty())
+        unregisterSocketNotifier((*(d->sn_read.begin()))->obj);
+    while (!d->sn_write.isEmpty())
+        unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
+    while (!d->sn_except.isEmpty())
+        unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
+
+    // clean up any timers
+    while (!d->timerDict.isEmpty())
+        unregisterTimer((*(d->timerDict.begin()))->timerId);
+#endif
+}
+
+// @todo remove later
+#if 0
+bool QEventDispatcherPM::event(QEvent *e)
+{
+    Q_D(QEventDispatcherPM);
+    if (e->type() == QEvent::ZeroTimerEvent) {
+        QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
+        WinTimerInfo *t = d->timerDict.value(zte->timerId());
+        if (t) {
+            t->inTimerEvent = true;
+
+            QTimerEvent te(zte->timerId());
+            QCoreApplication::sendEvent(t->obj, &te);
+
+            t = d->timerDict.value(zte->timerId());
+            if (t) {
+                if (t->interval == 0 && t->inTimerEvent) {
+                    // post the next zero timer event as long as the timer was not restarted
+                    QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+                }
+
+                t->inTimerEvent = false;
+            }
+        }
+        return true;
+    } else if (e->type() == QEvent::Timer) {
+        QTimerEvent *te = static_cast<QTimerEvent*>(e);
+        d->sendTimerEvent(te->timerId());
+    }
+    return QAbstractEventDispatcher::event(e);
+}
+#endif
+
+QT_END_NAMESPACE
Index: /trunk/src/corelib/kernel/qeventdispatcher_pm_p.h
===================================================================
--- /trunk/src/corelib/kernel/qeventdispatcher_pm_p.h	(revision 67)
+++ /trunk/src/corelib/kernel/qeventdispatcher_pm_p.h	(revision 67)
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Copyright (C) 2009 netlabs.org. OS/2 parts.
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_PM_P_H
+#define QEVENTDISPATCHER_PM_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qabstracteventdispatcher.h"
+#include "QtCore/qt_os2.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherPMPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherPM : public QAbstractEventDispatcher
+{
+    Q_OBJECT
+    Q_DECLARE_PRIVATE(QEventDispatcherPM)
+
+    friend class QGuiEventDispatcherPM;
+
+public:
+    explicit QEventDispatcherPM(QObject *parent = 0);
+    ~QEventDispatcherPM();
+
+    bool processEvents(QEventLoop::ProcessEventsFlags flags);
+    bool hasPendingEvents();
+
+    void registerSocketNotifier(QSocketNotifier *notifier);
+    void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+    void registerTimer(int timerId, int interval, QObject *object);
+    bool unregisterTimer(int timerId);
+    bool unregisterTimers(QObject *object);
+    QList<TimerInfo> registeredTimers(QObject *object) const;
+
+    void wakeUp();
+    void interrupt();
+    void flush();
+
+    void startingUp();
+    void closingDown();
+
+// @todo remove later
+//  bool event(QEvent *e);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_WIN_P_H
Index: /trunk/src/gui/kernel/qwindowdefs_pm.h
===================================================================
--- /trunk/src/gui/kernel/qwindowdefs_pm.h	(revision 67)
+++ /trunk/src/gui/kernel/qwindowdefs_pm.h	(revision 67)
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Copyright (C) 2009 netlabs.org. OS/2 parts.
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWDEFS_PM_H
+#define QWINDOWDEFS_PM_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+QT_END_NAMESPACE
+
+typedef HWND WId;
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QPMObjectWindow
+{
+public:
+    QPMObjectWindow(bool deferred = false);
+    virtual ~QPMObjectWindow();
+
+    bool create();
+    bool destroy();
+    HWND hwnd() const { return w; }
+
+    MRESULT send(ULONG msg, MPARAM mp1, MPARAM mp2) const {
+        return WinSendMsg(w, msg, mp1, mp2);
+    }
+
+    bool post(ULONG msg, MPARAM mp1, MPARAM mp2) const {
+        return WinPostMsg(w, msg, mp1, mp2);
+    }
+
+    virtual MRESULT message(ULONG msg, MPARAM mp1, MPARAM mp2) = 0;
+
+private:
+    static MRESULT EXPENTRY windowProc(HWND, ULONG, MPARAM, MPARAM);
+
+    HWND w;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWINDOWDEFS_WIN_H
