1
0
Fork 0
forked from wry/wry

event-listener: add LazyEventSource

This commit is contained in:
Julian Orth 2026-03-05 18:08:01 +01:00
parent ce30901093
commit 8fc9ead21e
3 changed files with 82 additions and 2 deletions

View file

@ -68,6 +68,7 @@ use {
clone3::ensure_reaper,
clonecell::CloneCell,
errorfmt::ErrorFmt,
event_listener::handle_lazy_event_sources,
fdcloser::FdCloser,
nice::{did_elevate_scheduler, elevate_scheduler},
numcell::NumCell,
@ -377,6 +378,7 @@ fn start_compositor2(
copy_device_registry: Rc::new(CopyDeviceRegistry::new(&ring, &engine, &eventfd_cache)),
supports_presentation_feedback: Default::default(),
eventfd_cache,
lazy_event_sources: Default::default(),
});
state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state);
@ -577,6 +579,10 @@ fn start_global_event_handlers(state: &Rc<State>) -> Vec<SpawnedFuture<()>> {
Phase::PostLayout,
handle_xdg_surface_configure_events(state.clone()),
),
eng.spawn(
"lazy event sources",
handle_lazy_event_sources(state.clone()),
),
]
}

View file

@ -110,7 +110,7 @@ use {
clonecell::CloneCell,
copyhashmap::CopyHashMap,
errorfmt::ErrorFmt,
event_listener::{EventListener, EventSource},
event_listener::{EventListener, EventSource, LazyEventSources},
fdcloser::FdCloser,
hash_map_ext::HashMapExt,
linkedlist::LinkedList,
@ -290,6 +290,7 @@ pub struct State {
pub copy_device_registry: Rc<CopyDeviceRegistry>,
pub supports_presentation_feedback: Cell<bool>,
pub eventfd_cache: Rc<EventfdCache>,
pub lazy_event_sources: Rc<LazyEventSources>,
}
// impl Drop for State {
@ -1128,6 +1129,7 @@ impl State {
self.cpu_worker.clear();
self.wait_for_syncobj.clear();
self.xdg_surface_configure_events.clear();
self.lazy_event_sources.clear();
}
pub fn remove_toplevel_id(&self, id: ToplevelIdentifier) {

View file

@ -1,11 +1,28 @@
use {
crate::utils::linkedlist::{LinkedList, LinkedListIter, LinkedNode},
crate::{
state::State,
utils::{
linkedlist::{LinkedList, LinkedListIter, LinkedNode},
queue::AsyncQueue,
},
},
std::{
cell::Cell,
ops::Deref,
rc::{Rc, Weak},
},
};
pub async fn handle_lazy_event_sources(state: Rc<State>) {
loop {
let source = state.lazy_event_sources.queue.pop().await;
source.queued.set(false);
for listener in source.listeners.iter() {
listener.triggered();
}
}
}
pub struct EventSource<T: ?Sized> {
listeners: LinkedList<Weak<T>>,
on_attach: Cell<Option<Box<dyn FnOnce()>>>,
@ -15,6 +32,21 @@ pub struct EventListener<T: ?Sized> {
link: LinkedNode<Weak<T>>,
}
#[derive(Default)]
pub struct LazyEventSources {
queue: AsyncQueue<Rc<LazyEventSource>>,
}
pub trait LazyEventSourceListener {
fn triggered(self: Rc<Self>);
}
pub struct LazyEventSource {
sources: Rc<LazyEventSources>,
queued: Cell<bool>,
listeners: EventSource<dyn LazyEventSourceListener>,
}
impl<T: ?Sized> Default for EventSource<T> {
fn default() -> Self {
Self {
@ -39,6 +71,10 @@ impl<T: ?Sized> EventSource<T> {
self.listeners.is_not_empty()
}
pub fn is_empty(&self) -> bool {
self.listeners.is_empty()
}
pub fn on_attach(&self, f: Box<dyn FnOnce()>) {
self.on_attach.set(Some(f));
}
@ -83,3 +119,39 @@ impl<T: ?Sized> EventListener<T> {
self.link.upgrade()
}
}
impl Deref for LazyEventSource {
type Target = EventSource<dyn LazyEventSourceListener>;
fn deref(&self) -> &Self::Target {
&self.listeners
}
}
impl LazyEventSource {
#[expect(dead_code)]
pub fn trigger(self: &Rc<Self>) {
if self.listeners.is_empty() {
return;
}
if self.queued.replace(true) {
return;
}
self.sources.queue.push(self.clone());
}
}
impl LazyEventSources {
#[expect(dead_code)]
pub fn create_source(self: &Rc<Self>) -> Rc<LazyEventSource> {
Rc::new(LazyEventSource {
sources: self.clone(),
queued: Default::default(),
listeners: Default::default(),
})
}
pub fn clear(&self) {
self.queue.clear();
}
}