Changeset 113


Ignore:
Timestamp:
Aug 10, 2006, 7:50:03 PM (19 years ago)
Author:
dmik
Message:

Kernel: Improved QEventLoop:

  • Timer and socket notifier events are now delivered even if the main event loop is run outside Qt (i.e., by a native modal dialog or when moving/resizing the widet using the mouse).
  • Added the non-portable QPMObjectWindow class (included from qwindowdefs.h) to simplify object window creation and maintainance.
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/qwindowdefs_pm.h

    r97 r113  
    9999const ULONG QT_EXTRAWINDATASIZE = sizeof(LONG) * 2;
    100100
     101#ifdef __cplusplus
     102class Q_EXPORT QPMObjectWindow
     103{
     104public:
     105    QPMObjectWindow( bool deferred = FALSE );
     106    virtual ~QPMObjectWindow();
     107   
     108    bool create();
     109    bool destroy();
     110    HWND hwnd() const { return w; }
     111
     112    MRESULT send( ULONG msg, MPARAM mp1, MPARAM mp2 ) const {
     113        return WinSendMsg( w, msg, mp1, mp2 );
     114    }
     115    bool post( ULONG msg, MPARAM mp1, MPARAM mp2 ) const {
     116        return WinPostMsg( w, msg, mp1, mp2 );
     117    }
     118   
     119    virtual MRESULT message( ULONG msg, MPARAM mp1, MPARAM mp2 ) = 0;
     120   
     121private:
     122    static MRESULT EXPENTRY windowProc( HWND, ULONG, MPARAM, MPARAM );
     123
     124    HWND w;
     125};
    101126#endif
     127
     128#endif
  • trunk/src/kernel/qeventloop.cpp

    r2 r113  
    386386*/
    387387
    388 #if !defined(Q_WS_X11)
     388#if !defined(Q_WS_X11) && !defined(Q_WS_PM)
    389389void QEventLoop::appStartingUp(){}
    390390void QEventLoop::appClosingDown(){}
    391 #endif // Q_WS_X11
     391#endif // !Q_WS_X11 && !Q_WS_PM
  • trunk/src/kernel/qeventloop_pm.cpp

    r77 r113  
    3939#include "qeventloop.h"
    4040#include "qapplication.h"
     41#include "qptrlist.h"
    4142
    4243#include <sys/socket.h>
     
    4849#endif // QT_THREAD_SUPPORT
    4950
     51// entry point: PMWIN.305
     52extern "C" HMQ APIENTRY WinQueueFromID( HAB hab, PID pid, PID tid );
     53
    5054extern uint qGlobalPostedEventsCount();
    5155extern bool qt_pmEventFilter( QMSG* msg, MRESULT &result );
     
    5761static HAB qt_gui_hab = 0;
    5862static HMQ qt_gui_queue = 0;
    59 
    60 /// @todo (dmik) later
    61 //  Simpler timers are needed when Qt does not have the event loop,
    62 //  such as for plugins.
    63 //#ifndef Q_OS_TEMP
    64 //Q_EXPORT bool qt_win_use_simple_timers = TRUE;
    65 //#else
    66 //Q_EXPORT bool qt_win_use_simple_timers = FALSE;
    67 //#endif
    68 //void CALLBACK   qt_simple_timer_func( HWND, UINT, UINT, DWORD );
    6963
    7064static void     initTimers();
     
    9286#if defined(QT_CHECK_STATE)
    9387        if( !qt_suppress_morph_warning )
    94             qWarning(
    95                 "Qt: the program has not been linked as the Presentation Manager application\n"
    96                 "    but it uses GUI capabilities. Switching to PM mode dynamically."
    97             );
     88            qWarning( "Qt: the program has not been linked as the Presentation "
     89                      "Manager application\n"
     90                      "but it uses GUI capabilities. Switching to PM mode "
     91                      "dynamically." );
    9892#endif
    9993        ppib->pib_ultype = 3;
    10094    }
    10195}
     96
     97enum
     98{
     99    // socket select notification (highest priority)
     100    WM_U_SEM_SELECT = WM_SEM1,
     101    // zero timer notification (lowest priority)
     102    WM_U_SEM_ZEROTIMER = WM_SEM4,
     103};
     104
     105/*****************************************************************************
     106  Auxiliary object window class for dedicated message processing.
     107  Declared in qwindowdefs_pm.h
     108 *****************************************************************************/
     109
     110/*!
     111  \class QPMObjectWindow qwindowdefs.h
     112   
     113  The QPMObjectWindow class is an auxiliary class for dedicated message
     114  processing. Its functionality is based on PM object windows. Once an instance
     115  of this class is created, PM window messages can be sent or posted to it using
     116  send() or post() methods. Subclasses should override the message() method to
     117  process sent or posted messages. The hwnd() method is used whenever a PM
     118  window handle of this object window is necessary to be passed as a HWND
     119  argument to other calls and/or messages.
     120 
     121  Instances of this class must be created on the main GUI thread only or on a
     122  thread that has created a PM message queue and runs the PM message loop
     123  \b itself. If you create an instance on a thread other than main, make sure
     124  you destroy it before destroying the thread's message queue.
     125 
     126  \note WM_CREATE and WM_DESTROY messages are processed internally and not
     127  delivered do the message() method. Instead, you can use the constructor and
     128  the destructor of the subclasses, respectively.
     129 
     130  \note This class is non-portable!
     131*/
     132
     133// returns HMQ of the current thread or NULL if no event queue has been created
     134static HMQ qt_WinQueryQueue( HAB hab )
     135{
     136    PTIB ptib;
     137    PPIB ppib;
     138    DosGetInfoBlocks( &ptib, &ppib );
     139    return WinQueueFromID( hab, ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid );
     140}
     141
     142static QPtrList<HWND> qt_objWindows;
     143
     144/*!
     145  Constructs a new object window for the current thread.
     146  If \a deferred is FALSE, this method calls create() to create a PM object
     147  window. Otherwise, you must call create() yourself before this object
     148  window is able to process messages.
     149*/
     150QPMObjectWindow::QPMObjectWindow( bool deferred /* = FALSE */ ) :
     151    w( NULLHANDLE )
     152{
     153    if ( !deferred )
     154        create();
     155}
     156
     157/*!
     158  Destroys this object window.
     159  This method calls destroy() to free the PM object window.
     160*/
     161QPMObjectWindow::~QPMObjectWindow()
     162{
     163    destroy();
     164}
     165
     166/*!
     167  Creates a PM object window.
     168  Returns \c TRUE on success or \c FALSE otherwise.
     169  The method does nothing but returns \c FALSE  if the window has been
     170  already created. The handle of the successfully created object window can
     171  be obtained using the hwnd() method.
     172 
     173  \note Must be called on the same thread that cosnstructed this instance.
     174*/
     175bool QPMObjectWindow::create()
     176{
     177    if ( w != NULLHANDLE )
     178        return FALSE;
     179   
     180    static const char *ClassName = "QPMObjectWindow";
     181    static bool classRegistered = FALSE;
     182   
     183    if ( !classRegistered ) {
     184        WinRegisterClass( 0, ClassName, windowProc, 0, QWL_USER + sizeof(PVOID) );
     185        classRegistered = TRUE;
     186    }
     187
     188    w = WinCreateWindow( HWND_OBJECT, ClassName,
     189                         NULL, 0, 0, 0, 0, 0, NULL,
     190                         HWND_BOTTOM, 0, this, NULL );
     191#ifndef QT_NO_DEBUG
     192    if ( w == NULLHANDLE )
     193        qSystemWarning( "QPMObjectWindow: Failed to create object window" );
     194#endif   
     195
     196    if ( w != NULLHANDLE && qt_gui_queue &&
     197         qt_WinQueryQueue( 0 ) == qt_gui_queue ) {
     198            // store the handle in the list for clean destruction
     199            qt_objWindows.append( &w );
     200    }
     201   
     202    return w != NULLHANDLE;
     203}
     204
     205/*!
     206  Destroys the PM object window.
     207  Returns \c TRUE on success or \c FALSE otherwise.
     208  The method does nothing but returns \c FALSE  if the window has been
     209  already destroyed (or never created).
     210 
     211  \note Must be called on the same thread that cosnstructed this instance.
     212*/
     213bool QPMObjectWindow::destroy()
     214{
     215    if ( w == NULLHANDLE )
     216        return FALSE;
     217   
     218    if ( qt_gui_queue && qt_WinQueryQueue( 0 ) == qt_gui_queue ) {
     219        // remove the handle from the 'clean destruction' list
     220        qt_objWindows.removeRef( &w );
     221    }
     222
     223    HWND h = w;
     224    w = 0; // tell windowProc() we're unsafe
     225    WinDestroyWindow( h );
     226   
     227    return TRUE;
     228}
     229
     230//static
     231MRESULT EXPENTRY QPMObjectWindow::windowProc( HWND hwnd, ULONG msg,
     232                                              MPARAM mp1, MPARAM mp2 )
     233{
     234    if ( msg == WM_CREATE ) {
     235        QPMObjectWindow *that = static_cast< QPMObjectWindow *>( mp1 );
     236        if ( !that )
     237            return (MRESULT) TRUE;
     238        WinSetWindowPtr( hwnd, QWL_USER, that );
     239        return (MRESULT) FALSE;
     240    }
     241
     242    QPMObjectWindow *that =
     243        static_cast< QPMObjectWindow * >( WinQueryWindowPtr( hwnd, QWL_USER ) );
     244    Q_ASSERT( that );
     245   
     246    // Note: before WinCreateWindow() returns to the constructor or after the
     247    // destructor has been called, w is 0. We use this to determine that the
     248    // object is in the unsafe state (VTBL is not yet initialized or has been
     249    // already uninitialized), so message() points to never-never land.
     250    if ( !that || !that->w )
     251        return (MRESULT) FALSE;
     252   
     253    return that->message( msg, mp1, mp2 );
     254}
     255
     256/*!
     257  \fn QPMObjectWindow::send( ULONG msg, MPARAM mp1, MPARAM mp2 ) const
     258 
     259  Synchronously sends a message \a msg with the given parameters \a mp1 and
     260  \a mp2 to this window handle and returns a reply from the message() function.
     261 
     262  \note Must be called on the same thread that cosnstructed this instance.
     263*/
     264
     265/*!
     266  \fn QPMObjectWindow::post( ULONG msg, MPARAM mp1, MPARAM mp2 ) const
     267 
     268  Asynchronously posts a message \a msg with the given parameters \a mp1 and
     269  \a mp2 to this window handle. Returns \c TRUE on success and \c FALSE
     270  otherwise.
     271 
     272  \note Can be called on any thread.
     273*/
     274
     275// Auxiliary object window to process WM_U_SEM_SELECT and WM_TIMER messages.
     276// We need a dedicated window along with processing these messages directly in
     277// QEventLoop::processEvents() to make sure they are processed even if the
     278// current message loop is not run by Qt. This happens when a native modal
     279// dialog is shown or when a top-level Qt widget is being moved or resized
     280// using the mouse, or when a Qt-based DLL plugin is used by a non-Qt
     281// application.
     282
     283class QPMAuxEventQueueWin : public QPMObjectWindow
     284{
     285public:
     286    QPMAuxEventQueueWin() : QPMObjectWindow( TRUE ), eventLoop( NULL ) {}
     287    void setEventLoop( QEventLoop *el ) { eventLoop = el; }
     288    MRESULT message( ULONG msg, MPARAM mp1, MPARAM mp2 );
     289private:
     290    QEventLoop *eventLoop;
     291};
     292
     293MRESULT QPMAuxEventQueueWin::message( ULONG msg, MPARAM mp1, MPARAM mp2 )
     294{
     295    switch ( msg ) {
     296        case WM_U_SEM_SELECT: {
     297            if ( eventLoop )
     298                eventLoop->activateSocketNotifiers();
     299            break;
     300        }
     301        case WM_U_SEM_ZEROTIMER: {
     302            if ( numZeroTimers ) {
     303                activateZeroTimers();
     304                // repost the message if there are still zero timers left
     305                if ( numZeroTimers )
     306                    WinPostMsg( hwnd(), WM_U_SEM_ZEROTIMER, 0, 0 );
     307            }
     308            break;
     309        }
     310        case WM_TIMER: {
     311            USHORT id = SHORT1FROMMP( mp1 );
     312            QMSG qmsg = { hwnd(), msg, mp1, mp2 };
     313            dispatchTimer( (uint) id, &qmsg );
     314            break;
     315        }
     316    }
     317   
     318    return FALSE;
     319}
     320
     321static QPMAuxEventQueueWin qt_aux_win;
     322
    102323
    103324/*****************************************************************************
     
    212433
    213434
    214 //@@TODO (dmik): later (needed for plugin support)
    215 //void CALLBACK qt_simple_timer_func( HWND, UINT, UINT idEvent, DWORD )
    216 //{
    217 //    dispatchTimer( idEvent, 0 );
    218 //}
    219 
    220 
    221435// Activate a timer, used by both event-loop based and simple timers.
    222436
     
    273487static void initTimers()                        // initialize timers
    274488{
    275 //@@TODO (dmik): qt_ensure_pm() should not be called when simple timers are
    276 //  implemented to be used by plugins.
    277     qt_ensure_pm();
    278489    timerVec = new TimerVec( 128 );
    279490    Q_CHECK_PTR( timerVec );
     
    282493    Q_CHECK_PTR( timerDict );
    283494}
     495
     496/// @todo (dmik) cleanupTimers() is only called by QEventLoop::cleanup() so it
     497//  won't be called if there is no QEventLoop instance created (for example,
     498//  when a Qt-based plugin DLL is used by a non-Qt application). Use atexit()?
     499//  Btw, the same relates to the QThread::cleanup() vs QApplication pair.
     500//  And to qt_aux_win (the DLL may be unloaded after the application has
     501//  destroyed the main event queue, so the static destructor will not be able
     502//  to properly destroy the window).
    284503
    285504static void cleanupTimers()                     // remove pending timers
     
    291510        t = timerVec->at( i );
    292511        if ( t && !t->zero )
    293             WinStopTimer( 0, 0, t->id );
     512            WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
    294513    }
    295514    delete timerDict;
     
    297516    delete timerVec;
    298517    timerVec  = 0;
    299 
    300 //@@TODO (dmik): later (needed for plugin support)
    301 //    if ( qt_win_use_simple_timers ) {
    302 //      // Dangerous to leave WM_TIMER events in the queue if they have our
    303 //      // timerproc (eg. Qt-based DLL plugins may be unloaded)
    304 //      MSG msg;
    305 //      while (winPeekMessage( &msg, (HWND)-1, WM_TIMER, WM_TIMER, PM_REMOVE ))
    306 //          continue;
    307 //    }
    308518}
    309519
     
    316526int qStartTimer( int interval, QObject *obj )
    317527{
     528    Q_ASSERT( obj );
     529    if ( !obj )
     530        return 0;
     531   
     532    // lazily create the auxiliary window to process WM_TIMER messages
     533    if ( !qt_aux_win.hwnd() )
     534        if ( !qt_aux_win.create() )
     535            return 0;
     536   
    318537    register TimerInfo *t;
    319538    if ( !timerVec )                            // initialize timer data
    320539        initTimers();
     540
    321541    int ind = timerVec->findRef( 0 );           // get free timer
    322     if ( ind == -1 || !obj ) {
     542    if ( ind == -1 ) {
    323543        ind = timerVec->size();                 // increase the size
     544        if ( ind >= TID_USERMAX ) {
     545#if defined(QT_CHECK_STATE)
     546            qWarning( "qStartTimer: Maximum number of timers (%d) is reached.",
     547                      TID_USERMAX );
     548            return 0;
     549#endif
     550        }
    324551        timerVec->resize( ind * 4 );
    325552    }
     
    329556    t->obj  = obj;
    330557
    331 //@@TODO (dmik): later (needed for plugin support)
    332 //    if ( qt_win_use_simple_timers ) {
    333 //      t->zero = FALSE;
    334 //      t->id = SetTimer( 0, 0, (uint)interval,
    335 //                        (TIMERPROC)qt_simple_timer_func );
    336 //    } else {
    337         t->zero = interval == 0;
    338         if ( t->zero ) {                        // add zero timer
    339             t->id = 0;
    340             numZeroTimers++;
    341             // post WM_NULL to our message queue to let
    342             // QEventLoop::processEvents() handle a newly created zero
    343             // timer as soon as possible; otherwise we could get quite a
    344             // noticeable delay between starting and emitting the first
    345             // signal (longer than if we had started a regular 1 ms timer),
    346             // due to the internal implementation of the WinGetMsg() function.
    347             WinPostMsg( 0, WM_NULL, 0, 0 );
    348         } else {
    349             t->id = WinStartTimer( 0, 0, 0, (ULONG) interval );
    350         }
    351 //    }
     558    t->zero = interval == 0;
     559    if ( t->zero ) {                            // add zero timer
     560        t->id = 0;
     561        numZeroTimers++;
     562        // indicate there is a new zero timer
     563        WinPostMsg( qt_aux_win.hwnd(), WM_U_SEM_ZEROTIMER, 0, 0 );
     564    } else {
     565        t->id = WinStartTimer( 0, qt_aux_win.hwnd(), ind + 1, (ULONG) interval );
     566    }
    352567    if ( !t->zero && t->id == 0 ) {
    353568#if defined(QT_CHECK_STATE)
     
    467682            ss_mutex.unlock();
    468683            int nsel = ::select( nfds,
    469                                &d->sn_vec[0].select_fds,
    470                                &d->sn_vec[1].select_fds,
    471                                &d->sn_vec[2].select_fds,
    472                                NULL );
     684                                 &d->sn_vec[0].select_fds,
     685                                 &d->sn_vec[1].select_fds,
     686                                 &d->sn_vec[2].select_fds,
     687                                 NULL );
    473688            if ( nsel > 0 ) {
    474689                ss_mutex.lock();
     
    496711                }
    497712                ss_mutex.unlock();
    498                 // wake up gui thread to let it activate notifiers
    499                 WinPostQueueMsg( qt_gui_queue, WM_NULL, 0, 0 );
     713                // post a message to activate socket notifiers
     714                qt_aux_win.post( WM_U_SEM_SELECT, 0, 0 );
    500715            }
    501716        } else {
     
    511726}
    512727
    513 void QSockSelectThread::cancelSelectOrIdle( bool terminate )
    514 {
     728void QSockSelectThread::cancelSelectOrIdle( bool terminate /* = FALSE */ )
     729{
     730    ss_mutex.lock();
    515731    exit = terminate;
    516732    if ( d->sn_highest >= 0 ) {
     
    522738            ss_flag --;
    523739    }
     740    ss_mutex.unlock();
    524741    // wait for this thread to end if the termination is requested
    525742    if ( exit )
     
    531748    ss_thread->cancelSelectOrIdle( TRUE );
    532749    delete ss_thread;
     750    ss_thread = 0;
    533751}
    534752
    535753static void ss_init( QEventLoopPrivate *d )
    536754{
    537     if ( ss_thread ) {
    538         // the user has created a second QEventLoop instance, it should
    539         // completely replace the previous (see also QEventLoop::QEventLoop()).
    540         ss_cleanup();
    541     } else {
    542         qAddPostRoutine( ss_cleanup );
    543     }
    544755    // capture the flag initially
    545756    ss_flag ++;
     
    564775    qt_gui_queue = d->hmq;
    565776
     777    qt_aux_win.setEventLoop( this );
     778
    566779#if defined(QT_THREAD_SUPPORT)
    567     ss_init( d );
     780    // there may only be one global QEventLoop instance that manages sockets
     781    Q_ASSERT( ss_thread == 0 );
    568782#else
    569783#if defined(QT_CHECK_STATE)
    570     qWarning(
    571         "QEventLoop::init: socket notifiers are not supported "
    572         "for a single-threaded version of Qt."
    573     );
     784    qWarning( "QEventLoop::init: socket notifiers are not supported "
     785              "for a single-threaded version of Qt." );
    574786#endif
    575787#endif // QT_THREAD_SUPPORT
     
    580792    cleanupTimers();
    581793
     794    // ss_thread should have been stopped already in appClosingDown()
     795    Q_ASSERT( ss_thread == 0 );
     796   
     797    qt_aux_win.setEventLoop( 0 );
     798   
     799    // destroy all windows created by QPMObjectWindow instances
     800    for ( HWND *w = qt_objWindows.first(); w; w = qt_objWindows.next() ) {
     801        Q_ASSERT( *w );
     802        WinDestroyWindow( *w );
     803        // tell QPMObjectWindow the window has been destroyed
     804        *w = 0;
     805    }
     806   
    582807    WinDestroyMsgQueue( d->hmq );
    583808    WinTerminate( d->hab );
     
    586811}
    587812
     813void QEventLoop::appStartingUp()
     814{
     815}
     816
     817void QEventLoop::appClosingDown()
     818{
     819    // ensure the thread is terminated before QApplication calls
     820    // QThread::cleanup()
     821    if ( ss_thread )
     822        ss_cleanup();
     823}
     824
    588825void QEventLoop::registerSocketNotifier( QSocketNotifier *notifier )
    589826{
    590827#if defined(QT_THREAD_SUPPORT)
     828    // there may only be one global QEventLoop instance that manages sockets
     829    Q_ASSERT( !qApp || qApp->eventloop == this );
     830    if ( qApp && qApp->eventloop != this )
     831        return;
     832
     833    // lazily create the auxiliary window to process WM_U_SEM_SELECT messages
     834    if ( !qt_aux_win.hwnd() )
     835        if ( !qt_aux_win.create() )
     836            return;
     837
     838    // lazily start the socket select thread
     839    if ( !ss_thread )
     840        ss_init( d );
     841
    591842    int sockfd = -1;
    592843    int type = -1;
     
    663914    }
    664915
     916    if ( !ss_thread )
     917        return; // definitely not found
     918   
    665919    QMutexLocker locker( &ss_mutex );
    666920    ss_thread->cancelSelectOrIdle();
     
    709963    }
    710964
     965    if ( !ss_thread )
     966        return; // definitely not found
     967   
    711968    QMutexLocker locker( &ss_mutex );
    712969
     
    7511008    QMutexLocker locker( QApplication::qt_mutex );
    7521009#endif
    753     emit awake();
    754     emit qApp->guiThreadAwake();
    7551010
    7561011    QApplication::sendPostedEvents();
    7571012
    7581013    if ( flags & ExcludeUserInput ) {
    759         while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) {
    760             if ( msg.msg == WM_CHAR ||
    761                 (msg.msg >= WM_MOUSEFIRST &&
     1014        while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) {
     1015            if ( msg.msg == WM_CHAR ||
     1016                (msg.msg >= WM_MOUSEFIRST &&
    7621017                     msg.msg <= WM_MOUSELAST) ||
    763                 (msg.msg >= WM_EXTMOUSEFIRST &&
     1018                (msg.msg >= WM_EXTMOUSEFIRST &&
    7641019                     msg.msg <= WM_EXTMOUSELAST) ||
    7651020                 msg.msg == WM_HSCROLL ||
    7661021                 msg.msg == WM_VSCROLL
    7671022            ) {
    768                 WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
    769                 continue;
    770             }
    771             break;
    772         }
     1023                WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
     1024                continue;
     1025            }
     1026            break;
     1027        }
    7731028    }
    7741029
    7751030    bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore);
    776 
    777     if ( canWait ) {                            // can wait if necessary
    778         if ( numZeroTimers ) {                  // activate full-speed timers
    779             int ok = FALSE;
    780             while ( numZeroTimers && !ok ) {
    781                 activateZeroTimers();
    782                 ok = WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE );
    783             }
    784             if ( !ok )  {                       // no event
    785                 return FALSE;
    786             }
    787         } else {
    788             if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) )
    789                 emit aboutToBlock();
     1031   
     1032    if ( canWait ) {
     1033        // can wait if necessary
     1034        if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) {
     1035            emit aboutToBlock();
    7901036#ifdef QT_THREAD_SUPPORT
    791             locker.mutex()->unlock();
    792 #endif // QT_THREAD_SUPPORT
    793             if ( !WinGetMsg( 0, &msg, 0, 0, 0 ) ) {     // WM_QUIT received
    794 #if !defined (QT_NO_SESSIONMANAGER)
    795                 if ( qt_app_canQuit() ) {
    796 #endif                   
     1037            locker.mutex()->unlock();
     1038#endif
     1039            WinGetMsg( 0, &msg, 0, 0, 0 );
    7971040#ifdef QT_THREAD_SUPPORT
    798                     locker.mutex()->lock();
    799 #endif // QT_THREAD_SUPPORT
    800                     exit( 0 );
    801                     return FALSE;
    802 #if !defined (QT_NO_SESSIONMANAGER)
    803                 } else {
    804                     WinCancelShutdown( d->hmq, FALSE );
    805                 }
    806 #endif                   
    807             }
    808 #ifdef QT_THREAD_SUPPORT
    809             locker.mutex()->lock();
    810 #endif // QT_THREAD_SUPPORT
    811         }
    812     } else {                                    // no-wait mode
    813         if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) { // no pending events
    814             if ( numZeroTimers > 0 ) {          // there are 0-timers
    815                 activateZeroTimers();
    816             }
     1041            locker.mutex()->lock();
     1042#endif
     1043            emit awake();
     1044            emit qApp->guiThreadAwake();
     1045        }
     1046    } else {
     1047        if ( !WinPeekMsg( 0, &msg, 0, 0, 0, PM_REMOVE ) ) {
     1048            // no pending events
    8171049            return FALSE;
    8181050        }
    8191051    }
     1052   
     1053    if ( msg.msg == WM_QUIT ) {
     1054        // process the quit request
     1055#if !defined (QT_NO_SESSIONMANAGER)
     1056        if ( qt_app_canQuit() ) {
     1057#endif                   
     1058            exit( 0 );
     1059            return TRUE;
     1060#if !defined (QT_NO_SESSIONMANAGER)
     1061        } else {
     1062            WinCancelShutdown( d->hmq, FALSE );
     1063            return TRUE;
     1064        }
     1065#endif                   
     1066    }
    8201067
    8211068    bool handled = FALSE;
    822     if ( msg.msg == WM_TIMER ) {                // timer message received
    823         if ( dispatchTimer( (uint)SHORT1FROMMP(msg.mp1), &msg ) )
    824             return TRUE;
    825     } else if ( msg.msg && (!msg.hwnd || !QWidget::find(msg.hwnd)) ) {
    826         MRESULT res = 0;
     1069    MRESULT res = 0;
     1070
     1071    if ( msg.msg == WM_U_SEM_SELECT ) {
     1072        // socket select event received: prevent it from being handled by
     1073        // qt_aux_win (to obey the ExcludeSocketNotifiers flag)
     1074        handled = TRUE;
     1075        // ignore socket notifier activation if processd by the Qt event hook
     1076        if ( qt_pmEventFilter( &msg, res ) )
     1077            flags |= ExcludeSocketNotifiers;
     1078    }
     1079   
     1080    if ( !handled && msg.msg && (!msg.hwnd || !QWidget::find( msg.hwnd )) ) {
    8271081        handled = qt_pmEventFilter( &msg, res );
    8281082    }
    8291083
    8301084    if ( !handled ) {
    831         WinDispatchMsg( 0, &msg );              // send to QtWndProc
     1085        // send to QtWndProc or to a native window procedure
     1086        WinDispatchMsg( 0, &msg );
    8321087    }
    8331088
     
    8351090        activateSocketNotifiers();
    8361091
    837     if ( configRequests )                       // any pending configs?
     1092    // any pending configs?   
     1093    if ( configRequests )
    8381094        qPMProcessConfigRequests();
    8391095    QApplication::sendPostedEvents();
     
    8681124        return 0;
    8691125
     1126    if ( !ss_thread )
     1127        return 0;
     1128   
    8701129    // postpone activation if ss_thread is working with the list
    8711130    if ( !ss_mutex.tryLock() )
  • trunk/src/kernel/qsocketnotifier.cpp

    r2 r113  
    167167    if ( socket < 0 )
    168168        qWarning( "QSocketNotifier: Invalid socket specified" );
    169 #  if defined(Q_OS_UNIX)
     169#  if defined(Q_OS_UNIX) || defined(Q_OS_OS2)
    170170    if ( socket >= FD_SETSIZE )
    171171        qWarning( "QSocketNotifier: Socket descriptor too large for select()" );
Note: See TracChangeset for help on using the changeset viewer.