Ignore:
Timestamp:
Jul 4, 2009, 2:13:09 PM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: OS/2: Initial port of QEventDispatcher.

Location:
trunk/src/corelib/kernel
Files:
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/kernel/qeventdispatcher_pm.cpp

    r63 r67  
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    44** Contact: Qt Software Information ([email protected])
     5
     6
    57**
    68** This file is part of the QtCore module of the Qt Toolkit.
     
    4042****************************************************************************/
    4143
    42 #include "qeventdispatcher_win_p.h"
     44#include "qeventdispatcher__p.h"
    4345
    4446#include "qcoreapplication.h"
     
    4951#include "qsocketnotifier.h"
    5052#include "qvarlengtharray.h"
    51 #include "qwineventnotifier_p.h"
    5253
    5354#include "qabstracteventdispatcher_p.h"
    5455#include "qcoreapplication_p.h"
     56
    5557#include <private/qthread_p.h>
    5658#include <private/qmutexpool_p.h>
    5759
     60
     61
    5862QT_BEGIN_NAMESPACE
    5963
    60 HINSTANCE qWinAppInst();
    6164extern uint qGlobalPostedEventsCount();
    6265
    63 #ifndef TIME_KILL_SYNCHRONOUS
    64 #  define TIME_KILL_SYNCHRONOUS 0x0100
    65 #endif
    66 
    67 #if defined(Q_OS_WINCE)
    68 QT_BEGIN_INCLUDE_NAMESPACE
    69 #include <winsock.h>
    70 // Asynchronous Winsocks ------------------------------------------
    71 #ifndef QT_NO_THREAD
    72 #include <qthread.h>
    73 #include <qmap.h>
    74 #include <qmutex.h>
    75 QT_END_INCLUDE_NAMESPACE
    76 
    77 //#define QCE_ASYNC_DEBUG
    78 
    79 namespace {
    80     class SocketAsyncHandler;
    81 
    82     class SocketAsyncHandler : public QThread
    83     {
    84     public:
    85         SocketAsyncHandler();
    86         ~SocketAsyncHandler();
    87         void run();
    88         void select(SOCKET sock, HWND handle, unsigned int msg, long ev);
    89         void removeSelect(SOCKET sock);
    90         void safeRemove(SOCKET sock);
    91     private:
    92         struct SockInfo {
    93             HWND handle;
    94             unsigned int msg;
    95             long ev;
    96         };
    97         QMap<SOCKET, SockInfo> sockets;
    98         QMutex mutex;
    99         QWaitCondition cond;
    100         bool supposedToDie;
    101     };
    102 
    103     SocketAsyncHandler::SocketAsyncHandler()
    104         : supposedToDie(false)
    105     {
    106     }
    107 
    108     SocketAsyncHandler::~SocketAsyncHandler()
    109     {
    110         mutex.lock();
    111         supposedToDie = true;
    112         mutex.unlock();
    113         cond.wakeOne();
    114         wait();
    115         while (sockets.size() > 0)
    116             removeSelect(sockets.begin().key());
    117     }
    118 
    119     void SocketAsyncHandler::removeSelect(SOCKET sock)
    120     {
    121         if (!sockets.contains(sock))
    122             return;
    123         sockets.remove(sock);
    124         return;
    125     }
    126 
    127     void SocketAsyncHandler::safeRemove(SOCKET sock)
    128     {
    129         QMutexLocker locker(&mutex);
    130         removeSelect(sock);
    131     }
    132 
    133     void SocketAsyncHandler::select(SOCKET sock, HWND handle, unsigned int msg, long ev)
    134     {
    135         QMutexLocker locker(&mutex);
    136 
    137         if (sockets.contains(sock))
    138             sockets.remove(sock);
    139 
    140         SockInfo info;
    141         info.handle = handle;
    142         info.msg = msg;
    143         info.ev = ev;
    144         sockets.insert(sock, info);
    145         cond.wakeOne();
    146     }
    147 
    148     void SocketAsyncHandler::run()
    149     {
    150         do {
    151             mutex.lock();
    152 
    153             while (!supposedToDie && sockets.isEmpty()) {
    154                 cond.wait(&mutex);
    155             }
    156 
    157             if (supposedToDie) {
    158                 mutex.unlock();
    159                 break;
    160             }
    161 
    162             // Copy current items to reduce lock time
    163             // and to be able to use SendMessage
    164             QMap<SOCKET, SockInfo> currentSockets = sockets;
    165             mutex.unlock();
    166 
    167             fd_set readS, writeS, exS;
    168             FD_ZERO(&readS);
    169             FD_ZERO(&writeS);
    170             FD_ZERO(&exS);
    171 
    172             int maxFd = 0;
    173 
    174             for (QMap<SOCKET, SockInfo>::iterator it = currentSockets.begin(); it != currentSockets.end(); ++it) {
    175                 const SockInfo &info = it.value();
    176                 int socket = it.key();
    177                 maxFd = qMax(maxFd, socket);
    178 
    179                 if ((info.ev & FD_READ) || (info.ev & FD_CLOSE) || (info.ev & FD_ACCEPT))
    180                     FD_SET(socket, &readS);
    181                 if ((info.ev & FD_WRITE)|| (info.ev & FD_CONNECT))
    182                     FD_SET(socket, &writeS);
    183                 if (info.ev & FD_OOB)
    184                     FD_SET(socket, &exS);
    185             }
    186 
    187             timeval timeout;
    188             timeout.tv_sec = 0;
    189             timeout.tv_usec = 50000;
    190             int result = ::select(maxFd + 1, &readS, &writeS, &exS, &timeout);
    191             if (result > 0) {
    192                 HWND handle;
    193                 unsigned int tmpMsg;
    194                 SOCKET sock;
    195                 HRESULT ret;
    196                 for (QMap<SOCKET, SockInfo>::const_iterator it = currentSockets.constBegin();
    197                     it != currentSockets.constEnd(); ++it) {
    198                         handle = (*it).handle;
    199                         tmpMsg = (*it).msg;
    200                         sock = it.key();
    201                         if (FD_ISSET(sock, &readS))
    202                             ret = SendMessage(handle, tmpMsg, sock, FD_READ);
    203 
    204                         if (FD_ISSET(sock, &writeS))
    205                             ret = SendMessage(handle, tmpMsg, sock, FD_WRITE);
    206 
    207                         if (FD_ISSET(sock, &exS))
    208                             ret = SendMessage(handle, tmpMsg, sock, FD_OOB);
    209                 }
    210             }
    211 
    212 #ifdef QCE_ASYNC_DEBUG
    213             else if (result == 0) { //timeout
    214                 qDebug("    WSAAsync select timeout");
    215             } else if (result < 0) { // SocketError
    216                 // This might happen because of two reasons
    217                 // 1. We already closed a socket in between the copy and the select
    218                 //    and thus select() returns an error
    219                 // 2. Something is really wrong, then
    220                 //    ### Loop on all descriptors, try to select and remove the
    221                 //    ### broken one.
    222                 qWarning("WSAAsync select error %d", WSAGetLastError());
    223             }
    224 #endif
    225         } while(true);
    226     }
    227 } // namespace
    228 
    229 Q_GLOBAL_STATIC(SocketAsyncHandler, qt_async_handler)
    230 
    231 int WSAAsyncSelect(SOCKET sock, HWND handle, unsigned int msg, long ev)
    232 {
    233     if (sock == 0 || handle == 0 || handle == INVALID_HANDLE_VALUE) {
    234         WSASetLastError(WSAEINVAL);
    235         return SOCKET_ERROR;
    236     }
    237 
    238     if (msg == 0 && ev == 0)
    239         qt_async_handler()->safeRemove(sock);
    240     else
    241         qt_async_handler()->select(sock, handle, msg, ev);
    242 
    243     qt_async_handler()->start(QThread::LowPriority);
    244     WSASetLastError(0);
    245     return 0;
    246 }
    247 #else // QT_NO_THREAD
    248 int WSAAsyncSelect(SOCKET, HWND, unsigned int, long)
    249 {
    250     return SOCKET_ERROR;
    251 }
    252 #endif
    253 #endif // Q_OS_WINCE
    254 
    255 class QEventDispatcherWin32Private;
    256 
    257 struct QSockNot {
    258     QSocketNotifier *obj;
    259     int fd;
    260 };
    261 typedef QHash<int, QSockNot *> QSNDict;
     66class QEventDispatcherPMPrivate;
     67
     68// @todo later: timers
     69#if 0
    26270
    26371struct WinTimerInfo {                           // internal timer info
     
    313121}
    314122
    315 
    316 class QEventDispatcherWin32Private : public QAbstractEventDispatcherPrivate
    317 {
    318     Q_DECLARE_PUBLIC(QEventDispatcherWin32)
     123#endif
     124
     125/*****************************************************************************
     126  Auxiliary object window class for dedicated message processing.
     127  Declared in qwindowdefs_pm.h
     128 *****************************************************************************/
     129
     130/*!
     131    \class QPMObjectWindow qwindowdefs.h
     132
     133    The QPMObjectWindow class is an auxiliary class for dedicated message
     134    processing. Its functionality is based on PM object windows. Once an
     135    instance of this class is created, PM window messages can be sent or posted
     136    to it using send() or post() methods. Subclasses should override the
     137    message() method to process sent or posted messages. The hwnd() method is
     138    used whenever a PM window handle of this object window is necessary to be
     139    passed as a HWND argument to other calls and/or messages.
     140
     141    Instances of this class may be created only on the main GUI thread or on a
     142    thread that has created a PM message queue and runs the PM message loop
     143    \b itself. If you create an instance on a thread other than main, make sure
     144    you destroy it before destroying the thread's message queue.
     145
     146    \note WM_CREATE and WM_DESTROY messages are processed internally and not
     147    delivered do the message() method. Instead, you can use the constructor and
     148    the destructor of the subclass, respectively.
     149
     150    \note This class is OS/2 specific and not available in Qt for other
     151    platforms!
     152*/
     153
     154/// @todo remove?
     155// returns HMQ of the current thread or NULL if no event queue has been created
     156static HMQ qt_WinQueryQueue(HAB hab)
     157{
     158    PTIB ptib;
     159    PPIB ppib;
     160    DosGetInfoBlocks(&ptib, &ppib);
     161    return WinQueueFromID(hab, ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
     162}
     163
     164/*!
     165    Constructs a new object window for the current thread.
     166    If \a deferred is \c false, this method calls create() to create a PM object
     167    window. Otherwise, you must call create() yourself before this object window
     168    is able to process messages.
     169*/
     170QPMObjectWindow::QPMObjectWindow(bool deferred /* = false */) :
     171    w(NULLHANDLE)
     172{
     173    if (!deferred)
     174        create();
     175}
     176
     177/*!
     178    Destroys this object window.
     179    This method calls destroy() to free the PM object window.
     180*/
     181QPMObjectWindow::~QPMObjectWindow()
     182{
     183    destroy();
     184}
     185
     186/*!
     187    Creates a PM object window.
     188    Returns \c true on success or \c false otherwise.
     189    The method does nothing but returns \c false if the window has been already
     190    created. The handle of the successfully created object window can be obtained
     191    using the hwnd() method.
     192
     193    \note Must be called on the same thread that cosnstructed this instance.
     194*/
     195bool QPMObjectWindow::create()
     196{
     197    if (w != NULLHANDLE)
     198        return false;
     199
     200    static const char *ClassName = "QPMObjectWindow";
     201    static bool classRegistered = FALSE;
     202
     203    if (!classRegistered) {
     204        WinRegisterClass(0, ClassName, windowProc, 0, QWL_USER + sizeof(PVOID));
     205        classRegistered = true;
     206    }
     207
     208    w = WinCreateWindow(HWND_OBJECT, ClassName,
     209                        NULL, 0, 0, 0, 0, 0, NULL,
     210                        HWND_BOTTOM, 0, this, NULL);
     211    if (w == NULLHANDLE)
     212        qWarning("QPMObjectWindow::create: WinCreateWindow failed with 0x%08lX",
     213                 WinGetLastError(0));
     214
     215    return w != NULLHANDLE;
     216}
     217
     218/*!
     219    Destroys the PM object window.
     220    Returns \c TRUE on success or \c FALSE otherwise.
     221    The method does nothing but returns \c FALSE  if the window has been
     222    already destroyed (or never created).
     223
     224    \note Must be called on the same thread that cosnstructed this instance.
     225*/
     226bool QPMObjectWindow::destroy()
     227{
     228    if (w == NULLHANDLE)
     229        return false;
     230
     231    HWND h = w;
     232    w = NULLHANDLE; // tell windowProc() we're unsafe
     233    WinDestroyWindow(h);
     234
     235    return true;
     236}
     237
     238//static
     239MRESULT EXPENTRY QPMObjectWindow::windowProc(HWND hwnd, ULONG msg,
     240                                             MPARAM mp1, MPARAM mp2)
     241{
     242    if (msg == WM_CREATE) {
     243        QPMObjectWindow *that = static_cast<QPMObjectWindow *>(mp1);
     244        if (!that)
     245            return (MRESULT) TRUE;
     246        WinSetWindowPtr(hwnd, QWL_USER, that);
     247        return (MRESULT) FALSE;
     248    }
     249
     250    QPMObjectWindow *that =
     251        static_cast<QPMObjectWindow *>(WinQueryWindowPtr(hwnd, QWL_USER));
     252    Q_ASSERT(that);
     253
     254    // Note: before WinCreateWindow() returns to the constructor or after the
     255    // destructor has been called, w is 0. We use this to determine that the
     256    // object is in the unsafe state (VTBL is not yet initialized or has been
     257    // already uninitialized), so message() points to never-never land.
     258    if (!that || !that->w)
     259        return (MRESULT) FALSE;
     260
     261    return that->message(msg, mp1, mp2);
     262}
     263
     264/*!
     265  \fn QPMObjectWindow::send(ULONG msg, MPARAM mp1, MPARAM mp2) const
     266
     267  Synchronously sends a message \a msg with the given parameters \a mp1 and
     268  \a mp2 to this window handle and returns a reply from the message() function.
     269
     270  \note Must be called on the same thread that cosnstructed this instance.
     271*/
     272
     273/*!
     274  \fn QPMObjectWindow::post(ULONG msg, MPARAM mp1, MPARAM mp2) const
     275
     276  Asynchronously posts a message \a msg with the given parameters \a mp1 and
     277  \a mp2 to this window handle. Returns \c TRUE on success and \c FALSE
     278  otherwise.
     279
     280  \note Can be called on any thread.
     281*/
     282
     283// socket select notification (highest priority)
     284#define WM_U_SEM_SELECT     WM_SEM1
     285// zero timer notification (lowest priority)
     286#define WM_U_SEM_ZEROTIMER  WM_SEM4
     287
     288class QEventDispatcherPMPrivate : public QAbstractEventDispatcherPrivate
     289{
     290    Q_DECLARE_PUBLIC(QEventDispatcherPM)
    319291public:
    320     QEventDispatcherWin32Private();
    321     ~QEventDispatcherWin32Private();
    322 
    323     DWORD threadId;
     292    QEventDispatcherPMPrivate();
     293    ~QEventDispatcherPMPrivate();
     294
     295    void createMsgQueue();
     296    void createAuxWnd();
     297
     298    // Auxiliary object window to process WM_U_SEM_SELECT and WM_TIMER messages.
     299    // We need a dedicated window along with processing these messages directly in
     300    // QEventLoop::processEvents() to make sure they are processed even if the
     301    // current message loop is not run by Qt. This happens when a native modal
     302    // dialog is shown or when a top-level Qt widget is being moved or resized
     303    // using the mouse, or when a Qt-based DLL plugin is used by a non-Qt
     304    // application.
     305    class AuxWnd : public QPMObjectWindow
     306    {
     307    public:
     308        AuxWnd() : QPMObjectWindow(true /* deferred */), dispatcher(0) {}
     309        void setDispatcher(QEventDispatcherPMPrivate *d) { dispatcher = d; }
     310        MRESULT message(ULONG msg, MPARAM mp1, MPARAM mp2);
     311        QEventDispatcherPMPrivate *dispatcher;
     312    } auxWnd;
     313
     314    HAB hab;
     315    HMQ hmq;
    324316
    325317    bool interrupt;
    326318
    327     // internal window handle used for socketnotifiers/timers/etc
    328     HWND internalHwnd;
    329 
    330     // timers
    331     WinTimerVec timerVec;
    332     WinTimerDict timerDict;
    333     void registerTimer(WinTimerInfo *t);
    334     void unregisterTimer(WinTimerInfo *t);
    335     void sendTimerEvent(int timerId);
    336 
    337     // socket notifiers
    338     QSNDict sn_read;
    339     QSNDict sn_write;
    340     QSNDict sn_except;
    341     void doWsaAsyncSelect(int socket);
    342 
    343     // event notifier
    344     QWinEventNotifier wakeUpNotifier;
    345 
    346     QList<QWinEventNotifier *> winEventNotifierList;
    347     void activateEventNotifier(QWinEventNotifier * wen);
    348 
    349     QList<MSG> queuedUserInputEvents;
    350     QList<MSG> queuedSocketEvents;
     319// @todo later
     320//  DWORD threadId;
     321//
     322//  bool interrupt;
     323//
     324//  // internal window handle used for socketnotifiers/timers/etc
     325//  HWND internalHwnd;
     326//
     327//  // timers
     328//  WinTimerVec timerVec;
     329//  WinTimerDict timerDict;
     330//  void registerTimer(WinTimerInfo *t);
     331//  void unregisterTimer(WinTimerInfo *t);
     332//  void sendTimerEvent(int timerId);
     333//
     334//  // socket notifiers
     335//  QSNDict sn_read;
     336//  QSNDict sn_write;
     337//  QSNDict sn_except;
     338//  void doWsaAsyncSelect(int socket);
     339//
     340//  QList<QMSG> queuedUserInputEvents;
     341//  QList<QMSG> queuedSocketEvents;
    351342};
    352343
    353 QEventDispatcherWin32Private::QEventDispatcherWin32Private()
    354     : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0)
    355 {
    356     resolveTimerAPI();
    357 
    358     wakeUpNotifier.setHandle(QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0),
    359                                           CreateEventA(0, FALSE, FALSE, 0)));
    360     if (!wakeUpNotifier.handle())
    361         qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed");
    362 }
    363 
    364 QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
    365 {
    366     wakeUpNotifier.setEnabled(false);
    367     CloseHandle(wakeUpNotifier.handle());
    368     if (internalHwnd)
    369         DestroyWindow(internalHwnd);
    370     QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc));
    371 #if !defined(Q_OS_WINCE)
    372     UnregisterClassA(className.constData(), qWinAppInst());
    373 #else
    374     UnregisterClassW(reinterpret_cast<const wchar_t *> (QString::fromLatin1(className.constData()).utf16())
    375                      , qWinAppInst());
    376 #endif
    377 }
    378 
    379 void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
    380 {
    381     QEvent event(QEvent::WinEventAct);
    382     QCoreApplication::sendEvent(wen, &event);
    383 }
    384 
    385 
    386 Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
    387                      UINT wMsgFilterMax, UINT wRemoveMsg)
    388 {
    389     QT_WA({ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } ,
    390           { return PeekMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); });
    391 }
    392 
    393 Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    394 {
    395     QT_WA({ return PostMessage(hWnd, msg, wParam, lParam); } ,
    396           { return PostMessageA(hWnd, msg, wParam, lParam); });
    397 }
    398 
    399 Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
    400                      UINT wMsgFilterMax)
    401 {
    402     QT_WA({ return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax); } ,
    403           { return GetMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax); });
    404 }
    405 
    406 // This function is called by a workerthread
    407 void WINAPI CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
    408 {
    409     if (!timerId) // sanity check
    410         return;
    411     WinTimerInfo *t = (WinTimerInfo*)user;
    412     Q_ASSERT(t);
    413     QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
    414 }
     344QEventDispatcherPMPrivate::QEventDispatcherPMPrivate()
     345    : hab(NULLHANDLE), hmq(NULLHANDLE), interrupt(false)
     346{
     347}
     348
     349QEventDispatcherPMPrivate::~QEventDispatcherPMPrivate()
     350{
     351    auxWnd.setDispatcher(0);
     352    auxWnd.destroy();
     353    if (hmq != NULLHANDLE) {
     354        WinDestroyMsgQueue(hmq);
     355        WinTerminate(hab);
     356    }
     357}
     358
     359void QEventDispatcherPMPrivate::createMsgQueue()
     360{
     361    if (hmq == NULLHANDLE) {
     362        // first, dynamically switch ("morph") to PM mode if we have been
     363        // compiled as the console application. This is necessary to create the
     364        // event queue, windows and other PM resources. As a side effect, the
     365        // console remains attached after morphing which can be useful for
     366        // debugging
     367        PPIB ppib;
     368        DosGetInfoBlocks(NULL, &ppib);
     369        if (ppib->pib_ultype != 3)
     370            ppib->pib_ultype = 3;
     371        // then create the message queue
     372        hab = WinInitialize(0);
     373        hmq = WinCreateMsgQueue(hab, 0);
     374        if (hmq == NULLHANDLE)
     375            qWarning("QEventDispatcherPMPrivate::createMsgQueue: "
     376                     "WinCreateMsgQueue failed with 0x%08lX",
     377                     WinGetLastError(hab));
     378    }
     379}
     380
     381void QEventDispatcherPMPrivate::createAuxWnd()
     382{
     383    if (auxWnd.hwnd() == NULLHANDLE) {
     384        createMsgQueue();
     385        auxWnd.setDispatcher(this);
     386        auxWnd.create();
     387    }
     388}
     389
     390MRESULT QEventDispatcherPMPrivate::AuxWnd::message(ULONG msg, MPARAM mp1, MPARAM mp2)
     391{
     392    QMSG qmsg = { hwnd(), msg, mp1, mp2 };
     393
     394    QCoreApplication *app = QCoreApplication::instance();
     395    MRESULT result;
     396    if (app && app->filterEvent(&qmsg, reinterpret_cast<long *>(&result)))
     397        return result;
     398
     399    switch (msg) {
     400        case WM_U_SEM_SELECT: {
     401// @todo later
     402//          if (eventLoop)
     403//              eventLoop->activateSocketNotifiers();
     404            break;
     405        }
     406        case WM_U_SEM_ZEROTIMER: {
     407// @todo later
     408//          if (numZeroTimers) {
     409//              activateZeroTimers();
     410//              // repost the message if there are still zero timers left
     411//              if (numZeroTimers)
     412//                  WinPostMsg(hwnd(), WM_U_SEM_ZEROTIMER, 0, 0);
     413//          }
     414            break;
     415        }
     416        case WM_TIMER: {
     417// @todo later
     418//          USHORT id = SHORT1FROMMP(mp1);
     419//          dispatchTimer((uint) id, &qmsg);
     420            break;
     421        }
     422    }
     423
     424    return FALSE;
     425}
     426
     427// @todo remove
     428#if 0
    415429
    416430LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
     
    450464
    451465    #ifdef GWLP_USERDATA
    452             QEventDispatcherWin32 *eventDispatcher =
    453                 (QEventDispatcherWin32 *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
     466            QEventDispatcher *eventDispatcher =
     467                (QEventDispatcher *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
    454468    #else
    455             QEventDispatcherWin32 *eventDispatcher =
    456                 (QEventDispatcherWin32 *) GetWindowLongA(hwnd, GWL_USERDATA);
     469            QEventDispatcher *eventDispatcher =
     470                (QEventDispatcher *) GetWindowLongA(hwnd, GWL_USERDATA);
    457471    #endif
    458472            if (eventDispatcher) {
    459                 QEventDispatcherWin32Private *d = eventDispatcher->d_func();
     473                QEventDispatcherPrivate *d = eventDispatcher->d_func();
    460474                QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
    461475                QSNDict *dict = sn_vec[type];
     
    489503            return result;
    490504
    491         QEventDispatcherWin32 *eventDispatcher =
    492             qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
     505        QEventDispatcher *eventDispatcher =
     506            qobject_cast<QEventDispatcher *>(QAbstractEventDispatcher::instance());
    493507        Q_ASSERT(eventDispatcher != 0);
    494         QEventDispatcherWin32Private *d = eventDispatcher->d_func();
     508        QEventDispatcherPrivate *d = eventDispatcher->d_func();
    495509        d->sendTimerEvent(wp);
    496510        return 0;
     
    500514}
    501515
    502 static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
    503 {
    504     HINSTANCE hi = qWinAppInst();
    505 #if defined(Q_OS_WINCE)
    506     WNDCLASS wc;
    507 #else
    508     WNDCLASSA wc;
    509 #endif
    510     wc.style = 0;
    511     wc.lpfnWndProc = qt_internal_proc;
    512     wc.cbClsExtra = 0;
    513     wc.cbWndExtra = 0;
    514     wc.hInstance = hi;
    515     wc.hIcon = 0;
    516     wc.hCursor = 0;
    517     wc.hbrBackground = 0;
    518     wc.lpszMenuName = NULL;
    519 
    520     // make sure that multiple Qt's can coexist in the same process
    521     QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc));
    522 #if defined(Q_OS_WINCE)
    523     QString tmp = QString::fromLatin1(className.data());
    524     wc.lpszClassName = reinterpret_cast<const wchar_t *> (tmp.utf16());
    525     RegisterClass(&wc);
    526     HWND wnd = CreateWindow(wc.lpszClassName,  // classname
    527                              wc.lpszClassName,  // window name
    528                              0,                 // style
    529                              0, 0, 0, 0,        // geometry
    530                              0,                 // parent
    531                              0,                 // menu handle
    532                              hi,                // application
    533                              0);                // windows creation data.
    534 #else
    535     wc.lpszClassName = className.constData();
    536     RegisterClassA(&wc);
    537     HWND wnd = CreateWindowA(wc.lpszClassName,  // classname
    538                              wc.lpszClassName,  // window name
    539                              0,                 // style
    540                              0, 0, 0, 0,        // geometry
    541                              0,                 // parent
    542                              0,                 // menu handle
    543                              hi,                // application
    544                              0);                // windows creation data.
    545 #endif
    546 
    547 
    548 #ifdef GWLP_USERDATA
    549     SetWindowLongPtrA(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
    550 #else
    551     SetWindowLongA(wnd, GWL_USERDATA, (LONG)eventDispatcher);
    552 #endif
    553 
    554     if (!wnd) {
    555         qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
    556     }
    557     return wnd;
    558 }
    559 
    560 void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
     516void QEventDispatcherPMPrivate::registerTimer(WinTimerInfo *t)
    561517{
    562518    Q_ASSERT(internalHwnd);
    563519
    564     Q_Q(QEventDispatcherWin32);
     520    Q_Q(QEventDispatcher);
    565521
    566522    int ok = 0;
     
    581537
    582538    if (ok == 0)
    583         qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
    584 }
    585 
    586 void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t)
     539        qErrnoWarning("QEventDispatcher::registerTimer: Failed to create a timer");
     540}
     541
     542void QEventDispatcherPrivate::unregisterTimer(WinTimerInfo *t)
    587543{
    588544    // mark timer as unused
     
    601557}
    602558
    603 void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
     559void QEventDispatcherPrivate::sendTimerEvent(int timerId)
    604560{
    605561    WinTimerInfo *t = timerDict.value(timerId);
     
    619575}
    620576
    621 void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
     577void QEventDispatcherPrivate::doWsaAsyncSelect(int socket)
    622578{
    623579    Q_ASSERT(internalHwnd);
     
    634590}
    635591
    636 void QEventDispatcherWin32::createInternalHwnd()
    637 {
    638     Q_D(QEventDispatcherWin32);
     592void QEventDispatcher::createInternalHwnd()
     593{
     594    Q_D(QEventDispatcher);
    639595
    640596    Q_ASSERT(!d->internalHwnd);
     
    655611}
    656612
    657 QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
    658     : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
    659 {
    660 }
    661 
    662 QEventDispatcherWin32::~QEventDispatcherWin32()
    663 {
    664 }
    665 
    666 bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
    667 {
    668     Q_D(QEventDispatcherWin32);
    669 
     613#endif
     614
     615QEventDispatcherPM::QEventDispatcherPM(QObject *parent)
     616    : QAbstractEventDispatcher(*new QEventDispatcherPMPrivate, parent)
     617{
     618}
     619
     620QEventDispatcherPM::~QEventDispatcherPM()
     621{
     622}
     623
     624bool QEventDispatcherPM::processEvents(QEventLoop::ProcessEventsFlags flags)
     625{
     626    Q_D(QEventDispatcherPM);
     627
     628// @todo later
     629#if 0
    670630    if (!d->internalHwnd)
    671631        createInternalHwnd();
     
    683643        QVarLengthArray<MSG> processedTimers;
    684644        while (!d->interrupt) {
    685             DWORD nCount = d->winEventNotifierList.count();
    686             Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
    687 
    688645            MSG msg;
    689646            bool haveMessage;
     
    716673                }
    717674            }
    718             if (!haveMessage) {
    719                 // no message - check for signalled objects
    720                 for (int i=0; i<(int)nCount; i++)
    721                     pHandles[i] = d->winEventNotifierList.at(i)->handle();
    722                 waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
    723                 if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
    724                     // a new message has arrived, process it
    725                     continue;
    726                 }
    727             }
    728675            if (haveMessage) {
    729676                if (msg.message == WM_TIMER) {
     
    751698                    });
    752699                }
    753             } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
    754                 d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
    755700            } else {
    756701                // nothing todo so break
     
    767712                   && (flags & QEventLoop::WaitForMoreEvents));
    768713        if (canWait) {
    769             DWORD nCount = d->winEventNotifierList.count();
    770             Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
    771             for (int i=0; i<(int)nCount; i++)
    772                 pHandles[i] = d->winEventNotifierList.at(i)->handle();
    773 
    774714            emit aboutToBlock();
    775             waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
     715            waitRet = (nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
    776716            emit awake();
    777             if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
    778                 d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
    779                 retVal = true;
    780             }
    781717        }
    782718    } while (canWait);
    783719
    784720    return retVal;
    785 }
    786 
    787 bool QEventDispatcherWin32::hasPendingEvents()
    788 {
    789     MSG msg;
    790     return qGlobalPostedEventsCount() || winPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
    791 }
    792 
    793 void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
    794 {
     721#else
     722    return false;
     723#endif
     724}
     725
     726bool QEventDispatcherPM::hasPendingEvents()
     727{
     728    QMSG msg;
     729    return qGlobalPostedEventsCount() || WinPeekMsg(0, &msg, NULL, 0, 0, PM_NOREMOVE);
     730}
     731
     732void QEventDispatcherPM::registerSocketNotifier(QSocketNotifier *notifier)
     733{
     734// @todo later
     735#if 0
    795736    Q_ASSERT(notifier);
    796737    int sockfd = notifier->socket();
     
    806747#endif
    807748
    808     Q_D(QEventDispatcherWin32);
     749    Q_D(QEventDispatcher);
    809750    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
    810751    QSNDict *dict = sn_vec[type];
     
    827768    if (d->internalHwnd)
    828769        d->doWsaAsyncSelect(sockfd);
    829 }
    830 
    831 void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
    832 {
     770#endif
     771}
     772
     773void QEventDispatcherPM::unregisterSocketNotifier(QSocketNotifier *notifier)
     774{
     775// @todo later
     776#if 0
    833777    Q_ASSERT(notifier);
    834778    int sockfd = notifier->socket();
     
    844788#endif
    845789
    846     Q_D(QEventDispatcherWin32);
     790    Q_D(QEventDispatcher);
    847791    QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
    848792    QSNDict *dict = sn_vec[type];
     
    856800    if (d->internalHwnd)
    857801        d->doWsaAsyncSelect(sockfd);
    858 }
    859 
    860 void QEventDispatcherWin32::registerTimer(int timerId, int interval, QObject *object)
    861 {
     802#endif
     803}
     804
     805void QEventDispatcherPM::registerTimer(int timerId, int interval, QObject *object)
     806{
     807// @todo later
     808#if 0
    862809    if (timerId < 1 || interval < 0 || !object) {
    863         qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
     810        qWarning("QEventDispatcher::registerTimer: invalid arguments");
    864811        return;
    865812    } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
     
    868815    }
    869816
    870     Q_D(QEventDispatcherWin32);
     817    Q_D(QEventDispatcher);
    871818
    872819    register WinTimerInfo *t = new WinTimerInfo;
     
    883830    d->timerVec.append(t);                      // store in timer vector
    884831    d->timerDict.insert(t->timerId, t);          // store timers in dict
    885 }
    886 
    887 bool QEventDispatcherWin32::unregisterTimer(int timerId)
    888 {
     832#endif
     833}
     834
     835bool QEventDispatcherPM::unregisterTimer(int timerId)
     836{
     837// @todo later
     838#if 0
    889839    if (timerId < 1) {
    890         qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
     840        qWarning("QEventDispatcher::unregisterTimer: invalid argument");
    891841        return false;
    892842    }
     
    897847    }
    898848
    899     Q_D(QEventDispatcherWin32);
     849    Q_D(QEventDispatcher);
    900850    if (d->timerVec.isEmpty() || timerId <= 0)
    901851        return false;
     
    909859    d->unregisterTimer(t);
    910860    return true;
    911 }
    912 
    913 bool QEventDispatcherWin32::unregisterTimers(QObject *object)
    914 {
     861#else
     862    return false;
     863#endif
     864}
     865
     866bool QEventDispatcherPM::unregisterTimers(QObject *object)
     867{
     868// @todo later
     869#if 0
    915870    if (!object) {
    916         qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument");
     871        qWarning("QEventDispatcher::unregisterTimers: invalid argument");
    917872        return false;
    918873    }
     
    923878    }
    924879
    925     Q_D(QEventDispatcherWin32);
     880    Q_D(QEventDispatcher);
    926881    if (d->timerVec.isEmpty())
    927882        return false;
     
    937892    }
    938893    return true;
    939 }
    940 
    941 QList<QEventDispatcherWin32::TimerInfo>
    942 QEventDispatcherWin32::registeredTimers(QObject *object) const
    943 {
     894#else
     895    return false;
     896#endif
     897}
     898
     899QList<QEventDispatcherPM::TimerInfo>
     900QEventDispatcherPM::registeredTimers(QObject *object) const
     901{
     902// @todo later
     903#if 0
    944904    if (!object) {
    945         qWarning("QEventDispatcherWin32:registeredTimers: invalid argument");
     905        qWarning("QEventDispatcher:registeredTimers: invalid argument");
    946906        return QList<TimerInfo>();
    947907    }
    948908
    949     Q_D(const QEventDispatcherWin32);
     909    Q_D(const QEventDispatcher);
    950910    QList<TimerInfo> list;
    951911    for (int i = 0; i < d->timerVec.size(); ++i) {
     
    955915    }
    956916    return list;
    957 }
    958 
    959 bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
    960 {
    961     if (!notifier) {
    962         qWarning("QWinEventNotifier: Internal error");
    963         return false;
    964     } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
    965         qWarning("QWinEventNotifier: event notifiers cannot be enabled from another thread");
    966         return false;
    967     }
    968 
    969     Q_D(QEventDispatcherWin32);
    970 
    971     if (d->winEventNotifierList.contains(notifier))
    972         return true;
    973 
    974     if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) {
    975         qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2);
    976         return false;
    977     }
    978     d->winEventNotifierList.append(notifier);
    979     return true;
    980 }
    981 
    982 void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
    983 {
    984     if (!notifier) {
    985         qWarning("QWinEventNotifier: Internal error");
    986         return;
    987     } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
    988         qWarning("QWinEventNotifier: event notifiers cannot be disabled from another thread");
    989         return;
    990     }
    991 
    992     Q_D(QEventDispatcherWin32);
    993 
    994     int i = d->winEventNotifierList.indexOf(notifier);
    995     if (i != -1)
    996         d->winEventNotifierList.takeAt(i);
    997 }
    998 
    999 void QEventDispatcherWin32::activateEventNotifiers()
    1000 {
    1001     Q_D(QEventDispatcherWin32);
    1002     //### this could break if events are removed/added in the activation
    1003     for (int i=0; i<d->winEventNotifierList.count(); i++) {
    1004 #if !defined(Q_OS_WINCE)
    1005         if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
    1006             d->activateEventNotifier(d->winEventNotifierList.at(i));
    1007917#else
    1008         if (WaitForSingleObject(d->winEventNotifierList.at(i)->handle(), 0) == WAIT_OBJECT_0)
    1009             d->activateEventNotifier(d->winEventNotifierList.at(i));
    1010 #endif
    1011     }
    1012 }
    1013 
    1014 void QEventDispatcherWin32::wakeUp()
    1015 {
    1016     Q_D(QEventDispatcherWin32);
    1017     SetEvent(d->wakeUpNotifier.handle());
    1018 }
    1019 
    1020 void QEventDispatcherWin32::interrupt()
    1021 {
    1022     Q_D(QEventDispatcherWin32);
     918    return QList<TimerInfo>();
     919#endif
     920}
     921
     922void QEventDispatcherPM::wakeUp()
     923{
     924    Q_D(QEventDispatcherPM);
     925    PTIB ptib;
     926    DosGetInfoBlocks(&ptib, NULL);
     927    MQINFO mqinfo;
     928    WinQueryQueueInfo(d->hmq, &mqinfo, sizeof(MQINFO));
     929    if (ptib->tib_ptib2->tib2_ultid != mqinfo.tid)
     930        WinPostQueueMsg(d->hmq, WM_NULL, 0, 0);
     931}
     932
     933void QEventDispatcherPM::interrupt()
     934{
     935    Q_D(QEventDispatcherPM);
    1023936    d->interrupt = true;
    1024937    wakeUp();
    1025938}
    1026939
    1027 void QEventDispatcherWin32::flush()
    1028 { }
    1029 
    1030 
    1031 void QEventDispatcherWin32::startingUp()
    1032 {
    1033     Q_D(QEventDispatcherWin32);
    1034 
    1035     if (d->wakeUpNotifier.handle()) d->wakeUpNotifier.setEnabled(true);
    1036 }
    1037 
    1038 void QEventDispatcherWin32::closingDown()
    1039 {
    1040     Q_D(QEventDispatcherWin32);
    1041 
     940void QEventDispatcherPM::flush()
     941{
     942}
     943
     944void QEventDispatcherPM::startingUp()
     945{
     946}
     947
     948void QEventDispatcherPM::closingDown()
     949{
     950    Q_D(QEventDispatcherPM);
     951
     952// @todo remove later
     953#if 0
    1042954    // clean up any socketnotifiers
    1043955    while (!d->sn_read.isEmpty())
     
    1051963    while (!d->timerDict.isEmpty())
    1052964        unregisterTimer((*(d->timerDict.begin()))->timerId);
    1053 }
    1054 
    1055 bool QEventDispatcherWin32::event(QEvent *e)
    1056 {
    1057     Q_D(QEventDispatcherWin32);
     965#endif
     966}
     967
     968// @todo remove later
     969#if 0
     970bool QEventDispatcherPM::event(QEvent *e)
     971{
     972    Q_D(QEventDispatcherPM);
    1058973    if (e->type() == QEvent::ZeroTimerEvent) {
    1059974        QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
     
    1082997    return QAbstractEventDispatcher::event(e);
    1083998}
     999
    10841000
    10851001QT_END_NAMESPACE
  • trunk/src/corelib/kernel/qeventdispatcher_pm_p.h

    r63 r67  
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    44** Contact: Qt Software Information ([email protected])
     5
     6
    57**
    68** This file is part of the QtCore module of the Qt Toolkit.
     
    4042****************************************************************************/
    4143
    42 #ifndef QEVENTDISPATCHER_WIN_P_H
    43 #define QEVENTDISPATCHER_WIN_P_H
     44#ifndef QEVENTDISPATCHER__P_H
     45#define QEVENTDISPATCHER__P_H
    4446
    4547//
     
    5557
    5658#include "QtCore/qabstracteventdispatcher.h"
    57 #include "QtCore/qt_windows.h"
     59#include "QtCore/qt_.h"
    5860
    5961QT_BEGIN_NAMESPACE
    6062
    61 class QWinEventNotifier;
    62 class QEventDispatcherWin32Private;
     63class QEventDispatcherPMPrivate;
    6364
    64 // forward declaration
    65 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
    66 
    67 class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
     65class Q_CORE_EXPORT QEventDispatcherPM : public QAbstractEventDispatcher
    6866{
    6967    Q_OBJECT
    70     Q_DECLARE_PRIVATE(QEventDispatcherWin32)
     68    Q_DECLARE_PRIVATE(QEventDispatcher)
    7169
    72     void createInternalHwnd();
    73     friend class QGuiEventDispatcherWin32;
     70    friend class QGuiEventDispatcherPM;
    7471
    7572public:
    76     explicit QEventDispatcherWin32(QObject *parent = 0);
    77     ~QEventDispatcherWin32();
     73    explicit QEventDispatcher(QObject *parent = 0);
     74    ~QEventDispatcher();
    7875
    7976    bool processEvents(QEventLoop::ProcessEventsFlags flags);
     
    8885    QList<TimerInfo> registeredTimers(QObject *object) const;
    8986
    90     bool registerEventNotifier(QWinEventNotifier *notifier);
    91     void unregisterEventNotifier(QWinEventNotifier *notifier);
    92     void activateEventNotifiers();
    93 
    9487    void wakeUp();
    9588    void interrupt();
     
    9992    void closingDown();
    10093
    101     bool event(QEvent *e);
    102 
    103 private:
    104     friend LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
     94// @todo remove later
     95//  bool event(QEvent *e);
    10596};
    10697
Note: See TracChangeset for help on using the changeset viewer.