diff --git a/Ladybird/AppKit/Application/EventLoopImplementation.mm b/Ladybird/AppKit/Application/EventLoopImplementation.mm index fcff07d147..db3f4b73e3 100644 --- a/Ladybird/AppKit/Application/EventLoopImplementation.mm +++ b/Ladybird/AppKit/Application/EventLoopImplementation.mm @@ -106,7 +106,7 @@ static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notificatio // before dispatching the event, which allows it to be triggered again. CFSocketEnableCallBacks(socket, notification_type); - Core::NotifierActivationEvent event(notifier.fd()); + Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); notifier.dispatch_event(event); // This manual process of enabling the callbacks also seems to require waking the event loop, diff --git a/Ladybird/Qt/EventLoopImplementationQt.cpp b/Ladybird/Qt/EventLoopImplementationQt.cpp index ee9f326c83..fce7d6e6c3 100644 --- a/Ladybird/Qt/EventLoopImplementationQt.cpp +++ b/Ladybird/Qt/EventLoopImplementationQt.cpp @@ -118,7 +118,7 @@ bool EventLoopManagerQt::unregister_timer(int timer_id) static void qt_notifier_activated(Core::Notifier& notifier) { - Core::NotifierActivationEvent event(notifier.fd()); + Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); notifier.dispatch_event(event); } diff --git a/Userland/Libraries/LibCore/Event.h b/Userland/Libraries/LibCore/Event.h index a3bdf01e30..ecacfbe460 100644 --- a/Userland/Libraries/LibCore/Event.h +++ b/Userland/Libraries/LibCore/Event.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -78,19 +79,30 @@ private: int m_timer_id; }; +enum class NotificationType { + None = 0, + Read = 1, + Write = 2, +}; + +AK_ENUM_BITWISE_OPERATORS(NotificationType); + class NotifierActivationEvent final : public Event { public: - explicit NotifierActivationEvent(int fd) + explicit NotifierActivationEvent(int fd, NotificationType type) : Event(Event::NotifierActivation) , m_fd(fd) + , m_type(type) { } ~NotifierActivationEvent() = default; int fd() const { return m_fd; } + NotificationType type() const { return m_type; } private: int m_fd; + NotificationType m_type; }; class ChildEvent final : public Event { diff --git a/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp b/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp index 91209c5a47..beffbad16d 100644 --- a/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp +++ b/Userland/Libraries/LibCore/EventLoopImplementationUnix.cpp @@ -157,12 +157,10 @@ retry: add_fd_to_set(thread_data.wake_pipe_fds[0], read_fds); for (auto& notifier : thread_data.notifiers) { - if (notifier->type() == Notifier::Type::Read) + if (has_flag(notifier->type(), Notifier::Type::Read)) add_fd_to_set(notifier->fd(), read_fds); - if (notifier->type() == Notifier::Type::Write) + if (has_flag(notifier->type(), Notifier::Type::Write)) add_fd_to_set(notifier->fd(), write_fds); - if (notifier->type() == Notifier::Type::Exceptional) - TODO(); } bool has_pending_events = ThreadEventQueue::current().has_pending_events(); @@ -257,12 +255,14 @@ try_select_again: // Handle file system notifiers by making them normal events. for (auto& notifier : thread_data.notifiers) { - if (notifier->type() == Notifier::Type::Read && FD_ISSET(notifier->fd(), &read_fds)) { - ThreadEventQueue::current().post_event(*notifier, make(notifier->fd())); - } - if (notifier->type() == Notifier::Type::Write && FD_ISSET(notifier->fd(), &write_fds)) { - ThreadEventQueue::current().post_event(*notifier, make(notifier->fd())); - } + auto type = NotificationType::None; + if (FD_ISSET(notifier->fd(), &read_fds)) + type |= NotificationType::Read; + if (FD_ISSET(notifier->fd(), &write_fds)) + type |= NotificationType::Write; + type &= notifier->type(); + if (type != NotificationType::None) + ThreadEventQueue::current().post_event(*notifier, make(notifier->fd(), type)); } } diff --git a/Userland/Libraries/LibCore/Notifier.cpp b/Userland/Libraries/LibCore/Notifier.cpp index 064799bcb5..e328810044 100644 --- a/Userland/Libraries/LibCore/Notifier.cpp +++ b/Userland/Libraries/LibCore/Notifier.cpp @@ -27,6 +27,9 @@ void Notifier::set_enabled(bool enabled) { if (m_fd < 0) return; + if (enabled == m_is_enabled) + return; + m_is_enabled = enabled; if (enabled) Core::EventLoop::register_notifier({}, *this); else @@ -41,6 +44,18 @@ void Notifier::close() m_fd = -1; } +void Notifier::set_type(Type type) +{ + if (m_is_enabled) { + // FIXME: Directly communicate intent to the EventLoop. + set_enabled(false); + m_type = type; + set_enabled(true); + } else { + m_type = type; + } +} + void Notifier::event(Core::Event& event) { if (event.type() == Core::Event::NotifierActivation) { diff --git a/Userland/Libraries/LibCore/Notifier.h b/Userland/Libraries/LibCore/Notifier.h index a3fa27ebdb..eb43bc1717 100644 --- a/Userland/Libraries/LibCore/Notifier.h +++ b/Userland/Libraries/LibCore/Notifier.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include namespace Core { @@ -15,12 +16,7 @@ class Notifier final : public EventReceiver { C_OBJECT(Notifier); public: - enum class Type { - None, - Read, - Write, - Exceptional, - }; + using Type = NotificationType; virtual ~Notifier() override; @@ -32,7 +28,7 @@ public: int fd() const { return m_fd; } Type type() const { return m_type; } - void set_type(Type type) { m_type = type; } + void set_type(Type type); void event(Core::Event&) override; @@ -40,6 +36,7 @@ private: Notifier(int fd, Type type, EventReceiver* parent = nullptr); int m_fd { -1 }; + bool m_is_enabled { false }; Type m_type { Type::None }; };