bool QLuaApplication::close() { if (! d->closingDown) { d->closingDown = true; QCloseEvent ev; sendEvent(this, &ev); d->closingDown = ev.isAccepted(); if (d->closingDown) { sendPostedEvents(); QTimer::singleShot(0, this, SLOT(quit())); } } return d->closingDown; }
void QLuaApplication::Private::ttyEndOfFile() { if (++ttyEofCount > 8) { sendPostedEvents(); theApp->quit(); } else if (ttyConsole && interactionStarted) { accepting = false; emit theApp->acceptingCommands(false); luaInput.clear(); QByteArray prompt = "Really quit [y/N]? "; ttyEofReceived = true; theConsole->abortReadLine(); theConsole->readLine(prompt); } }
unsigned int EventLoop::exec(int timeoutTime) { int quitTimerId = -1; if (timeoutTime != -1) quitTimerId = registerTimer([=](int) { timeout = true; quit(); }, timeoutTime, Timer::SingleShot); unsigned int ret = 0; #if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE) enum { MaxEvents = 64 }; NativeEvent events[MaxEvents]; #endif for (;;) { for (;;) { if (!sendPostedEvents() && !sendTimers()) break; } int waitUntil = -1; { std::lock_guard<std::mutex> locker(mutex); // check if we're stopped if (stop) { stop = false; if (timeout) { timeout = false; ret = Timeout; } else { ret = Success; } break; } const auto timer = timersByTime.begin(); if (timer != timersByTime.end()) { const uint64_t now = currentTime(); waitUntil = std::max<int>((*timer)->when - now, 0); } } int eventCount; #if defined(HAVE_EPOLL) eintrwrap(eventCount, epoll_wait(pollFd, events, MaxEvents, waitUntil)); #elif defined(HAVE_KQUEUE) timespec timeout; timespec* timeptr = 0; if (waitUntil != -1) { timeout.tv_sec = waitUntil / 1000; timeout.tv_nsec = (waitUntil % 1000LLU) * 1000000; timeptr = &timeout; } eintrwrap(eventCount, kevent(pollFd, 0, 0, events, MaxEvents, timeptr)); #elif defined(HAVE_SELECT) timeval timeout; timeval* timeptr = 0; if (waitUntil != -1) { timeout.tv_sec = waitUntil / 1000; timeout.tv_usec = (waitUntil % 1000LLU) * 1000; timeptr = &timeout; } fd_set rdfd, wrfd; fd_set* wrfdp = 0; FD_ZERO(&rdfd); FD_ZERO(&wrfd); int max = eventPipe[0]; FD_SET(max, &rdfd); { std::lock_guard<std::mutex> locker(mutex); auto s = sockets.begin(); const auto e = sockets.end(); while (s != e) { if (s->second.first & SocketRead) { FD_SET(s->first, &rdfd); } if (s->second.first & SocketWrite) { if (!wrfdp) wrfdp = &wrfd; FD_SET(s->first, wrfdp); } max = std::max(max, s->first); ++s; } } eintrwrap(eventCount, select(max + 1, &rdfd, wrfdp, 0, timeptr)); #endif if (eventCount < 0) { // bad ret = GeneralError; break; } else if (eventCount) { #if defined(HAVE_SELECT) NativeEvent event; event.rdfd = &rdfd; event.wrfd = wrfdp; NativeEvent* events = &event; #endif ret = processSocketEvents(events, eventCount); if (ret & (Success|GeneralError|Timeout)) break; } } if (quitTimerId != -1) clearTimer(quitTimerId); return ret; }
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherWin32); if (!d->internalHwnd) createInternalHwnd(); d->interrupt = false; emit awake(); bool canWait; bool retVal = false; bool seenWM_QT_SENDPOSTEDEVENTS = false; bool needWM_QT_SENDPOSTEDEVENTS = false; do { DWORD waitRet = 0; HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1]; QVarLengthArray<MSG> processedTimers; while (!d->interrupt) { DWORD nCount = d->winEventNotifierList.count(); Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1); MSG msg; bool haveMessage; if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) { // process queued user input events haveMessage = true; msg = d->queuedUserInputEvents.takeFirst(); } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) { // process queued socket events haveMessage = true; msg = d->queuedSocketEvents.takeFirst(); } else { haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) && ((msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) || (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) || msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL || msg.message == WM_TOUCH #ifndef QT_NO_GESTURES || msg.message == WM_GESTURE || msg.message == WM_GESTURENOTIFY #endif || msg.message == WM_CLOSE)) { // queue user input events for later processing haveMessage = false; d->queuedUserInputEvents.append(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); } } if (!haveMessage) { // no message - check for signalled objects for (int i=0; i<(int)nCount; i++) pHandles[i] = d->winEventNotifierList.at(i)->handle(); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE); if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) { // a new message has arrived, process it 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 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; continue; } seenWM_QT_SENDPOSTEDEVENTS = true; } else if (msg.message == WM_TIMER) { // avoid live-lock by keeping track of the timers we've already sent bool found = false; for (int i = 0; !found && i < processedTimers.count(); ++i) { const MSG processed = processedTimers.constData()[i]; found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam); } if (found) continue; processedTimers.append(msg); } else if (msg.message == WM_QUIT) { if (QCoreApplication::instance()) QCoreApplication::instance()->quit(); return false; } if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else if (waitRet - WAIT_OBJECT_0 < nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); } else { // nothing todo so break break; } retVal = true; } // still nothing - wait for message or signalled objects canWait = (!retVal && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) { 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(); emit aboutToBlock(); waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE); emit awake(); if (waitRet - WAIT_OBJECT_0 < nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); retVal = true; } } } while (canWait); if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) { // when called "manually", always send posted events sendPostedEvents(); } if (needWM_QT_SENDPOSTEDEVENTS) PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); return retVal; }