1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:48:11 +00:00

Ladybird: Move Qt-specific classes and functions to a Qt subdirectory

This will help a lot with developing chromes for different UI frameworks
where we can see which helper classes and processes are really using Qt
vs just using it to get at helper data.

As a bonus, remove Qt dependency from WebDriver.
This commit is contained in:
Andrew Kaster 2023-08-05 10:42:26 -06:00 committed by Andrew Kaster
parent ccaa423372
commit 391beef707
53 changed files with 160 additions and 157 deletions

View file

@ -0,0 +1,177 @@
/*
* 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(int timer_id, 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(timer_id);
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, [timer_id, should_fire_when_not_visible, weak_object = move(weak_object)] {
auto object = weak_object.strong_ref();
if (!object)
return;
qt_timer_fired(timer_id, 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.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, [&notifier] {
qt_notifier_activated(notifier);
});
ThreadData::the().notifiers.set(&notifier, move(socket_notifier));
}
void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier)
{
ThreadData::the().notifiers.remove(&notifier);
}
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);
}
}