261QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
262 : mainContext(context)
264#if GLIB_MAJOR_VERSION == 2
&& GLIB_MINOR_VERSION < 32
265 if (qEnvironmentVariableIsEmpty(
"QT_NO_THREADED_GLIB")) {
266 Q_CONSTINIT
static QBasicMutex mutex;
267 QMutexLocker locker(&mutex);
268 if (!g_thread_supported())
274 g_main_context_ref(mainContext);
276 QCoreApplication *app = QCoreApplication::instance();
277 if (app && QThread::currentThread() == app->thread()) {
278 mainContext = g_main_context_default();
279 g_main_context_ref(mainContext);
281 mainContext = g_main_context_new();
285#if GLIB_CHECK_VERSION (2
, 22
, 0
)
286 g_main_context_push_thread_default (mainContext);
290 GSource *source = g_source_new(&postEventSourceFuncs,
sizeof(GPostEventSource));
291 g_source_set_name(source,
"[Qt] GPostEventSource");
292 postEventSource =
reinterpret_cast<GPostEventSource *>(source);
294 postEventSource->serialNumber.storeRelaxed(1);
295 postEventSource->d =
this;
296 g_source_set_can_recurse(&postEventSource->source,
true);
297 g_source_attach(&postEventSource->source, mainContext);
300 source = g_source_new(&socketNotifierSourceFuncs,
sizeof(GSocketNotifierSource));
301 g_source_set_name(source,
"[Qt] GSocketNotifierSource");
302 socketNotifierSource =
reinterpret_cast<GSocketNotifierSource *>(source);
303 (
void)
new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
304 g_source_set_can_recurse(&socketNotifierSource->source,
true);
305 g_source_attach(&socketNotifierSource->source, mainContext);
308 source = g_source_new(&timerSourceFuncs,
sizeof(GTimerSource));
309 g_source_set_name(source,
"[Qt] GTimerSource");
310 timerSource =
reinterpret_cast<GTimerSource *>(source);
311 (
void)
new (&timerSource->timerList) QTimerInfoList();
312 timerSource->processEventsFlags = QEventLoop::AllEvents;
313 timerSource->runWithIdlePriority =
false;
314 g_source_set_can_recurse(&timerSource->source,
true);
315 g_source_attach(&timerSource->source, mainContext);
317 source = g_source_new(&idleTimerSourceFuncs,
sizeof(GIdleTimerSource));
318 g_source_set_name(source,
"[Qt] GIdleTimerSource");
319 idleTimerSource =
reinterpret_cast<GIdleTimerSource *>(source);
320 idleTimerSource->timerSource = timerSource;
321 g_source_set_can_recurse(&idleTimerSource->source,
true);
322 g_source_attach(&idleTimerSource->source, mainContext);
342QEventDispatcherGlib::~QEventDispatcherGlib()
344 Q_D(QEventDispatcherGlib);
347 d->timerSource->timerList.clearTimers();
348 d->timerSource->timerList.~QTimerInfoList();
349 g_source_destroy(&d->timerSource->source);
350 g_source_unref(&d->timerSource->source);
351 d->timerSource =
nullptr;
352 g_source_destroy(&d->idleTimerSource->source);
353 g_source_unref(&d->idleTimerSource->source);
354 d->idleTimerSource =
nullptr;
357 for (
int i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
358 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds[i];
359 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
362 d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
363 g_source_destroy(&d->socketNotifierSource->source);
364 g_source_unref(&d->socketNotifierSource->source);
365 d->socketNotifierSource =
nullptr;
368 g_source_destroy(&d->postEventSource->source);
369 g_source_unref(&d->postEventSource->source);
370 d->postEventSource =
nullptr;
372 Q_ASSERT(d->mainContext !=
nullptr);
373#if GLIB_CHECK_VERSION (2
, 22
, 0
)
374 g_main_context_pop_thread_default (d->mainContext);
376 g_main_context_unref(d->mainContext);
377 d->mainContext =
nullptr;
380bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
382 Q_D(QEventDispatcherGlib);
384 const bool canWait = flags.testAnyFlag(QEventLoop::WaitForMoreEvents);
391 QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
392 d->timerSource->processEventsFlags = flags;
394 if (!(flags & QEventLoop::EventLoopExec)) {
396 d->timerSource->runWithIdlePriority =
false;
399 bool result = g_main_context_iteration(d->mainContext, canWait);
400 while (!result && canWait)
401 result = g_main_context_iteration(d->mainContext, canWait);
403 d->timerSource->processEventsFlags = savedFlags;
411void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
414 int sockfd =
int(notifier->socket());
415 int type = notifier->type();
418 qWarning(
"QSocketNotifier: Internal error");
420 }
else if (notifier->thread() != thread()
421 || thread() != QThread::currentThread()) {
422 qWarning(
"QSocketNotifier: socket notifiers cannot be enabled from another thread");
427 Q_D(QEventDispatcherGlib);
430 GPollFDWithQSocketNotifier *p =
new GPollFDWithQSocketNotifier;
431 p->pollfd.fd = sockfd;
433 case QSocketNotifier::Read:
434 p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
436 case QSocketNotifier::Write:
437 p->pollfd.events = G_IO_OUT | G_IO_HUP | G_IO_ERR;
439 case QSocketNotifier::Exception:
440 p->pollfd.events = G_IO_PRI | G_IO_HUP | G_IO_ERR;
443 p->socketNotifier = notifier;
445 d->socketNotifierSource->pollfds.append(p);
447 g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
450void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
454 if (notifier->socket() < 0) {
455 qWarning(
"QSocketNotifier: Internal error");
457 }
else if (notifier->thread() != thread()
458 || thread() != QThread::currentThread()) {
459 qWarning(
"QSocketNotifier: socket notifiers cannot be disabled from another thread");
464 Q_D(QEventDispatcherGlib);
466 for (qsizetype i = 0; i < d->socketNotifierSource->pollfds.size(); ++i) {
467 GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
468 if (p->socketNotifier == notifier) {
470 g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
472 d->socketNotifierSource->pollfds.removeAt(i);
476 if (i <= d->socketNotifierSource->activeNotifierPos)
477 --d->socketNotifierSource->activeNotifierPos;
484void QEventDispatcherGlib::registerTimer(Qt::TimerId timerId, Duration interval,
485 Qt::TimerType timerType, QObject *object)
488 if (qToUnderlying(timerId) < 1 || interval < 0ns || !object) {
489 qWarning(
"QEventDispatcherGlib::registerTimer: invalid arguments");
491 }
else if (object->thread() != thread() || thread() != QThread::currentThread()) {
492 qWarning(
"QEventDispatcherGlib::registerTimer: timers cannot be started from another thread");
497 Q_D(QEventDispatcherGlib);
498 d->timerSource->timerList.registerTimer(timerId, interval, timerType, object);
QEventDispatcherGlibPrivate * d