265QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
266 : mainContext(context)
268#if GLIB_MAJOR_VERSION == 2
&& GLIB_MINOR_VERSION < 32
269 if (qEnvironmentVariableIsEmpty(
"QT_NO_THREADED_GLIB")) {
270 Q_CONSTINIT
static QBasicMutex mutex;
271 QMutexLocker locker(&mutex);
272 if (!g_thread_supported())
278 g_main_context_ref(mainContext);
280 QCoreApplication *app = QCoreApplication::instance();
281 if (app && QThread::isMainThread()) {
282 mainContext = g_main_context_default();
283 g_main_context_ref(mainContext);
285 mainContext = g_main_context_new();
289#if GLIB_CHECK_VERSION (2
, 22
, 0
)
290 g_main_context_push_thread_default (mainContext);
294 GSource *source = g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource));
295 g_source_set_name(source,
"[Qt] GPostEventSource");
296 postEventSource =
reinterpret_cast<GPostEventSource *>(source);
299 q20::construct_at(&postEventSource->serialNumber, 1);
300 postEventSource->d =
this;
301 g_source_set_can_recurse(&postEventSource->source,
true);
302 g_source_attach(&postEventSource->source, mainContext);
305 source = g_source_new(&socketNotifierSourceFuncs,
sizeof(GSocketNotifierSource));
306 g_source_set_name(source,
"[Qt] GSocketNotifierSource");
307 socketNotifierSource =
reinterpret_cast<GSocketNotifierSource *>(source);
308 (
void)
new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
309 g_source_set_can_recurse(&socketNotifierSource->source,
true);
310 g_source_attach(&socketNotifierSource->source, mainContext);
313 source = g_source_new(&timerSourceFuncs,
sizeof(GTimerSource));
314 g_source_set_name(source,
"[Qt] GTimerSource");
315 timerSource =
reinterpret_cast<GTimerSource *>(source);
316 (
void)
new (&timerSource->timerList) QTimerInfoList();
317 timerSource->processEventsFlags = QEventLoop::AllEvents;
318 timerSource->runWithIdlePriority =
false;
319 g_source_set_can_recurse(&timerSource->source,
true);
320 g_source_attach(&timerSource->source, mainContext);
322 source = g_source_new(&idleTimerSourceFuncs,
sizeof(GIdleTimerSource));
323 g_source_set_name(source,
"[Qt] GIdleTimerSource");
324 idleTimerSource =
reinterpret_cast<GIdleTimerSource *>(source);
325 idleTimerSource->timerSource = timerSource;
326 g_source_set_can_recurse(&idleTimerSource->source,
true);
327 g_source_attach(&idleTimerSource->source, mainContext);
347QEventDispatcherGlib::~QEventDispatcherGlib()
349 Q_D(QEventDispatcherGlib);
352 d->timerSource->timerList.clearTimers();
353 d->timerSource->timerList.~QTimerInfoList();
354 g_source_destroy(&d->timerSource->source);
355 g_source_unref(&d->timerSource->source);
356 d->timerSource =
nullptr;
357 g_source_destroy(&d->idleTimerSource->source);
358 g_source_unref(&d->idleTimerSource->source);
359 d->idleTimerSource =
nullptr;
362 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
363 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
364 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
367 d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
368 g_source_destroy(&d->socketNotifierSource->source);
369 g_source_unref(&d->socketNotifierSource->source);
370 d->socketNotifierSource =
nullptr;
373 g_source_destroy(&d->postEventSource->source);
374 g_source_unref(&d->postEventSource->source);
375 d->postEventSource =
nullptr;
377 Q_ASSERT(d->mainContext !=
nullptr);
378#if GLIB_CHECK_VERSION (2
, 22
, 0
)
379 g_main_context_pop_thread_default (d->mainContext);
381 g_main_context_unref(d->mainContext);
382 d->mainContext =
nullptr;
385bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
387 Q_D(QEventDispatcherGlib);
389 const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents);
396 QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
397 d->timerSource->processEventsFlags = flags;
399 if (!(flags & QEventLoop::EventLoopExec)) {
401 d->timerSource->runWithIdlePriority =
false;
404 bool result = g_main_context_iteration(d->mainContext, canWait);
405 while (!result && canWait)
406 result = g_main_context_iteration(d->mainContext, canWait);
408 d->timerSource->processEventsFlags = savedFlags;
416void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
419 int sockfd =
int(notifier->socket());
420 const auto type = notifier->type();
423 qWarning(
"QSocketNotifier: Internal error");
425 }
else if (notifier->thread() != thread()
426 || thread() != QThread::currentThread()) {
427 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
432 Q_D(QEventDispatcherGlib);
435 GPollFDWithQSocketNotifier *p =
new GPollFDWithQSocketNotifier;
436 p->pollfd.fd = sockfd;
438 case QSocketNotifier::Read:
439 p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
441 case QSocketNotifier::Write:
442 p->pollfd.events = G_IO_OUT | G_IO_HUP | G_IO_ERR;
444 case QSocketNotifier::Exception:
445 p->pollfd.events = G_IO_PRI | G_IO_HUP | G_IO_ERR;
448 p->socketNotifier = notifier;
450 d->socketNotifierSource->pollfds.append(p);
452 g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
455void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
459 if (notifier->socket() < 0) {
460 qWarning(
"QSocketNotifier: Internal error");
462 }
else if (notifier->thread() != thread()
463 || thread() != QThread::currentThread()) {
464 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
469 Q_D(QEventDispatcherGlib);
471 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
472 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
473 if (p->socketNotifier == notifier) {
475 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
477 d->socketNotifierSource->pollfds.removeAt(i);
481 if (i <= d->socketNotifierSource->activeNotifierPos)
482 --d->socketNotifierSource->activeNotifierPos;
489void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval,
490 Qt::TimerType timerType, QObject *object)
493 if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
494 qWarning(
"QEventDispatcherGlib::registerTimer: invalid arguments");
496 }
else if (object->thread() != thread() || thread() != QThread::currentThread()) {
497 qWarning(
"QEventDispatcherGlib::registerTimer: timers cannot be started from another thread");
502 Q_D(QEventDispatcherGlib);
503 d->timerSource->timerList.registerTimer(timerId, interval, timerType, object);
QEventDispatcherGlibPrivate * d