--- qeventdispatcher_win.cpp.org 2010-10-07 23:49:29.006076200 +0200 +++ qeventdispatcher_win.cpp 2010-10-11 06:22:25.585665000 +0200 @@ -97,6 +97,326 @@ #include QT_END_INCLUDE_NAMESPACE + + +#include +#include + +extern "C" +{ + void elog_add (char *msg, ...); +} + +#define ELOG_MAX 2048 +#define ELOG_MSG 64 +struct elog_data_entry_s +{ + char msg[ELOG_MSG]; +}; + +struct elog_data_s +{ + int idx; + + struct elog_data_entry_s *entry; +}; + +QThreadStorage elog_data; + +/* Logging infrastructure. */ +void +elog_add (char *msg, ...) +{ + struct elog_data_s *data; + va_list ap; + SYSTEMTIME stime; + int len; + + if (!elog_data.hasLocalData()) + { + data = (struct elog_data_s *) qMalloc (sizeof (struct elog_data_s)); + memset (data, 0x00, sizeof (struct elog_data_s)); + data->entry = (struct elog_data_entry_s *) qMalloc (ELOG_MAX * sizeof (struct elog_data_entry_s)); + printf ("@@@ ### @@@ Event log for thread 0x%x at %p/%p\n", GetCurrentThreadId(), data, data->entry); + elog_data.setLocalData(data); + } + else + data = elog_data.localData(); + + memset (&data->entry[data->idx], 0x00, sizeof (struct elog_data_entry_s)); + + GetLocalTime (&stime); + sprintf (data->entry[data->idx].msg, "%02i%02i%02i ", + stime.wHour, stime.wMinute, stime.wSecond); + len = strlen (data->entry[data->idx].msg); + va_start (ap, msg); + _vsnprintf (data->entry[data->idx].msg + len, ELOG_MSG - len, msg, ap); + va_end (ap); + + data->idx++; + if (data->idx == ELOG_MAX) + data->idx = 0; + + /* Mark the current position for easier human inspection. */ + memset (&data->entry[data->idx], 0xff, sizeof (struct elog_data_entry_s)); +} + + +static const char * +elog_msg_to_str (MSG *msg) +{ + switch (msg->message) + { + case WM_TOUCH: + return "WM_TOUCH"; +#ifndef QT_NO_GESTURES + case WM_GESTURE: + return "WM_GESTURES"; + case WM_GESTURENOTIFY: + return "WM_GESTURENOTIFY"; +#endif // QT_NO_GESTURES + case WM_QT_SOCKETNOTIFIER: + return "WM_QT_SOCKETNOTIFIER"; + case WM_QT_SENDPOSTEDEVENTS: + return "WM_QT_SENDPOSTEDEVENTS"; + case WM_APP: + return "WM_APP"; + case WM_ACTIVATE: + return "WM_ACTIVATE"; + case WM_CANCELMODE: + return "WM_CANCELMODE"; + case WM_CAPTURECHANGED: + return "WM_CAPTURECHANGED"; + case WM_CHAR: + return "WM_CHAR"; + case WM_CHARTOITEM: + return "WM_CHARTOITEM"; + case WM_CLEAR: + return "WM_CLEAR"; + case WM_CLOSE: + return "WM_CLOSE"; + case WM_COMMAND: + return "WM_COMMAND"; + case WM_COMPAREITEM: + return "WM_COMPAREITEM"; + case WM_CONTEXTMENU: + return "WM_CONTEXTMENU"; + case WM_COPY: + return "WM_COPY"; + case WM_COPYDATA: + return "WM_COPYDATA"; + case WM_CREATE: + return "WM_CREATE"; + case WM_CTLCOLORBTN: + return "WM_CTLCOLORBTN"; + case WM_CTLCOLORDLG: + return "WM_CTLCOLORDLG"; + case WM_CTLCOLOREDIT: + return "WM_CTLCOLOREDIT"; + case WM_CTLCOLORLISTBOX: + return "WM_CTLCOLORLISTBOX"; + case WM_CTLCOLORMSGBOX: + return "WM_CTLCOLORMSGBOX"; + case WM_CTLCOLORSCROLLBAR: + return "WM_CTLCOLORSCROLLBAR"; + case WM_CTLCOLORSTATIC: + return "WM_CTLCOLORSTATIC"; + case WM_CUT: + return "WM_CUT"; + case WM_DEADCHAR: + return "WM_DEADCHAR"; + case WM_DELETEITEM: + return "WM_DELETEITEM"; + case WM_DESTROY: + return "WM_DESTROY"; + case WM_DESTROYCLIPBOARD: + return "WM_DESTROYCLIPBOARD"; + case WM_DRAWITEM: + return "WM_DRAWITEM"; + case WM_ENABLE: + return "WM_ENABLE"; + case WM_ENTERIDLE: + return "WM_ENTERIDLE"; + case WM_ENTERMENULOOP: + return "WM_ENTERMENULOOP"; + case WM_ERASEBKGND: + return "WM_ERASEBKGND"; + case WM_EXITMENULOOP: + return "WM_EXITMENULOOP"; + case WM_FONTCHANGE: + return "WM_FONTCHANGE"; + case WM_GETDLGCODE: + return "WM_GETDLGCODE"; + case WM_GETFONT: + return "WM_GETFONT"; + case WM_GETICON: + return "WM_GETICON"; + case WM_GETTEXT: + return "WM_GETTEXT"; + case WM_GETTEXTLENGTH: + return "WM_GETTEXTLENGTH"; + case WM_HELP: + return "WM_HELP"; +#ifdef _WIN32_WCE + case WM_HIBERNATE: + return "WM_HIBERNATE"; +#endif + case WM_HOTKEY: + return "WM_HOTKEY"; + case WM_HSCROLL: + return "WM_HSCROLL"; + case WM_INITDIALOG: + return "WM_INITDIALOG"; + case WM_INITMENUPOPUP: + return "WM_INITMENUPOPUP"; +#if (_WIN32_WINNT >= 0x0501) + case WM_INPUT: + return "WM_INPUT"; +#endif + case WM_INPUTLANGCHANGE: + return "WM_INPUTLANGCHANGE"; + case WM_INPUTLANGCHANGEREQUEST: + return "WM_INPUTLANGCHANGEREQUEST"; + case WM_KEYDOWN: + return "WM_KEYDOWN"; + case WM_KEYUP: + return "WM_KEYUP"; + case WM_KILLFOCUS: + return "WM_KILLFOCUS"; + case WM_MEASUREITEM: + return "WM_MEASUREITEM"; + case WM_MENUCHAR: + return "WM_MENUCHAR"; + case WM_MOVE: + return "WM_MOVE"; + case WM_NCCREATE: + return "WM_NCCREATE"; + case WM_NCDESTROY: + return "WM_NCDESTROY"; +#if (_WIN32_WINNT >= 0x0500) + case WM_NCXBUTTONDOWN: + return "WM_NCXBUTTONDOWN"; + case WM_NCXBUTTONUP: + return "WM_NCXBUTTONUP"; + case WM_NCXBUTTONDBLCLK: + return "WM_NCXBUTTONDBLCLK"; + case WM_NCMOUSEHOVER: + return "WM_NCMOUSEHOVER"; + case WM_NCMOUSELEAVE: + return "WM_NCMOUSELEAVE"; +#endif + case WM_NEXTDLGCTL: + return "WM_NEXTDLGCTL"; + case WM_NOTIFY: + return "WM_NOTIFY"; + case WM_NULL: + return "WM_NULL"; + case WM_PAINT: + return "WM_PAINT"; + case WM_PASTE: + return "WM_PASTE"; + case WM_QUERYDRAGICON: + return "WM_QUERYDRAGICON"; + case WM_QUERYNEWPALETTE: + return "WM_QUERYNEWPALETTE"; + case WM_QUIT: + return "WM_QUIT"; + case WM_RENDERALLFORMATS: + return "WM_RENDERALLFORMATS"; + case WM_RENDERFORMAT: + return "WM_RENDERFORMAT"; + case WM_SETCURSOR: + return "WM_SETCURSOR"; + case WM_SETFOCUS: + return "WM_SETFOCUS"; + case WM_SETFONT: + return "WM_SETFONT"; + case WM_SETICON: + return "WM_SETICON"; + case WM_SETREDRAW: + return "WM_SETREDRAW"; + case WM_SETTEXT: + return "WM_SETTEXT"; + case WM_SETTINGCHANGE: + return "WM_SETTINGCHANGE"; + case WM_SHOWWINDOW: + return "WM_SHOWWINDOW"; + case WM_SIZE: + return "WM_SIZE"; + case WM_STYLECHANGED: + return "WM_STYLECHANGED"; + case WM_SYSCHAR: + return "WM_SYSCHAR"; + case WM_SYSCOLORCHANGE: + return "WM_SYSCOLORCHANGE"; + case WM_SYSCOMMAND: + return "WM_SYSCOMMAND"; + case WM_SYSDEADCHAR: + return "WM_SYSDEADCHAR"; + case WM_SYSKEYDOWN: + return "WM_SYSKEYDOWN"; + case WM_SYSKEYUP: + return "WM_SYSKEYUP"; + case WM_TIMER: + return "WM_TIMER"; + case WM_UNDO: + return "WM_UNDO"; + case WM_VKEYTOITEM: + return "WM_VKEYTOITEM"; + case WM_VSCROLL: + return "WM_VSCROLL"; + case WM_WINDOWPOSCHANGED: + return "WM_WINDOWPOSCHANGED"; + case WM_KEYLAST: + return "WM_KEYLAST"; + case WM_MOUSEMOVE: + return "WM_MOUSEMOVE"; + case WM_LBUTTONDOWN: + return "WM_LBUTTONDOWN"; + case WM_LBUTTONUP: + return "WM_LBUTTONUP"; + case WM_LBUTTONDBLCLK: + return "WM_LBUTTONDBLCLK"; + case WM_RBUTTONDOWN: + return "WM_RBUTTONDOWN"; + case WM_RBUTTONUP: + return "WM_RBUTTONUP"; + case WM_RBUTTONDBLCLK: + return "WM_RBUTTONDBLCLK"; + case WM_MBUTTONDOWN: + return "WM_MBUTTONDOWN"; + case WM_MBUTTONUP: + return "WM_MBUTTONUP"; + case WM_MBUTTONDBLCLK: + return "WM_MBUTTONDBLCLK"; + case WM_MOUSEWHEEL: + return "WM_MOUSEWHEEL"; +#if (_WIN32_WINNT >= 0x0500) + case WM_XBUTTONDOWN: + return "WM_XBUTTONDOWN"; + case WM_XBUTTONUP: + return "WM_XBUTTONUP"; + case WM_XBUTTONDBLCLK: + return "WM_XBUTTONDBLCLK"; + case WM_MOUSELAST: + return "WM_MOUSELAST"; +#else + case WM_MOUSELAST: + return "WM_MOUSELAST"; +#endif + default: + return "unknown"; + } +} + +void +elog_msg (MSG *msg) +{ + elog_add ("msg %p (0x%x): %s\n", msg, msg->message, + elog_msg_to_str (msg)); +} + + //#define QCE_ASYNC_DEBUG namespace { @@ -401,6 +721,7 @@ void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) { QEvent event(QEvent::WinEventAct); + elog_add ("activateEventNotifier %p\n", wen); QCoreApplication::sendEvent(wen, &event); } @@ -706,6 +1027,8 @@ { Q_D(QEventDispatcherWin32); + elog_add ("processEvents(0x%x)\n", int(flags)); + if (!d->internalHwnd) createInternalHwnd(); @@ -731,10 +1054,14 @@ // process queued user input events haveMessage = true; msg = d->queuedUserInputEvents.takeFirst(); + elog_add ("haveMessage: queuedUserInputEvents %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) { // process queued socket events haveMessage = true; msg = d->queuedSocketEvents.takeFirst(); + elog_add ("haveMessage: queuedSocketEvents %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); } else { haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) @@ -753,37 +1080,48 @@ // queue user input events for later processing haveMessage = false; d->queuedUserInputEvents.append(msg); + elog_add ("queued: UserInputEvents %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); } if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers) && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) { // queue socket events for later processing haveMessage = false; d->queuedSocketEvents.append(msg); + elog_add ("queued: SocketEvents %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); } } if (!haveMessage) { // no message - check for signalled objects for (int i=0; i<(int)nCount; i++) pHandles[i] = d->winEventNotifierList.at(i)->handle(); + elog_add ("MWFMOE: count = %i\n", nCount); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE); if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) { // a new message has arrived, process it + elog_add ("MWFMOE: message arrived, starting over\n"); continue; } } if (haveMessage) { + #ifdef Q_OS_WINCE // WinCE doesn't support hooks at all, so we have to call this by hand :( (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg); #endif + elog_add ("MWFMOE: qt_GetMessageHook: %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) { if (seenWM_QT_SENDPOSTEDEVENTS) { // when calling processEvents() "manually", we only want to send posted // events once needWM_QT_SENDPOSTEDEVENTS = true; + elog_add ("MWFMOE: needWM_QT_SENDPOSTEDEVENTS = true\n"); continue; } + elog_add ("MWFMOE: seenWM_QT_SENDPOSTEDEVENTS = true\n"); seenWM_QT_SENDPOSTEDEVENTS = true; } else if (msg.message == WM_TIMER) { // avoid live-lock by keeping track of the timers we've already sent @@ -793,21 +1131,29 @@ found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam); } if (found) + { + elog_add ("MWFMOE: timer processed already\n"); continue; - processedTimers.append(msg); + } + elog_add ("MWFMOE: timer not processed yet\n"); + processedTimers.append(msg); } else if (msg.message == WM_QUIT) { + elog_add ("MWFMOE: quit!\n"); if (QCoreApplication::instance()) QCoreApplication::instance()->quit(); return false; } if (!filterEvent(&msg)) { + elog_add ("MWFMOE: not filtered, dispatching msg %p (0x%x)\n", msg, msg.message); + elog_msg (&msg); TranslateMessage(&msg); DispatchMessage(&msg); } } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); } else { + elog_add ("no message, no event\n"); // nothing todo so break break; } @@ -819,14 +1165,17 @@ && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) { + elog_add ("still nothing, waiting\n"); DWORD nCount = d->winEventNotifierList.count(); Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1); for (int i=0; i<(int)nCount; i++) pHandles[i] = d->winEventNotifierList.at(i)->handle(); + elog_add ("MWFMOE: count = %i (blocking)\n", nCount); emit aboutToBlock(); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); + elog_add ("MWFMOE: waitRet = %i\n", waitRet); if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); retVal = true; @@ -835,12 +1184,17 @@ } while (canWait); if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) { + elog_add ("sendPostedEvents\n"); // when called "manually", always send posted events QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); } if (needWM_QT_SENDPOSTEDEVENTS) + { + elog_add ("PostMessage\n"); PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); + } + elog_add ("processEvents leave\n"); return retVal; }