layer_shika_composition/
event_loop.rs1use crate::{Error, Result};
2use layer_shika_adapters::errors::EventLoopError;
3use layer_shika_adapters::platform::calloop::{
4 EventSource, Generic, Interest, Mode, PostAction, RegistrationToken, TimeoutAction, Timer,
5 channel,
6};
7use layer_shika_adapters::{AppState, WaylandSystemOps};
8use std::cell::RefCell;
9use std::os::unix::io::AsFd;
10use std::rc::{Rc, Weak};
11use std::time::{Duration, Instant};
12
13pub trait FromAppState<'a> {
14 fn from_app_state(app_state: &'a mut AppState) -> Self;
15}
16
17pub struct ShellEventLoop {
22 inner: Rc<RefCell<dyn WaylandSystemOps>>,
23}
24
25impl ShellEventLoop {
26 pub fn new(inner: Rc<RefCell<dyn WaylandSystemOps>>) -> Self {
27 Self { inner }
28 }
29
30 pub fn run(&mut self) -> Result<()> {
31 self.inner.borrow_mut().run()?;
32 Ok(())
33 }
34
35 pub fn get_handle(&self) -> EventLoopHandle {
36 EventLoopHandle::new(Rc::downgrade(&self.inner))
37 }
38}
39
40pub struct EventLoopHandle {
44 system: Weak<RefCell<dyn WaylandSystemOps>>,
45}
46
47impl EventLoopHandle {
48 pub fn new(system: Weak<RefCell<dyn WaylandSystemOps>>) -> Self {
49 Self { system }
50 }
51
52 pub fn insert_source<S, F, R>(&self, source: S, callback: F) -> Result<RegistrationToken>
56 where
57 S: EventSource<Ret = R> + 'static,
58 F: FnMut(S::Event, &mut S::Metadata, &mut AppState) -> R + 'static,
59 {
60 let system = self.system.upgrade().ok_or(Error::SystemDropped)?;
61 let loop_handle = system.borrow().event_loop_handle();
62
63 loop_handle.insert_source(source, callback).map_err(|e| {
64 Error::Adapter(
65 EventLoopError::InsertSource {
66 message: format!("{e:?}"),
67 }
68 .into(),
69 )
70 })
71 }
72
73 pub fn add_timer<F>(&self, duration: Duration, mut callback: F) -> Result<RegistrationToken>
77 where
78 F: FnMut(Instant, &mut AppState) -> TimeoutAction + 'static,
79 {
80 let timer = Timer::from_duration(duration);
81 self.insert_source(timer, move |deadline, (), app_state| {
82 callback(deadline, app_state)
83 })
84 }
85
86 pub fn add_timer_at<F>(&self, deadline: Instant, mut callback: F) -> Result<RegistrationToken>
90 where
91 F: FnMut(Instant, &mut AppState) -> TimeoutAction + 'static,
92 {
93 let timer = Timer::from_deadline(deadline);
94 self.insert_source(timer, move |deadline, (), app_state| {
95 callback(deadline, app_state)
96 })
97 }
98
99 pub fn add_channel<T, F>(
103 &self,
104 mut callback: F,
105 ) -> Result<(RegistrationToken, channel::Sender<T>)>
106 where
107 T: 'static,
108 F: FnMut(T, &mut AppState) + 'static,
109 {
110 let (sender, receiver) = channel::channel();
111 let token = self.insert_source(receiver, move |event, (), app_state| {
112 if let channel::Event::Msg(msg) = event {
113 callback(msg, app_state);
114 }
115 })?;
116 Ok((token, sender))
117 }
118
119 pub fn add_fd<F, T>(
123 &self,
124 fd: T,
125 interest: Interest,
126 mode: Mode,
127 mut callback: F,
128 ) -> Result<RegistrationToken>
129 where
130 T: AsFd + 'static,
131 F: FnMut(&mut AppState) + 'static,
132 {
133 let generic = Generic::new(fd, interest, mode);
134 self.insert_source(generic, move |_readiness, _fd, app_state| {
135 callback(app_state);
136 Ok(PostAction::Continue)
137 })
138 }
139}