123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- * Copyright (c) 2022-2023, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include "EventLoopImplementationQt.h"
- #include "EventLoopImplementationQtEventTarget.h"
- #include <AK/IDAllocator.h>
- #include <LibCore/Event.h>
- #include <LibCore/EventReceiver.h>
- #include <LibCore/Notifier.h>
- #include <LibCore/ThreadEventQueue.h>
- #include <QCoreApplication>
- #include <QTimer>
- namespace Ladybird {
- struct ThreadData;
- static thread_local ThreadData* s_thread_data;
- struct ThreadData {
- static ThreadData& the()
- {
- if (!s_thread_data) {
- // FIXME: Don't leak this.
- s_thread_data = new ThreadData;
- }
- return *s_thread_data;
- }
- IDAllocator timer_id_allocator;
- HashMap<int, NonnullOwnPtr<QTimer>> timers;
- HashMap<Core::Notifier*, NonnullOwnPtr<QSocketNotifier>> notifiers;
- };
- EventLoopImplementationQt::EventLoopImplementationQt()
- {
- }
- EventLoopImplementationQt::~EventLoopImplementationQt() = default;
- int EventLoopImplementationQt::exec()
- {
- if (is_main_loop())
- return QCoreApplication::exec();
- return m_event_loop.exec();
- }
- size_t EventLoopImplementationQt::pump(PumpMode mode)
- {
- auto result = Core::ThreadEventQueue::current().process();
- auto qt_mode = mode == PumpMode::WaitForEvents ? QEventLoop::WaitForMoreEvents : QEventLoop::AllEvents;
- if (is_main_loop())
- QCoreApplication::processEvents(qt_mode);
- else
- m_event_loop.processEvents(qt_mode);
- result += Core::ThreadEventQueue::current().process();
- return result;
- }
- void EventLoopImplementationQt::quit(int code)
- {
- if (is_main_loop())
- QCoreApplication::exit(code);
- else
- m_event_loop.exit(code);
- }
- void EventLoopImplementationQt::wake()
- {
- if (!is_main_loop())
- m_event_loop.wakeUp();
- }
- void EventLoopImplementationQt::post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&& event)
- {
- m_thread_event_queue.post_event(receiver, move(event));
- if (&m_thread_event_queue != &Core::ThreadEventQueue::current())
- wake();
- }
- static void qt_timer_fired(Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible, Core::EventReceiver& object)
- {
- if (should_fire_when_not_visible == Core::TimerShouldFireWhenNotVisible::No) {
- if (!object.is_visible_for_timer_purposes())
- return;
- }
- Core::TimerEvent event;
- object.dispatch_event(event);
- }
- int EventLoopManagerQt::register_timer(Core::EventReceiver& object, int milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible)
- {
- auto& thread_data = ThreadData::the();
- auto timer = make<QTimer>();
- timer->setInterval(milliseconds);
- timer->setSingleShot(!should_reload);
- auto timer_id = thread_data.timer_id_allocator.allocate();
- auto weak_object = object.make_weak_ptr();
- QObject::connect(timer, &QTimer::timeout, [should_fire_when_not_visible, weak_object = move(weak_object)] {
- auto object = weak_object.strong_ref();
- if (!object)
- return;
- qt_timer_fired(should_fire_when_not_visible, *object);
- });
- timer->start();
- thread_data.timers.set(timer_id, move(timer));
- return timer_id;
- }
- bool EventLoopManagerQt::unregister_timer(int timer_id)
- {
- auto& thread_data = ThreadData::the();
- thread_data.timer_id_allocator.deallocate(timer_id);
- return thread_data.timers.remove(timer_id);
- }
- static void qt_notifier_activated(Core::Notifier& notifier)
- {
- Core::NotifierActivationEvent event(notifier.fd(), notifier.type());
- notifier.dispatch_event(event);
- }
- void EventLoopManagerQt::register_notifier(Core::Notifier& notifier)
- {
- QSocketNotifier::Type type;
- switch (notifier.type()) {
- case Core::Notifier::Type::Read:
- type = QSocketNotifier::Read;
- break;
- case Core::Notifier::Type::Write:
- type = QSocketNotifier::Write;
- break;
- default:
- TODO();
- }
- auto socket_notifier = make<QSocketNotifier>(notifier.fd(), type);
- QObject::connect(socket_notifier, &QSocketNotifier::activated, [¬ifier] {
- qt_notifier_activated(notifier);
- });
- ThreadData::the().notifiers.set(¬ifier, move(socket_notifier));
- }
- void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier)
- {
- ThreadData::the().notifiers.remove(¬ifier);
- }
- void EventLoopManagerQt::did_post_event()
- {
- QCoreApplication::postEvent(m_main_thread_event_target.ptr(), new QtEventLoopManagerEvent(QtEventLoopManagerEvent::process_event_queue_event_type()));
- }
- bool EventLoopManagerQt::event_target_received_event(Badge<EventLoopImplementationQtEventTarget>, QEvent* event)
- {
- if (event->type() == QtEventLoopManagerEvent::process_event_queue_event_type()) {
- Core::ThreadEventQueue::current().process();
- return true;
- }
- return false;
- }
- EventLoopManagerQt::EventLoopManagerQt()
- : m_main_thread_event_target(make<EventLoopImplementationQtEventTarget>())
- {
- }
- EventLoopManagerQt::~EventLoopManagerQt() = default;
- NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerQt::make_implementation()
- {
- return adopt_own(*new EventLoopImplementationQt);
- }
- }
|