Index: trunk/src/kernel/qeventloop.cpp
===================================================================
--- trunk/src/kernel/qeventloop.cpp	(revision 112)
+++ trunk/src/kernel/qeventloop.cpp	(revision 113)
@@ -386,6 +386,6 @@
 */
 
-#if !defined(Q_WS_X11)
+#if !defined(Q_WS_X11) && !defined(Q_WS_PM)
 void QEventLoop::appStartingUp(){}
 void QEventLoop::appClosingDown(){}
-#endif // Q_WS_X11
+#endif // !Q_WS_X11 && !Q_WS_PM
Index: trunk/src/kernel/qeventloop_pm.cpp
===================================================================
--- trunk/src/kernel/qeventloop_pm.cpp	(revision 112)
+++ trunk/src/kernel/qeventloop_pm.cpp	(revision 113)
@@ -39,4 +39,5 @@
 #include "qeventloop.h"
 #include "qapplication.h"
+#include "qptrlist.h"
 
 #include <sys/socket.h>
@@ -48,4 +49,7 @@
 #endif // QT_THREAD_SUPPORT
 
+// entry point: PMWIN.305
+extern "C" HMQ APIENTRY WinQueueFromID( HAB hab, PID pid, PID tid );
+
 extern uint qGlobalPostedEventsCount();
 extern bool qt_pmEventFilter( QMSG* msg, MRESULT &result );
@@ -57,14 +61,4 @@
 static HAB qt_gui_hab = 0;
 static HMQ qt_gui_queue = 0;
-
-/// @todo (dmik) later
-//  Simpler timers are needed when Qt does not have the event loop,
-//  such as for plugins.
-//#ifndef Q_OS_TEMP
-//Q_EXPORT bool	qt_win_use_simple_timers = TRUE;
-//#else
-//Q_EXPORT bool	qt_win_use_simple_timers = FALSE;
-//#endif
-//void CALLBACK   qt_simple_timer_func( HWND, UINT, UINT, DWORD );
 
 static void	initTimers();
@@ -92,12 +86,239 @@
 #if defined(QT_CHECK_STATE)
         if( !qt_suppress_morph_warning )
-            qWarning(
-                "Qt: the program has not been linked as the Presentation Manager application\n"
-                "    but it uses GUI capabilities. Switching to PM mode dynamically."
-            );
+            qWarning( "Qt: the program has not been linked as the Presentation "
+                      "Manager application\n"
+                      "but it uses GUI capabilities. Switching to PM mode "
+                      "dynamically." );
 #endif
         ppib->pib_ultype = 3;
     }
 }
+
+enum
+{
+    // socket select notification (highest priority)
+    WM_U_SEM_SELECT = WM_SEM1,
+    // zero timer notification (lowest priority)
+    WM_U_SEM_ZEROTIMER = WM_SEM4,
+};
+
+/*****************************************************************************
+  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 must be created on the main GUI thread only 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 subclasses, respectively.
+  
+  \note This class is non-portable!
+*/
+
+// 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 );
+}
+
+static QPtrList<HWND> qt_objWindows;
+
+/*!
+  Constructs a new object window for the current thread.
+  If \a deferred is 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 );
+#ifndef QT_NO_DEBUG
+    if ( w == NULLHANDLE )
+        qSystemWarning( "QPMObjectWindow: Failed to create object window" );
+#endif    
+
+    if ( w != NULLHANDLE && qt_gui_queue &&
+         qt_WinQueryQueue( 0 ) == qt_gui_queue ) {
+            // store the handle in the list for clean destruction
+            qt_objWindows.append( &w );
+    }
+    
+    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;
+    
+    if ( qt_gui_queue && qt_WinQueryQueue( 0 ) == qt_gui_queue ) {
+        // remove the handle from the 'clean destruction' list
+        qt_objWindows.removeRef( &w );
+    }
+
+    HWND h = w;
+    w = 0; // 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.
+*/
+
+// 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 QPMAuxEventQueueWin : public QPMObjectWindow
+{
+public:
+    QPMAuxEventQueueWin() : QPMObjectWindow( TRUE ), eventLoop( NULL ) {}
+    void setEventLoop( QEventLoop *el ) { eventLoop = el; }
+    MRESULT message( ULONG msg, MPARAM mp1, MPARAM mp2 );
+private:
+    QEventLoop *eventLoop;
+};
+
+MRESULT QPMAuxEventQueueWin::message( ULONG msg, MPARAM mp1, MPARAM mp2 )
+{
+    switch ( msg ) {
+        case WM_U_SEM_SELECT: {
+            if ( eventLoop )
+                eventLoop->activateSocketNotifiers();
+            break;
+        }
+        case WM_U_SEM_ZEROTIMER: {
+            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: {
+            USHORT id = SHORT1FROMMP( mp1 );
+            QMSG qmsg = { hwnd(), msg, mp1, mp2 };
+            dispatchTimer( (uint) id, &qmsg );
+            break;
+        }
+    }
+    
+    return FALSE;
+}
+
+static QPMAuxEventQueueWin qt_aux_win;
+
 
 /*****************************************************************************
@@ -212,11 +433,4 @@
 
 
-//@@TODO (dmik): later (needed for plugin support)
-//void CALLBACK qt_simple_timer_func( HWND, UINT, UINT idEvent, DWORD )
-//{
-//    dispatchTimer( idEvent, 0 );
-//}
-
-
 // Activate a timer, used by both event-loop based and simple timers.
 
@@ -273,7 +487,4 @@
 static void initTimers()			// initialize timers
 {
-//@@TODO (dmik): qt_ensure_pm() should not be called when simple timers are
-//  implemented to be used by plugins.
-    qt_ensure_pm();
     timerVec = new TimerVec( 128 );
     Q_CHECK_PTR( timerVec );
@@ -282,4 +493,12 @@
     Q_CHECK_PTR( timerDict );
 }
+
+/// @todo (dmik) cleanupTimers() is only called by QEventLoop::cleanup() so it
+//  won't be called if there is no QEventLoop instance created (for example,
+//  when a Qt-based plugin DLL is used by a non-Qt application). Use atexit()?
+//  Btw, the same relates to the QThread::cleanup() vs QApplication pair.
+//  And to qt_aux_win (the DLL may be unloaded after the application has
+//  destroyed the main event queue, so the static destructor will not be able
+//  to properly destroy the window).
 
 static void cleanupTimers()			// remove pending timers
@@ -291,5 +510,5 @@
 	t = timerVec->at( i );
 	if ( t && !t->zero )
-	    WinStopTimer( 0, 0, t->id );
+	    WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
     }
     delete timerDict;
@@ -297,13 +516,4 @@
     delete timerVec;
     timerVec  = 0;
-
-//@@TODO (dmik): later (needed for plugin support)
-//    if ( qt_win_use_simple_timers ) {
-//	// Dangerous to leave WM_TIMER events in the queue if they have our
-//	// timerproc (eg. Qt-based DLL plugins may be unloaded)
-//	MSG msg;
-//	while (winPeekMessage( &msg, (HWND)-1, WM_TIMER, WM_TIMER, PM_REMOVE ))
-//	    continue;
-//    }
 }
 
@@ -316,10 +526,27 @@
 int qStartTimer( int interval, QObject *obj )
 {
+    Q_ASSERT( obj );
+    if ( !obj )
+        return 0;
+    
+    // lazily create the auxiliary window to process WM_TIMER messages
+    if ( !qt_aux_win.hwnd() )
+        if ( !qt_aux_win.create() )
+            return 0;
+    
     register TimerInfo *t;
     if ( !timerVec )				// initialize timer data
 	initTimers();
+
     int ind = timerVec->findRef( 0 );		// get free timer
-    if ( ind == -1 || !obj ) {
+    if ( ind == -1 ) {
 	ind = timerVec->size();			// increase the size
+        if ( ind >= TID_USERMAX ) {
+#if defined(QT_CHECK_STATE)
+            qWarning( "qStartTimer: Maximum number of timers (%d) is reached.",
+                      TID_USERMAX );
+            return 0;
+#endif
+        }
 	timerVec->resize( ind * 4 );
     }
@@ -329,25 +556,13 @@
     t->obj  = obj;
 
-//@@TODO (dmik): later (needed for plugin support)
-//    if ( qt_win_use_simple_timers ) {
-//	t->zero = FALSE;
-//	t->id = SetTimer( 0, 0, (uint)interval,
-//			  (TIMERPROC)qt_simple_timer_func );
-//    } else {
-	t->zero = interval == 0;
-	if ( t->zero ) {			// add zero timer
-            t->id = 0;
-	    numZeroTimers++;
-            // post WM_NULL to our message queue to let
-            // QEventLoop::processEvents() handle a newly created zero
-            // timer as soon as possible; otherwise we could get quite a
-            // noticeable delay between starting and emitting the first
-            // signal (longer than if we had started a regular 1 ms timer),
-            // due to the internal implementation of the WinGetMsg() function.
-            WinPostMsg( 0, WM_NULL, 0, 0 );
-	} else {
-            t->id = WinStartTimer( 0, 0, 0, (ULONG) interval );
-	}
-//    }
+    t->zero = interval == 0;
+    if ( t->zero ) {				// add zero timer
+        t->id = 0;
+        numZeroTimers++;
+        // indicate there is a new zero timer
+        WinPostMsg( qt_aux_win.hwnd(), WM_U_SEM_ZEROTIMER, 0, 0 );
+    } else {
+        t->id = WinStartTimer( 0, qt_aux_win.hwnd(), ind + 1, (ULONG) interval );
+    }
     if ( !t->zero && t->id == 0 ) {
 #if defined(QT_CHECK_STATE)
@@ -467,8 +682,8 @@
             ss_mutex.unlock();
             int nsel = ::select( nfds,
-                               &d->sn_vec[0].select_fds,
-                               &d->sn_vec[1].select_fds,
-                               &d->sn_vec[2].select_fds,
-                               NULL );
+                                 &d->sn_vec[0].select_fds,
+                                 &d->sn_vec[1].select_fds,
+                                 &d->sn_vec[2].select_fds,
+                                 NULL );
             if ( nsel > 0 ) {
                 ss_mutex.lock();
@@ -496,6 +711,6 @@
                 }
                 ss_mutex.unlock();
-                // wake up gui thread to let it activate notifiers
-                WinPostQueueMsg( qt_gui_queue, WM_NULL, 0, 0 );
+                // post a message to activate socket notifiers 
+                qt_aux_win.post( WM_U_SEM_SELECT, 0, 0 );
             }
         } else {
@@ -511,6 +726,7 @@
 }
 
-void QSockSelectThread::cancelSelectOrIdle( bool terminate )
-{
+void QSockSelectThread::cancelSelectOrIdle( bool terminate /* = FALSE */ )
+{
+    ss_mutex.lock();
     exit = terminate;
     if ( d->sn_highest >= 0 ) {
@@ -522,4 +738,5 @@
             ss_flag --;
     }
+    ss_mutex.unlock();
     // wait for this thread to end if the termination is requested
     if ( exit )
@@ -531,15 +748,9 @@
     ss_thread->cancelSelectOrIdle( TRUE );
     delete ss_thread;
+    ss_thread = 0;
 }
 
 static void ss_init( QEventLoopPrivate *d )
 {
-    if ( ss_thread ) {
-        // the user has created a second QEventLoop instance, it should
-        // completely replace the previous (see also QEventLoop::QEventLoop()).
-        ss_cleanup();
-    } else {
-        qAddPostRoutine( ss_cleanup );
-    }
     // capture the flag initially
     ss_flag ++;
@@ -564,12 +775,13 @@
     qt_gui_queue = d->hmq;
 
+    qt_aux_win.setEventLoop( this ); 
+
 #if defined(QT_THREAD_SUPPORT)
-    ss_init( d );
+    // there may only be one global QEventLoop instance that manages sockets
+    Q_ASSERT( ss_thread == 0 );
 #else
 #if defined(QT_CHECK_STATE)
-    qWarning(
-        "QEventLoop::init: socket notifiers are not supported "
-        "for a single-threaded version of Qt."
-    );
+    qWarning( "QEventLoop::init: socket notifiers are not supported "
+              "for a single-threaded version of Qt." );
 #endif
 #endif // QT_THREAD_SUPPORT
@@ -580,4 +792,17 @@
     cleanupTimers();
 
+    // ss_thread should have been stopped already in appClosingDown()
+    Q_ASSERT( ss_thread == 0 );
+    
+    qt_aux_win.setEventLoop( 0 ); 
+    
+    // destroy all windows created by QPMObjectWindow instances
+    for ( HWND *w = qt_objWindows.first(); w; w = qt_objWindows.next() ) {
+        Q_ASSERT( *w );
+        WinDestroyWindow( *w );
+        // tell QPMObjectWindow the window has been destroyed
+        *w = 0; 
+    }
+    
     WinDestroyMsgQueue( d->hmq );
     WinTerminate( d->hab );
@@ -586,7 +811,33 @@
 }
 
+void QEventLoop::appStartingUp()
+{
+}
+
+void QEventLoop::appClosingDown()
+{
+    // ensure the thread is terminated before QApplication calls
+    // QThread::cleanup()
+    if ( ss_thread )
+        ss_cleanup();
+}
+
 void QEventLoop::registerSocketNotifier( QSocketNotifier *notifier )
 {
 #if defined(QT_THREAD_SUPPORT)
+    // there may only be one global QEventLoop instance that manages sockets
+    Q_ASSERT( !qApp || qApp->eventloop == this );
+    if ( qApp && qApp->eventloop != this )
+        return;
+
+    // lazily create the auxiliary window to process WM_U_SEM_SELECT messages
+    if ( !qt_aux_win.hwnd() )
+        if ( !qt_aux_win.create() )
+            return;
+
+    // lazily start the socket select thread
+    if ( !ss_thread )
+        ss_init( d );
+
     int sockfd = -1;
     int type = -1;
@@ -663,4 +914,7 @@
     }
 
+    if ( !ss_thread )
+        return; // definitely not found
+    
     QMutexLocker locker( &ss_mutex );
     ss_thread->cancelSelectOrIdle();
@@ -709,4 +963,7 @@
     }
 
+    if ( !ss_thread )
+        return; // definitely not found
+    
     QMutexLocker locker( &ss_mutex );
 
@@ -751,83 +1008,81 @@
     QMutexLocker locker( QApplication::qt_mutex );
 #endif
-    emit awake();
-    emit qApp->guiThreadAwake();
 
     QApplication::sendPostedEvents();
 
     if ( flags & ExcludeUserInput ) {
-	while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) {
-	    if ( msg.msg == WM_CHAR ||
-		 (msg.msg >= WM_MOUSEFIRST &&
+        while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) {
+            if ( msg.msg == WM_CHAR ||
+                 (msg.msg >= WM_MOUSEFIRST &&
                      msg.msg <= WM_MOUSELAST) ||
-		 (msg.msg >= WM_EXTMOUSEFIRST &&
+                 (msg.msg >= WM_EXTMOUSEFIRST &&
                      msg.msg <= WM_EXTMOUSELAST) ||
                  msg.msg == WM_HSCROLL ||
                  msg.msg == WM_VSCROLL
             ) {
-		WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
-		continue;
-	    }
-	    break;
-	}
+                WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
+                continue;
+            }
+            break;
+        }
     }
 
     bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore);
-
-    if ( canWait ) {				// can wait if necessary
-	if ( numZeroTimers ) {			// activate full-speed timers
-	    int ok = FALSE;
-            while ( numZeroTimers && !ok ) {
-		activateZeroTimers();
-		ok = WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
-	    }
-	    if ( !ok )	{			// no event
-		return FALSE;
-	    }
-	} else {
-	    if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) )
-		emit aboutToBlock();
+    
+    if ( canWait ) {
+        // can wait if necessary
+        if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) {
+            emit aboutToBlock();
 #ifdef QT_THREAD_SUPPORT
-	    locker.mutex()->unlock();
-#endif // QT_THREAD_SUPPORT
-	    if ( !WinGetMsg( 0, &msg, 0, 0, 0 ) ) {	// WM_QUIT received
-#if !defined (QT_NO_SESSIONMANAGER)
-                if ( qt_app_canQuit() ) {
-#endif                    
+            locker.mutex()->unlock();
+#endif
+            WinGetMsg( 0, &msg, 0, 0, 0 );
 #ifdef QT_THREAD_SUPPORT
-                    locker.mutex()->lock();
-#endif // QT_THREAD_SUPPORT
-                    exit( 0 );
-                    return FALSE;
-#if !defined (QT_NO_SESSIONMANAGER)
-                } else {
-                    WinCancelShutdown( d->hmq, FALSE );
-                }
-#endif                    
-	    }
-#ifdef QT_THREAD_SUPPORT
-	    locker.mutex()->lock();
-#endif // QT_THREAD_SUPPORT
-	}
-    } else {					// no-wait mode
-	if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) { // no pending events
-	    if ( numZeroTimers > 0 ) {		// there are 0-timers
-		activateZeroTimers();
-	    }
+            locker.mutex()->lock();
+#endif
+            emit awake();
+            emit qApp->guiThreadAwake();
+        }
+    } else {
+	if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) {
+            // no pending events
 	    return FALSE;
 	}
     }
+    
+    if ( msg.msg == WM_QUIT ) {
+        // process the quit request
+#if !defined (QT_NO_SESSIONMANAGER)
+        if ( qt_app_canQuit() ) {
+#endif                    
+            exit( 0 );
+            return TRUE;
+#if !defined (QT_NO_SESSIONMANAGER)
+        } else {
+            WinCancelShutdown( d->hmq, FALSE );
+            return TRUE;
+        }
+#endif                    
+    }
 
     bool handled = FALSE;
-    if ( msg.msg == WM_TIMER ) {		// timer message received
-	if ( dispatchTimer( (uint)SHORT1FROMMP(msg.mp1), &msg ) )
-	    return TRUE;
-    } else if ( msg.msg && (!msg.hwnd || !QWidget::find(msg.hwnd)) ) {
-	MRESULT res = 0;
+    MRESULT res = 0;
+
+    if ( msg.msg == WM_U_SEM_SELECT ) {
+        // socket select event received: prevent it from being handled by
+        // qt_aux_win (to obey the ExcludeSocketNotifiers flag)
+        handled = TRUE;
+        // ignore socket notifier activation if processd by the Qt event hook
+        if ( qt_pmEventFilter( &msg, res ) )
+            flags |= ExcludeSocketNotifiers;
+    }
+    
+    if ( !handled && msg.msg && (!msg.hwnd || !QWidget::find( msg.hwnd )) ) {
 	handled = qt_pmEventFilter( &msg, res );
     }
 
     if ( !handled ) {
-	WinDispatchMsg( 0, &msg );              // send to QtWndProc
+        // send to QtWndProc or to a native window procedure
+	WinDispatchMsg( 0, &msg );
     }
 
@@ -835,5 +1090,6 @@
 	activateSocketNotifiers();
 
-    if ( configRequests )			// any pending configs?
+    // any pending configs?    
+    if ( configRequests )
 	qPMProcessConfigRequests();
     QApplication::sendPostedEvents();
@@ -868,4 +1124,7 @@
 	return 0;
 
+    if ( !ss_thread )
+        return 0;
+    
     // postpone activation if ss_thread is working with the list
     if ( !ss_mutex.tryLock() )
Index: trunk/src/kernel/qsocketnotifier.cpp
===================================================================
--- trunk/src/kernel/qsocketnotifier.cpp	(revision 112)
+++ trunk/src/kernel/qsocketnotifier.cpp	(revision 113)
@@ -167,5 +167,5 @@
     if ( socket < 0 )
 	qWarning( "QSocketNotifier: Invalid socket specified" );
-#  if defined(Q_OS_UNIX)
+#  if defined(Q_OS_UNIX) || defined(Q_OS_OS2)
     if ( socket >= FD_SETSIZE )
 	qWarning( "QSocketNotifier: Socket descriptor too large for select()" );
