bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherGlib); const bool canWait = (flags & QEventLoop::WaitForMoreEvents); if (canWait) emit aboutToBlock(); else emit awake(); // tell postEventSourcePrepare() and timerSource about any new flags QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags; d->timerSource->processEventsFlags = flags; if (!(flags & QEventLoop::EventLoopExec)) { // force timers to be sent at normal priority d->timerSource->runWithIdlePriority = false; } bool result = g_main_context_iteration(d->mainContext, canWait); while (!result && canWait) result = g_main_context_iteration(d->mainContext, canWait); d->timerSource->processEventsFlags = savedFlags; if (canWait) emit awake(); return result; }
bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherGlib); const bool canWait = (flags & QEventLoop::WaitForMoreEvents); if (canWait) emit aboutToBlock(); else emit awake(); // tell postEventSourcePrepare() and timerSource about any new flags QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags; d->timerSource->processEventsFlags = flags; bool result = g_main_context_iteration(d->mainContext, canWait); while (!result && canWait) result = g_main_context_iteration(d->mainContext, canWait); d->timerSource->processEventsFlags = savedFlags; if (canWait) emit awake(); return result; }
void edunlink() { //printf("TimerFixer[%p] unlinking from dispatcher %p\n", this, ed); if(ed) { disconnect(ed, SIGNAL(aboutToBlock()), this, SLOT(ed_aboutToBlock())); ed = 0; } }
QXcbConnection::QXcbConnection(const char *displayName) : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) #ifdef XCB_USE_DRI2 , m_dri2_major(0) , m_dri2_minor(0) , m_dri2_support_probed(false) , m_has_support_for_dri2(false) #endif { int primaryScreen = 0; #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); primaryScreen = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); XSetEventQueueOwner(dpy, XCBOwnsEventQueue); m_xlib_display = dpy; #ifdef XCB_USE_EGL EGLDisplay eglDisplay = eglGetDisplay(dpy); m_egl_display = eglDisplay; EGLint major, minor; eglBindAPI(EGL_OPENGL_ES_API); m_has_egl = eglInitialize(eglDisplay,&major,&minor); #endif //XCB_USE_EGL #else m_connection = xcb_connect(m_displayName.constData(), &primaryScreen); #endif //XCB_USE_XLIB m_setup = xcb_get_setup(xcb_connection()); initializeAllAtoms(); xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int screenNumber = 0; while (it.rem) { m_screens << new QXcbScreen(this, it.data, screenNumber++); xcb_screen_next(&it); } m_keyboard = new QXcbKeyboard(this); #ifdef XCB_USE_DRI2 initializeDri2(); #endif QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); connect(notifier, SIGNAL(activated(int)), this, SLOT(processXcbEvents())); QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(qApp->thread()); connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processXcbEvents())); sync(); }
QWaylandDisplay::QWaylandDisplay() : mLastKeyboardFocusInputDevice(0) , mDndSelectionHandler(0) , mWindowExtension(0) , mSubSurfaceExtension(0) , mOutputExtension(0) , mTouchExtension(0) , mQtKeyExtension(0) { display = this; qRegisterMetaType<uint32_t>("uint32_t"); mEventThreadObject = new QWaylandEventThread(0); mEventThread = new QThread(this); mEventThreadObject->moveToThread(mEventThread); mEventThread->start(); mEventThreadObject->displayConnect(); mDisplay = mEventThreadObject->display(); //blocks until display is available //Create a new even queue for the QtGui thread mEventQueue = wl_display_create_queue(mDisplay); struct ::wl_registry *registry = wl_display_get_registry(mDisplay); wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue); init(registry); QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(flushRequests())); connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests())); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration = QWaylandGLIntegration::createGLIntegration(this); #endif mWindowManagerIntegration = new QWaylandWindowManagerIntegration(this); blockingReadEvents(); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration->initialize(); flushRequests(); while (mEglIntegration->waitingForEvents()) blockingReadEvents(); #endif waitForScreens(); }
int QAbstractEventDispatcher::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: aboutToBlock(); break; case 1: awake(); break; default: ; } _id -= 2; } return _id; }
bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherUNIX); d->interrupt = false; // we are awake, broadcast it emit awake(); QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); int nevents = 0; const bool canWait = (d->threadData->canWait && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents)); if (canWait) emit aboutToBlock(); if (!d->interrupt) { // return the maximum time we can wait for an event. timeval *tm = 0; timeval wait_tm = { 0l, 0l }; if (!(flags & QEventLoop::X11ExcludeTimers)) { if (d->timerList.timerWait(wait_tm)) tm = &wait_tm; } if (!canWait) { if (!tm) tm = &wait_tm; // no time to wait tm->tv_sec = 0l; tm->tv_usec = 0l; } nevents = d->doSelect(flags, tm); // activate timers if (! (flags & QEventLoop::X11ExcludeTimers)) { nevents += activateTimers(); } } // return true if we handled events, false otherwise return (nevents > 0); }
QWaylandDisplay::QWaylandDisplay(void) : argb_visual(0), premultiplied_argb_visual(0), rgb_visual(0) { display = this; qRegisterMetaType<uint32_t>("uint32_t"); mDisplay = wl_display_connect(NULL); if (mDisplay == NULL) { qErrnoWarning(errno, "Failed to create display"); qFatal("No wayland connection available."); } wl_display_add_global_listener(mDisplay, QWaylandDisplay::displayHandleGlobal, this); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration = QWaylandGLIntegration::createGLIntegration(this); #endif #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT mWindowManagerIntegration = QWaylandWindowManagerIntegration::createIntegration(this); #endif blockingReadEvents(); #ifdef QT_WAYLAND_GL_SUPPORT mEglIntegration->initialize(); #endif connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(flushRequests())); mFd = wl_display_get_fd(mDisplay, sourceUpdate, this); mReadNotifier = new QSocketNotifier(mFd, QSocketNotifier::Read, this); connect(mReadNotifier, SIGNAL(activated(int)), this, SLOT(readEvents())); waitForScreens(); }
bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags) { Q_D(QEventDispatcherMac); #if 0 //TrackDrag says you may not use the EventManager things.. if(qt_mac_in_drag) { qWarning("Qt: Cannot process events whilst dragging!"); return false; } #endif d->interrupt = false; emit awake(); #ifndef QT_MAC_NO_QUICKDRAW if(!qt_mac_safe_pdev) { //create an empty widget and this can be used for a port anytime QWidget *tlw = new QWidget; tlw->setAttribute(Qt::WA_DeleteOnClose); tlw->setObjectName(QLatin1String("empty_widget")); tlw->hide(); qt_mac_safe_pdev = tlw; } #endif bool retVal = false; for (;;) { QApplicationPrivate::sendPostedEvents(0, 0, d->threadData); if (d->activateTimers() > 0) //send null timers retVal = true; do { EventRef event; if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) { // process a pending user input event event = d->queuedUserInputEvents.takeFirst(); } else { OSStatus err = ReceiveNextEvent(0,0, kEventDurationNoWait, true, &event); if(err != noErr) continue; // else if (flags & QEventLoop::ExcludeUserInputEvents) { UInt32 ekind = GetEventKind(event), eclass = GetEventClass(event); switch(eclass) { case kEventClassQt: if(ekind != kEventQtRequestContext) break; // fall through case kEventClassMouse: case kEventClassKeyboard: d->queuedUserInputEvents.append(event); continue; } } } if (!filterEvent(&event) && qt_mac_send_event(flags, event)) retVal = true; ReleaseEvent(event); } while(!d->interrupt && GetNumEventsInQueue(GetMainEventQueue()) > 0); bool canWait = (d->threadData->canWait && !retVal && !d->interrupt && (flags & QEventLoop::WaitForMoreEvents) && !d->zero_timer_count); if (canWait) { emit aboutToBlock(); while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e20, true) == kCFRunLoopRunTimedOut); flags &= ~QEventLoop::WaitForMoreEvents; emit awake(); } else { CFRunLoopRunInMode(kCFRunLoopDefaultMode, kEventDurationNoWait, true); break; } } return retVal; }
bool QEventLoop::processEvents( ProcessEventsFlags flags ) { // process events from the X server XEvent event; int nevents = 0; #if defined(QT_THREAD_SUPPORT) QMutexLocker locker( QApplication::qt_mutex ); #endif // handle gui and posted events if ( qt_is_gui_used ) { QApplication::sendPostedEvents(); // Two loops so that posted events accumulate while ( XPending( QPaintDevice::x11AppDisplay() ) ) { // also flushes output buffer while ( XPending( QPaintDevice::x11AppDisplay() ) ) { if ( d->shortcut ) { return FALSE; } XNextEvent( QPaintDevice::x11AppDisplay(), &event ); if ( flags & ExcludeUserInput ) { switch ( event.type ) { case ButtonPress: case ButtonRelease: case MotionNotify: case XKeyPress: case XKeyRelease: case EnterNotify: case LeaveNotify: continue; case ClientMessage: { // from qapplication_x11.cpp extern Atom qt_wm_protocols; extern Atom qt_wm_take_focus; extern Atom qt_qt_scrolldone; // only keep the wm_take_focus and // qt_qt_scrolldone protocols, discard all // other client messages if ( event.xclient.format != 32 ) continue; if ( event.xclient.message_type == qt_wm_protocols || (Atom) event.xclient.data.l[0] == qt_wm_take_focus ) break; if ( event.xclient.message_type == qt_qt_scrolldone ) break; } default: break; } } nevents++; if ( qApp->x11ProcessEvent( &event ) == 1 ) return TRUE; } } } if ( d->shortcut ) { return FALSE; } QApplication::sendPostedEvents(); const uint exclude_all = ExcludeSocketNotifiers | 0x08; // 0x08 == ExcludeTimers for X11 only if ( nevents > 0 && ( flags & exclude_all ) == exclude_all && ( flags & WaitForMore ) ) { return TRUE; } // don't block if exitLoop() or exit()/quit() has been called. bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore); // Process timers and socket notifiers - the common UNIX stuff // return the maximum time we can wait for an event. static timeval zerotm; timeval *tm = 0; if ( ! ( flags & 0x08 ) ) { // 0x08 == ExcludeTimers for X11 only tm = qt_wait_timer(); // wait for timer or X event if ( !canWait ) { if ( !tm ) tm = &zerotm; tm->tv_sec = 0; // no time to wait tm->tv_usec = 0; } } int highest = 0; if ( ! ( flags & ExcludeSocketNotifiers ) ) { // return the highest fd we can wait for input on if ( d->sn_highest >= 0 ) { // has socket notifier(s) if ( d->sn_vec[0].list && ! d->sn_vec[0].list->isEmpty() ) d->sn_vec[0].select_fds = d->sn_vec[0].enabled_fds; else FD_ZERO( &d->sn_vec[0].select_fds ); if ( d->sn_vec[1].list && ! d->sn_vec[1].list->isEmpty() ) d->sn_vec[1].select_fds = d->sn_vec[1].enabled_fds; else FD_ZERO( &d->sn_vec[1].select_fds ); if ( d->sn_vec[2].list && ! d->sn_vec[2].list->isEmpty() ) d->sn_vec[2].select_fds = d->sn_vec[2].enabled_fds; else FD_ZERO( &d->sn_vec[2].select_fds ); } else { FD_ZERO( &d->sn_vec[0].select_fds ); FD_ZERO( &d->sn_vec[1].select_fds ); FD_ZERO( &d->sn_vec[2].select_fds ); } highest = d->sn_highest; } else { FD_ZERO( &d->sn_vec[0].select_fds ); FD_ZERO( &d->sn_vec[1].select_fds ); FD_ZERO( &d->sn_vec[2].select_fds ); } if ( qt_is_gui_used ) { // select for events on the event socket - only on X11 FD_SET( d->xfd, &d->sn_vec[0].select_fds ); highest = QMAX( highest, d->xfd ); } FD_SET( d->thread_pipe[0], &d->sn_vec[0].select_fds ); highest = QMAX( highest, d->thread_pipe[0] ); if ( canWait ) emit aboutToBlock(); if ( qt_preselect_handler ) { QVFuncList::Iterator it, end = qt_preselect_handler->end(); for ( it = qt_preselect_handler->begin(); it != end; ++it ) (**it)(); } // unlock the GUI mutex and select. when we return from this function, there is // something for us to do #if defined(QT_THREAD_SUPPORT) locker.mutex()->unlock(); #endif int nsel; do { nsel = select( highest + 1, &d->sn_vec[0].select_fds, &d->sn_vec[1].select_fds, &d->sn_vec[2].select_fds, tm ); } while (nsel == -1 && (errno == EINTR || errno == EAGAIN)); // relock the GUI mutex before processing any pending events #if defined(QT_THREAD_SUPPORT) locker.mutex()->lock(); #endif // we are awake, broadcast it emit awake(); emit qApp->guiThreadAwake(); if (nsel == -1) { if (errno == EBADF) { // it seems a socket notifier has a bad fd... find out // which one it is and disable it fd_set fdset; zerotm.tv_sec = zerotm.tv_usec = 0l; for (int type = 0; type < 3; ++type) { QPtrList<QSockNot> *list = d->sn_vec[type].list; if (!list) continue; QSockNot *sn = list->first(); while (sn) { FD_ZERO(&fdset); FD_SET(sn->fd, &fdset); int ret = -1; do { switch (type) { case 0: // read ret = select(sn->fd + 1, &fdset, 0, 0, &zerotm); break; case 1: // write ret = select(sn->fd + 1, 0, &fdset, 0, &zerotm); break; case 2: // except ret = select(sn->fd + 1, 0, 0, &fdset, &zerotm); break; } } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); if (ret == -1 && errno == EBADF) { // disable the invalid socket notifier static const char *t[] = { "Read", "Write", "Exception" }; qWarning("QSocketNotifier: invalid socket %d and type '%s', disabling...", sn->fd, t[type]); sn->obj->setEnabled(FALSE); } sn = list->next(); } } } else { // EINVAL... shouldn't happen, so let's complain to stderr // and hope someone sends us a bug report perror( "select" ); } } // some other thread woke us up... consume the data on the thread pipe so that // select doesn't immediately return next time if ( nsel > 0 && FD_ISSET( d->thread_pipe[0], &d->sn_vec[0].select_fds ) ) { char c; ::read( d->thread_pipe[0], &c, 1 ); } if ( qt_postselect_handler ) { QVFuncList::Iterator it, end = qt_postselect_handler->end(); for ( it = qt_postselect_handler->begin(); it != end; ++it ) (**it)(); } // activate socket notifiers if ( ! ( flags & ExcludeSocketNotifiers ) && nsel > 0 && d->sn_highest >= 0 ) { // if select says data is ready on any socket, then set the socket notifier // to pending int i; for ( i=0; i<3; i++ ) { if ( ! d->sn_vec[i].list ) continue; QPtrList<QSockNot> *list = d->sn_vec[i].list; QSockNot *sn = list->first(); while ( sn ) { if ( FD_ISSET( sn->fd, &d->sn_vec[i].select_fds ) ) setSocketNotifierPending( sn->obj ); sn = list->next(); } } nevents += activateSocketNotifiers(); } // activate timers if ( ! ( flags & 0x08 ) ) { // 0x08 == ExcludeTimers for X11 only nevents += activateTimers(); } // color approx. optimization - only on X11 qt_reset_color_avail(); // return true if we handled events, false otherwise return (nevents > 0); }
void QWaylandIntegration::initialize() { QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests())); QObject::connect(dispatcher, SIGNAL(awake()), mDisplay, SLOT(flushRequests())); }
int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout) { Q_UNUSED(nfds); Q_D(QEventDispatcherBlackberry); const BBScopedLoopLevelCounter bbLoopCounter(d); BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); // prepare file sets for bps callback d->ioData->count = 0; d->ioData->readfds = readfds; d->ioData->writefds = writefds; d->ioData->exceptfds = exceptfds; // reset all file sets if (readfds) FD_ZERO(readfds); if (writefds) FD_ZERO(writefds); if (exceptfds) FD_ZERO(exceptfds); bps_event_t *event = 0; unsigned int eventCount = 0; // If an event handler called through filterEvent() starts a nested event loop by creating a // new QEventLoop, we will recursively enter this function again. However, each time // bps_get_event() is called, it destroys the last event it handed out before returning the // next event. We don't want it to destroy the event that triggered the nested event loop, // since there may still be more handlers that need to get that event, once the nested event // loop is done and control returns to the outer event loop. // // So we move an event to a holding channel, which takes ownership of the event. Putting // the event on our own channel allows us to manage when it is destroyed, keeping it alive // until we know we are done with it. Each recursive call of this function needs to have // it's own holding channel, since a channel is a queue, not a stack. // // However, a recursive call into this function happens very rarely compared to the many // times this function is called. We don't want to create a holding channel for each time // this function is called, only when it is called recursively. Thus we have the instance // variable d->holding_channel to use in the common case. We keep track of recursive calls // with d->loop_level. If we are in a recursive call, then we create a new holding channel // for this run. int holding_channel = d->holding_channel; if ((d->loop_level > 1) && Q_UNLIKELY(bps_channel_create(&holding_channel, 0) != BPS_SUCCESS)) { qWarning("QEventDispatcherBlackberry: bps_channel_create failed"); holding_channel = -1; } // Convert timeout to milliseconds int timeoutTotal = -1; if (timeout) timeoutTotal = timespecToMillisecs(*timeout); int timeoutLeft = timeoutTotal; timespec startTime = qt_gettime(); // This loop exists such that we can drain the bps event queue of all native events // more efficiently than if we were to return control to Qt after each event. This // is important for handling touch events which can come in rapidly. forever { // Only emit the awake() and aboutToBlock() signals in the second iteration. For the // first iteration, the UNIX event dispatcher will have taken care of that already. // Also native events are actually processed one loop iteration after they were // retrieved with bps_get_event(). // Filtering the native event should happen between the awake() and aboutToBlock() // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - // bps_get_event() need not to be interrupted by a break or return statement. if (eventCount > 0) { if (event) { emit awake(); filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); emit aboutToBlock(); if (Q_LIKELY(holding_channel != -1)) { // We are now done with this BPS event. Destroy it. destroyHeldBpsEvent(holding_channel); } } // Update the timeout // Clock source is monotonic, so we can recalculate how much timeout is left if (timeoutTotal != -1) { timespec t2 = qt_gettime(); timeoutLeft = timeoutTotal - (timespecToMillisecs(t2) - timespecToMillisecs(startTime)); if (timeoutLeft < 0) timeoutLeft = 0; } timespec tnext; if (d->timerList.timerWait(tnext)) { int timeoutNext = timespecToMillisecs(tnext); if (timeoutNext < timeoutLeft || timeoutTotal == -1) { timeoutTotal = timeoutLeft = timeoutNext; startTime = qt_gettime(); } } } event = 0; { // We need to increase loop level in this scope, // because bps_get_event can also invoke callbacks QScopedLoopLevelCounter loopLevelCounter(d->threadData); // Wait for event or file to be ready const int result = bps_get_event(&event, timeoutLeft); if (Q_UNLIKELY(result != BPS_SUCCESS)) qWarning("QEventDispatcherBlackberry: bps_get_event failed"); } if (!event) // In case of !event, we break out of the loop to let Qt process the timers break; // (since timeout has expired) and socket notifiers that are now ready. if (bps_event_get_domain(event) == bpsUnblockDomain) { timeoutTotal = 0; // in order to immediately drain the event queue of native events event = 0; // (especially touch move events) we don't break out here } else { // Move the event to our holding channel so we can manage when it is destroyed. if (Q_LIKELY(holding_channel != 1) && Q_UNLIKELY(bps_channel_push_event(holding_channel, event) != BPS_SUCCESS)) { qWarning("QEventDispatcherBlackberry: bps_channel_push_event failed"); } } ++eventCount; // Make sure we are not trapped in this loop due to continuous native events // also we cannot recalculate the timeout without a monotonic clock as the time may have changed const unsigned int maximumEventCount = 12; if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0) || !QElapsedTimer::isMonotonic())) { if (event) { filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); if (Q_LIKELY(holding_channel != -1)) { // We are now done with this BPS event. Destroy it. destroyHeldBpsEvent(holding_channel); } } break; } } // If this was a recursive call into this function, a new holding channel was created for // this run, so destroy it now. if ((holding_channel != d->holding_channel) && Q_LIKELY(holding_channel != -1) && Q_UNLIKELY(bps_channel_destroy(holding_channel) != BPS_SUCCESS)) { qWarning("QEventDispatcherBlackberry: bps_channel_destroy failed"); } // the number of bits set in the file sets return d->ioData->count; }
bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags ) { bool handledAnyEvent = false; bool oldNoSocketEventsValue = m_noSocketEvents; bool oldInsideTimerEventValue = m_insideTimerEvent; m_insideTimerEvent = false; QT_TRY { Q_D(QAbstractEventDispatcher); // It is safe if this counter overflows. The main importance is that each // iteration count is different from the last. m_iterationCount++; RThread &thread = d->threadData->symbian_thread_handle; bool block; if (flags & QEventLoop::WaitForMoreEvents) { block = true; emit aboutToBlock(); } else { block = false; } if (flags & QEventLoop::ExcludeSocketNotifiers) { m_noSocketEvents = true; } else { m_noSocketEvents = false; handledAnyEvent = sendDeferredSocketEvents(); } bool handledSymbianEvent = false; m_interrupt = false; #ifdef QT_SYMBIAN_PRIORITY_DROP QElapsedTimer eventTimer; #endif while (1) { if (block) { // This is where Qt will spend most of its time. CActiveScheduler::Current()->WaitForAnyRequest(); } else { if (thread.RequestCount() == 0) { #ifdef QT_SYMBIAN_PRIORITY_DROP if (idleDetectorThread()->hasRun()) { m_lastIdleRequestTimer.start(); idleDetectorThread()->kick(); } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) { User::AfterHighRes(m_delay); } #endif break; } // This one should return without delay. CActiveScheduler::Current()->WaitForAnyRequest(); } #ifdef QT_SYMBIAN_PRIORITY_DROP if (idleDetectorThread()->hasRun()) { if (m_delay > baseDelay) m_delay -= baseDelay; m_lastIdleRequestTimer.start(); idleDetectorThread()->kick(); } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) { User::AfterHighRes(m_delay); // allow delay to be up to 1/4 of execution time if (!idleDetectorThread()->hasRun() && m_delay*3 < m_avgEventTime) m_delay += baseDelay; } eventTimer.start(); #endif TInt error; handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt); if (error) { qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error); CActiveScheduler::Current()->Error(error); } #ifdef QT_SYMBIAN_PRIORITY_DROP int eventDur = eventTimer.elapsed()*1000; // average is calcualted as a 5% decaying exponential average m_avgEventTime = (m_avgEventTime * 95 + eventDur * 5) / 100; #endif if (!handledSymbianEvent) { qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal"); } handledAnyEvent = true; if (m_interrupt) { break; } block = false; }; emit awake(); } QT_CATCH (const std::exception& ex) { #ifndef QT_NO_EXCEPTIONS CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex)); #endif }
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 (!filterEvent(&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 { // 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 && 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 QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); } if (needWM_QT_SENDPOSTEDEVENTS) PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); return retVal; }
Compositor::Compositor(QWaylandCompositor *qt_compositor) : m_display(new Display) , m_default_input_device(0) , m_pageFlipper(0) , m_current_frame(0) , m_last_queued_buf(-1) , m_qt_compositor(qt_compositor) , m_orientation(Qt::PrimaryOrientation) , m_directRenderSurface(0) , m_directRenderContext(0) , m_directRenderActive(false) #if defined (QT_COMPOSITOR_WAYLAND_GL) , m_graphics_hw_integration(0) #endif , m_outputExtension(0) , m_surfaceExtension(0) , m_subSurfaceExtension(0) , m_touchExtension(0) , m_retainNotify(0) { compositor = this; #if defined (QT_COMPOSITOR_WAYLAND_GL) QWindow *window = qt_compositor->window(); if (window && window->surfaceType() != QWindow::RasterSurface) { QStringList keys = QWaylandGraphicsHardwareIntegrationFactory::keys(); QString targetKey; QByteArray hardwareIntegration = qgetenv("QT_WAYLAND_HARDWARE_INTEGRATION"); if (keys.contains(QString::fromLocal8Bit(hardwareIntegration.constData()))) { targetKey = QString::fromLocal8Bit(hardwareIntegration.constData()); } else if (keys.contains(QString::fromLatin1("wayland-egl"))) { targetKey = QString::fromLatin1("wayland-egl"); } else if (!keys.isEmpty()) { targetKey = keys.first(); } if (!targetKey.isEmpty()) { m_graphics_hw_integration = QWaylandGraphicsHardwareIntegrationFactory::create(targetKey, QStringList()); if (m_graphics_hw_integration) { m_graphics_hw_integration->setCompositor(qt_compositor); } } //BUG: if there is no hw_integration, bad things will probably happen } #endif m_windowManagerIntegration = new WindowManagerServerIntegration(qt_compositor, this); wl_display_add_global(m_display->handle(),&wl_compositor_interface,this,Compositor::bind_func); m_data_device_manager = new DataDeviceManager(this); wl_display_init_shm(m_display->handle()); m_output_global = new OutputGlobal(m_display->handle()); m_shell = new Shell(); wl_display_add_global(m_display->handle(), &wl_shell_interface, m_shell, Shell::bind_func); m_outputExtension = new OutputExtensionGlobal(this); m_surfaceExtension = new SurfaceExtensionGlobal(this); m_qtkeyExtension = new QtKeyExtensionGlobal(this); m_touchExtension = new TouchExtensionGlobal(this); if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) { fprintf(stderr, "Fatal: Failed to open server socket\n"); exit(EXIT_FAILURE); } m_loop = wl_display_get_event_loop(m_display->handle()); int fd = wl_event_loop_get_fd(m_loop); QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, this); connect(sockNot, SIGNAL(activated(int)), this, SLOT(processWaylandEvents())); QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processWaylandEvents())); qRegisterMetaType<SurfaceBuffer*>("SurfaceBuffer*"); //initialize distancefieldglyphcache here }
bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags ) { bool handledAnyEvent = false; bool oldNoSocketEventsValue = m_noSocketEvents; QT_TRY { Q_D(QAbstractEventDispatcher); // It is safe if this counter overflows. The main importance is that each // iteration count is different from the last. m_iterationCount++; RThread &thread = d->threadData->symbian_thread_handle; bool block; if (flags & QEventLoop::WaitForMoreEvents) { block = true; emit aboutToBlock(); } else { block = false; } if (flags & QEventLoop::ExcludeSocketNotifiers) { m_noSocketEvents = true; } else { m_noSocketEvents = false; handledAnyEvent = sendDeferredSocketEvents(); } bool handledSymbianEvent = false; m_interrupt = false; /* * This QTime variable is used to measure the time it takes to finish * the event loop. If we take too long in the loop, other processes * may be starved and killed. After the first event has completed, we * take the current time, and if the remaining events take longer than * a preset time, we temporarily lower the priority to force a context * switch. For applications that do not take unecessarily long in the * event loop, the priority will not be altered. */ QTime time; enum { FirstRun, SubsequentRun, TimeStarted } timeState = FirstRun; TProcessPriority priority; while (1) { if (block) { // This is where Qt will spend most of its time. CActiveScheduler::Current()->WaitForAnyRequest(); } else { if (thread.RequestCount() == 0) { break; } // This one should return without delay. CActiveScheduler::Current()->WaitForAnyRequest(); } if (timeState == SubsequentRun) { time.start(); timeState = TimeStarted; } TInt error; handledSymbianEvent = CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle); if (error) { qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error); CActiveScheduler::Current()->Error(error); } if (!handledSymbianEvent) { qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal"); } handledAnyEvent = true; if (m_interrupt) { break; } block = false; if (timeState == TimeStarted && time.elapsed() > 100) { priority = m_processHandle.Priority(); m_processHandle.SetPriority(EPriorityBackground); time.start(); // Slight chance of race condition in the next lines, but nothing fatal // will happen, just wrong priority. if (m_processHandle.Priority() == EPriorityBackground) { m_processHandle.SetPriority(priority); } } if (timeState == FirstRun) timeState = SubsequentRun; }; emit awake(); } QT_CATCH (const std::exception& ex) { #ifndef QT_NO_EXCEPTIONS CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex)); #endif }