Changeset 67 for trunk/src/corelib/kernel
- Timestamp:
- Jul 4, 2009, 2:13:09 PM (16 years ago)
- Location:
- trunk/src/corelib/kernel
- Files:
-
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/kernel/qeventdispatcher_pm.cpp
r63 r67 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** Contact: Qt Software Information ([email protected]) 5 6 5 7 ** 6 8 ** This file is part of the QtCore module of the Qt Toolkit. … … 40 42 ****************************************************************************/ 41 43 42 #include "qeventdispatcher_ win_p.h"44 #include "qeventdispatcher__p.h" 43 45 44 46 #include "qcoreapplication.h" … … 49 51 #include "qsocketnotifier.h" 50 52 #include "qvarlengtharray.h" 51 #include "qwineventnotifier_p.h"52 53 53 54 #include "qabstracteventdispatcher_p.h" 54 55 #include "qcoreapplication_p.h" 56 55 57 #include <private/qthread_p.h> 56 58 #include <private/qmutexpool_p.h> 57 59 60 61 58 62 QT_BEGIN_NAMESPACE 59 63 60 HINSTANCE qWinAppInst();61 64 extern uint qGlobalPostedEventsCount(); 62 65 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; 66 class QEventDispatcherPMPrivate; 67 68 // @todo later: timers 69 #if 0 262 70 263 71 struct WinTimerInfo { // internal timer info … … 313 121 } 314 122 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 156 static 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 */ 170 QPMObjectWindow::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 */ 181 QPMObjectWindow::~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 */ 195 bool 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 */ 226 bool 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 239 MRESULT 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 288 class QEventDispatcherPMPrivate : public QAbstractEventDispatcherPrivate 289 { 290 Q_DECLARE_PUBLIC(QEventDispatcherPM) 319 291 public: 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; 324 316 325 317 bool interrupt; 326 318 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; 351 342 }; 352 343 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 } 344 QEventDispatcherPMPrivate::QEventDispatcherPMPrivate() 345 : hab(NULLHANDLE), hmq(NULLHANDLE), interrupt(false) 346 { 347 } 348 349 QEventDispatcherPMPrivate::~QEventDispatcherPMPrivate() 350 { 351 auxWnd.setDispatcher(0); 352 auxWnd.destroy(); 353 if (hmq != NULLHANDLE) { 354 WinDestroyMsgQueue(hmq); 355 WinTerminate(hab); 356 } 357 } 358 359 void 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 381 void QEventDispatcherPMPrivate::createAuxWnd() 382 { 383 if (auxWnd.hwnd() == NULLHANDLE) { 384 createMsgQueue(); 385 auxWnd.setDispatcher(this); 386 auxWnd.create(); 387 } 388 } 389 390 MRESULT 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 415 429 416 430 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) … … 450 464 451 465 #ifdef GWLP_USERDATA 452 QEventDispatcher Win32*eventDispatcher =453 (QEventDispatcher Win32*) GetWindowLongPtrA(hwnd, GWLP_USERDATA);466 QEventDispatcher *eventDispatcher = 467 (QEventDispatcher *) GetWindowLongPtrA(hwnd, GWLP_USERDATA); 454 468 #else 455 QEventDispatcher Win32*eventDispatcher =456 (QEventDispatcher Win32*) GetWindowLongA(hwnd, GWL_USERDATA);469 QEventDispatcher *eventDispatcher = 470 (QEventDispatcher *) GetWindowLongA(hwnd, GWL_USERDATA); 457 471 #endif 458 472 if (eventDispatcher) { 459 QEventDispatcher Win32Private *d = eventDispatcher->d_func();473 QEventDispatcherPrivate *d = eventDispatcher->d_func(); 460 474 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; 461 475 QSNDict *dict = sn_vec[type]; … … 489 503 return result; 490 504 491 QEventDispatcher Win32*eventDispatcher =492 qobject_cast<QEventDispatcher Win32*>(QAbstractEventDispatcher::instance());505 QEventDispatcher *eventDispatcher = 506 qobject_cast<QEventDispatcher *>(QAbstractEventDispatcher::instance()); 493 507 Q_ASSERT(eventDispatcher != 0); 494 QEventDispatcher Win32Private *d = eventDispatcher->d_func();508 QEventDispatcherPrivate *d = eventDispatcher->d_func(); 495 509 d->sendTimerEvent(wp); 496 510 return 0; … … 500 514 } 501 515 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) 516 void QEventDispatcherPMPrivate::registerTimer(WinTimerInfo *t) 561 517 { 562 518 Q_ASSERT(internalHwnd); 563 519 564 Q_Q(QEventDispatcher Win32);520 Q_Q(QEventDispatcher); 565 521 566 522 int ok = 0; … … 581 537 582 538 if (ok == 0) 583 qErrnoWarning("QEventDispatcher Win32::registerTimer: Failed to create a timer");584 } 585 586 void QEventDispatcher Win32Private::unregisterTimer(WinTimerInfo *t)539 qErrnoWarning("QEventDispatcher::registerTimer: Failed to create a timer"); 540 } 541 542 void QEventDispatcherPrivate::unregisterTimer(WinTimerInfo *t) 587 543 { 588 544 // mark timer as unused … … 601 557 } 602 558 603 void QEventDispatcher Win32Private::sendTimerEvent(int timerId)559 void QEventDispatcherPrivate::sendTimerEvent(int timerId) 604 560 { 605 561 WinTimerInfo *t = timerDict.value(timerId); … … 619 575 } 620 576 621 void QEventDispatcher Win32Private::doWsaAsyncSelect(int socket)577 void QEventDispatcherPrivate::doWsaAsyncSelect(int socket) 622 578 { 623 579 Q_ASSERT(internalHwnd); … … 634 590 } 635 591 636 void QEventDispatcher Win32::createInternalHwnd()637 { 638 Q_D(QEventDispatcher Win32);592 void QEventDispatcher::createInternalHwnd() 593 { 594 Q_D(QEventDispatcher); 639 595 640 596 Q_ASSERT(!d->internalHwnd); … … 655 611 } 656 612 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 615 QEventDispatcherPM::QEventDispatcherPM(QObject *parent) 616 : QAbstractEventDispatcher(*new QEventDispatcherPMPrivate, parent) 617 { 618 } 619 620 QEventDispatcherPM::~QEventDispatcherPM() 621 { 622 } 623 624 bool QEventDispatcherPM::processEvents(QEventLoop::ProcessEventsFlags flags) 625 { 626 Q_D(QEventDispatcherPM); 627 628 // @todo later 629 #if 0 670 630 if (!d->internalHwnd) 671 631 createInternalHwnd(); … … 683 643 QVarLengthArray<MSG> processedTimers; 684 644 while (!d->interrupt) { 685 DWORD nCount = d->winEventNotifierList.count();686 Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);687 688 645 MSG msg; 689 646 bool haveMessage; … … 716 673 } 717 674 } 718 if (!haveMessage) {719 // no message - check for signalled objects720 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 it725 continue;726 }727 }728 675 if (haveMessage) { 729 676 if (msg.message == WM_TIMER) { … … 751 698 }); 752 699 } 753 } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {754 d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));755 700 } else { 756 701 // nothing todo so break … … 767 712 && (flags & QEventLoop::WaitForMoreEvents)); 768 713 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 774 714 emit aboutToBlock(); 775 waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);715 waitRet = (nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE); 776 716 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 }781 717 } 782 718 } while (canWait); 783 719 784 720 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 726 bool QEventDispatcherPM::hasPendingEvents() 727 { 728 QMSG msg; 729 return qGlobalPostedEventsCount() || WinPeekMsg(0, &msg, NULL, 0, 0, PM_NOREMOVE); 730 } 731 732 void QEventDispatcherPM::registerSocketNotifier(QSocketNotifier *notifier) 733 { 734 // @todo later 735 #if 0 795 736 Q_ASSERT(notifier); 796 737 int sockfd = notifier->socket(); … … 806 747 #endif 807 748 808 Q_D(QEventDispatcher Win32);749 Q_D(QEventDispatcher); 809 750 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; 810 751 QSNDict *dict = sn_vec[type]; … … 827 768 if (d->internalHwnd) 828 769 d->doWsaAsyncSelect(sockfd); 829 } 830 831 void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) 832 { 770 #endif 771 } 772 773 void QEventDispatcherPM::unregisterSocketNotifier(QSocketNotifier *notifier) 774 { 775 // @todo later 776 #if 0 833 777 Q_ASSERT(notifier); 834 778 int sockfd = notifier->socket(); … … 844 788 #endif 845 789 846 Q_D(QEventDispatcher Win32);790 Q_D(QEventDispatcher); 847 791 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; 848 792 QSNDict *dict = sn_vec[type]; … … 856 800 if (d->internalHwnd) 857 801 d->doWsaAsyncSelect(sockfd); 858 } 859 860 void QEventDispatcherWin32::registerTimer(int timerId, int interval, QObject *object) 861 { 802 #endif 803 } 804 805 void QEventDispatcherPM::registerTimer(int timerId, int interval, QObject *object) 806 { 807 // @todo later 808 #if 0 862 809 if (timerId < 1 || interval < 0 || !object) { 863 qWarning("QEventDispatcher Win32::registerTimer: invalid arguments");810 qWarning("QEventDispatcher::registerTimer: invalid arguments"); 864 811 return; 865 812 } else if (object->thread() != thread() || thread() != QThread::currentThread()) { … … 868 815 } 869 816 870 Q_D(QEventDispatcher Win32);817 Q_D(QEventDispatcher); 871 818 872 819 register WinTimerInfo *t = new WinTimerInfo; … … 883 830 d->timerVec.append(t); // store in timer vector 884 831 d->timerDict.insert(t->timerId, t); // store timers in dict 885 } 886 887 bool QEventDispatcherWin32::unregisterTimer(int timerId) 888 { 832 #endif 833 } 834 835 bool QEventDispatcherPM::unregisterTimer(int timerId) 836 { 837 // @todo later 838 #if 0 889 839 if (timerId < 1) { 890 qWarning("QEventDispatcher Win32::unregisterTimer: invalid argument");840 qWarning("QEventDispatcher::unregisterTimer: invalid argument"); 891 841 return false; 892 842 } … … 897 847 } 898 848 899 Q_D(QEventDispatcher Win32);849 Q_D(QEventDispatcher); 900 850 if (d->timerVec.isEmpty() || timerId <= 0) 901 851 return false; … … 909 859 d->unregisterTimer(t); 910 860 return true; 911 } 912 913 bool QEventDispatcherWin32::unregisterTimers(QObject *object) 914 { 861 #else 862 return false; 863 #endif 864 } 865 866 bool QEventDispatcherPM::unregisterTimers(QObject *object) 867 { 868 // @todo later 869 #if 0 915 870 if (!object) { 916 qWarning("QEventDispatcher Win32::unregisterTimers: invalid argument");871 qWarning("QEventDispatcher::unregisterTimers: invalid argument"); 917 872 return false; 918 873 } … … 923 878 } 924 879 925 Q_D(QEventDispatcher Win32);880 Q_D(QEventDispatcher); 926 881 if (d->timerVec.isEmpty()) 927 882 return false; … … 937 892 } 938 893 return true; 939 } 940 941 QList<QEventDispatcherWin32::TimerInfo> 942 QEventDispatcherWin32::registeredTimers(QObject *object) const 943 { 894 #else 895 return false; 896 #endif 897 } 898 899 QList<QEventDispatcherPM::TimerInfo> 900 QEventDispatcherPM::registeredTimers(QObject *object) const 901 { 902 // @todo later 903 #if 0 944 904 if (!object) { 945 qWarning("QEventDispatcher Win32:registeredTimers: invalid argument");905 qWarning("QEventDispatcher:registeredTimers: invalid argument"); 946 906 return QList<TimerInfo>(); 947 907 } 948 908 949 Q_D(const QEventDispatcher Win32);909 Q_D(const QEventDispatcher); 950 910 QList<TimerInfo> list; 951 911 for (int i = 0; i < d->timerVec.size(); ++i) { … … 955 915 } 956 916 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 activation1003 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));1007 917 #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 922 void 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 933 void QEventDispatcherPM::interrupt() 934 { 935 Q_D(QEventDispatcherPM); 1023 936 d->interrupt = true; 1024 937 wakeUp(); 1025 938 } 1026 939 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 940 void QEventDispatcherPM::flush() 941 { 942 } 943 944 void QEventDispatcherPM::startingUp() 945 { 946 } 947 948 void QEventDispatcherPM::closingDown() 949 { 950 Q_D(QEventDispatcherPM); 951 952 // @todo remove later 953 #if 0 1042 954 // clean up any socketnotifiers 1043 955 while (!d->sn_read.isEmpty()) … … 1051 963 while (!d->timerDict.isEmpty()) 1052 964 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 970 bool QEventDispatcherPM::event(QEvent *e) 971 { 972 Q_D(QEventDispatcherPM); 1058 973 if (e->type() == QEvent::ZeroTimerEvent) { 1059 974 QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e); … … 1082 997 return QAbstractEventDispatcher::event(e); 1083 998 } 999 1084 1000 1085 1001 QT_END_NAMESPACE -
trunk/src/corelib/kernel/qeventdispatcher_pm_p.h
r63 r67 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** Contact: Qt Software Information ([email protected]) 5 6 5 7 ** 6 8 ** This file is part of the QtCore module of the Qt Toolkit. … … 40 42 ****************************************************************************/ 41 43 42 #ifndef QEVENTDISPATCHER_ WIN_P_H43 #define QEVENTDISPATCHER_ WIN_P_H44 #ifndef QEVENTDISPATCHER__P_H 45 #define QEVENTDISPATCHER__P_H 44 46 45 47 // … … 55 57 56 58 #include "QtCore/qabstracteventdispatcher.h" 57 #include "QtCore/qt_ windows.h"59 #include "QtCore/qt_.h" 58 60 59 61 QT_BEGIN_NAMESPACE 60 62 61 class QWinEventNotifier; 62 class QEventDispatcherWin32Private; 63 class QEventDispatcherPMPrivate; 63 64 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 65 class Q_CORE_EXPORT QEventDispatcherPM : public QAbstractEventDispatcher 68 66 { 69 67 Q_OBJECT 70 Q_DECLARE_PRIVATE(QEventDispatcher Win32)68 Q_DECLARE_PRIVATE(QEventDispatcher) 71 69 72 void createInternalHwnd(); 73 friend class QGuiEventDispatcherWin32; 70 friend class QGuiEventDispatcherPM; 74 71 75 72 public: 76 explicit QEventDispatcher Win32(QObject *parent = 0);77 ~QEventDispatcher Win32();73 explicit QEventDispatcher(QObject *parent = 0); 74 ~QEventDispatcher(); 78 75 79 76 bool processEvents(QEventLoop::ProcessEventsFlags flags); … … 88 85 QList<TimerInfo> registeredTimers(QObject *object) const; 89 86 90 bool registerEventNotifier(QWinEventNotifier *notifier);91 void unregisterEventNotifier(QWinEventNotifier *notifier);92 void activateEventNotifiers();93 94 87 void wakeUp(); 95 88 void interrupt(); … … 99 92 void closingDown(); 100 93 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); 105 96 }; 106 97
Note:
See TracChangeset
for help on using the changeset viewer.