breadx_special_events/
lib.rs1#![no_std]
22
23extern crate alloc;
24
25use alloc::{boxed::Box, collections::VecDeque, sync::Arc, vec::Vec};
26use breadx::{
27 display::{Display, DisplayBase, RawReply, RawRequest},
28 protocol::Event,
29 Result,
30};
31use slab::Slab;
32
33#[cfg(feature = "async")]
34use breadx::display::{AsyncDisplay, AsyncDisplayExt, AsyncStatus, CanBeAsyncDisplay};
35#[cfg(feature = "async")]
36use core::task::Context;
37
38pub struct SpecialEventDisplay<Dpy: ?Sized> {
44 event_queue: VecDeque<Event>,
46 special_event_queues: Slab<VecDeque<Event>>,
48 classifiers: Vec<Classifier>,
50 display: Dpy,
52}
53
54struct Classifier {
55 classify: Box<dyn FnMut(&Event) -> bool + Send + Sync + 'static>,
57 key: usize,
59}
60
61impl<Dpy> From<Dpy> for SpecialEventDisplay<Dpy> {
62 fn from(display: Dpy) -> Self {
63 Self {
64 event_queue: VecDeque::new(),
65 special_event_queues: Slab::new(),
66 classifiers: Vec::new(),
67 display,
68 }
69 }
70}
71
72impl<Dpy: ?Sized> AsRef<Dpy> for SpecialEventDisplay<Dpy> {
73 fn as_ref(&self) -> &Dpy {
74 &self.display
75 }
76}
77
78impl<Dpy: ?Sized> AsMut<Dpy> for SpecialEventDisplay<Dpy> {
79 fn as_mut(&mut self) -> &mut Dpy {
80 &mut self.display
81 }
82}
83
84impl<Dpy> SpecialEventDisplay<Dpy> {
85 pub fn into_inner(self) -> Dpy {
87 self.display
88 }
89}
90
91impl<Dpy: ?Sized> SpecialEventDisplay<Dpy> {
92 pub fn create_special_event_queue(
96 &mut self,
97 classifier: impl FnMut(&Event) -> bool + Send + Sync + 'static,
98 ) -> usize {
99 let key = self.special_event_queues.insert(VecDeque::new());
101
102 self.classifiers.push(Classifier {
104 classify: Box::new(classifier),
105 key,
106 });
107
108 key
109 }
110
111 pub fn remove_special_event_queue(&mut self, key: usize) {
113 self.classifiers.retain(|classifier| classifier.key != key);
115
116 self.special_event_queues.remove(key);
118 }
119
120 fn enqueue_event(&mut self, event: Event) {
122 for classifier in &mut self.classifiers {
124 if (classifier.classify)(&event) {
125 self.special_event_queues[classifier.key].push_back(event);
127 return;
128 }
129 }
130
131 self.event_queue.push_back(event);
133 }
134}
135
136impl<Dpy: DisplayBase + ?Sized> SpecialEventDisplay<Dpy> {
137 fn poll_for_some_event(
139 &mut self,
140 mut until: impl FnMut(&mut Self) -> Option<Event>,
141 ) -> Result<Option<Event>> {
142 loop {
143 if let Some(event) = until(self) {
144 return Ok(Some(event));
145 }
146
147 let event = match self.display.poll_for_event()? {
149 Some(event) => event,
150 None => return Ok(None),
151 };
152
153 self.enqueue_event(event);
154 }
155 }
156
157 pub fn poll_for_special_event(&mut self, key: usize) -> Result<Option<Event>> {
159 self.poll_for_some_event(|this| this.special_event_queues[key].pop_front())
160 }
161}
162
163impl<Dpy: Display + ?Sized> SpecialEventDisplay<Dpy> {
164 fn wait_for_some_event(
166 &mut self,
167 mut until: impl FnMut(&mut Self) -> Option<Event>,
168 ) -> Result<Event> {
169 loop {
170 if let Some(event) = until(self) {
171 return Ok(event);
172 }
173
174 let event = self.display.wait_for_event()?;
176
177 self.enqueue_event(event);
178 }
179 }
180
181 pub fn wait_for_special_event(&mut self, key: usize) -> Result<Event> {
183 self.wait_for_some_event(|this| this.special_event_queues[key].pop_front())
184 }
185}
186
187#[cfg(feature = "async")]
188impl<Dpy: AsyncDisplay + ?Sized> SpecialEventDisplay<Dpy> {
189 pub async fn wait_for_special_event_async(&mut self, key: usize) -> Result<Event> {
191 loop {
192 if let Some(event) = self.special_event_queues[key].pop_front() {
193 return Ok(event);
194 }
195
196 let event = self.display.wait_for_event().await?;
197
198 self.enqueue_event(event);
199 }
200 }
201}
202
203impl<D: DisplayBase + ?Sized> DisplayBase for SpecialEventDisplay<D> {
204 fn setup(&self) -> &Arc<breadx::protocol::xproto::Setup> {
205 self.display.setup()
206 }
207
208 fn default_screen_index(&self) -> usize {
209 self.display.default_screen_index()
210 }
211
212 fn poll_for_event(&mut self) -> Result<Option<Event>> {
213 self.poll_for_some_event(|this| this.event_queue.pop_front())
214 }
215
216 fn poll_for_reply_raw(&mut self, seq: u64) -> Result<Option<RawReply>> {
217 self.display.poll_for_reply_raw(seq)
218 }
219}
220
221impl<D: Display + ?Sized> Display for SpecialEventDisplay<D> {
222 fn send_request_raw(&mut self, req: RawRequest<'_, '_>) -> Result<u64> {
223 self.display.send_request_raw(req)
224 }
225
226 fn flush(&mut self) -> Result<()> {
227 self.display.flush()
228 }
229
230 fn generate_xid(&mut self) -> Result<u32> {
231 self.display.generate_xid()
232 }
233
234 fn maximum_request_length(&mut self) -> Result<usize> {
235 self.display.maximum_request_length()
236 }
237
238 fn synchronize(&mut self) -> Result<()> {
239 self.display.synchronize()
240 }
241
242 fn wait_for_reply_raw(&mut self, seq: u64) -> Result<RawReply> {
243 self.display.wait_for_reply_raw(seq)
244 }
245
246 fn wait_for_event(&mut self) -> Result<Event> {
247 self.wait_for_some_event(|this| this.event_queue.pop_front())
248 }
249
250 fn check_for_error(&mut self, seq: u64) -> Result<()> {
251 self.display.check_for_error(seq)
252 }
253}
254
255#[cfg(feature = "async")]
256impl<D: CanBeAsyncDisplay + ?Sized> CanBeAsyncDisplay for SpecialEventDisplay<D> {
257 fn format_request(
258 &mut self,
259 req: &mut RawRequest<'_, '_>,
260 ctx: &mut Context<'_>,
261 ) -> Result<AsyncStatus<u64>> {
262 self.display.format_request(req, ctx)
263 }
264
265 fn try_flush(&mut self, ctx: &mut Context<'_>) -> Result<AsyncStatus<()>> {
266 self.display.try_flush(ctx)
267 }
268
269 fn try_generate_xid(&mut self, ctx: &mut Context<'_>) -> Result<AsyncStatus<u32>> {
270 self.display.try_generate_xid(ctx)
271 }
272
273 fn try_maximum_request_length(&mut self, ctx: &mut Context<'_>) -> Result<AsyncStatus<usize>> {
274 self.display.try_maximum_request_length(ctx)
275 }
276
277 fn try_send_request_raw(
278 &mut self,
279 req: &mut RawRequest<'_, '_>,
280 ctx: &mut Context<'_>,
281 ) -> Result<AsyncStatus<()>> {
282 self.display.try_send_request_raw(req, ctx)
283 }
284
285 fn try_wait_for_event(&mut self, ctx: &mut Context<'_>) -> Result<AsyncStatus<Event>> {
286 loop {
287 let event = match self.display.try_wait_for_event(ctx)? {
288 AsyncStatus::Ready(event) => event,
289 stats => return Ok(stats),
290 };
291
292 self.enqueue_event(event);
293
294 if let Some(event) = self.event_queue.pop_front() {
295 return Ok(AsyncStatus::Ready(event));
296 }
297 }
298 }
299
300 fn try_wait_for_reply_raw(
301 &mut self,
302 seq: u64,
303 ctx: &mut Context<'_>,
304 ) -> Result<AsyncStatus<RawReply>> {
305 self.display.try_wait_for_reply_raw(seq, ctx)
306 }
307
308 fn try_check_for_error(&mut self, seq: u64, ctx: &mut Context<'_>) -> Result<AsyncStatus<()>> {
309 self.display.try_check_for_error(seq, ctx)
310 }
311}
312
313#[cfg(feature = "async")]
314impl<D: AsyncDisplay + ?Sized> AsyncDisplay for SpecialEventDisplay<D> {
315 fn poll_for_interest(
316 &mut self,
317 interest: breadx::display::Interest,
318 callback: &mut dyn FnMut(&mut dyn AsyncDisplay, &mut Context<'_>) -> Result<()>,
319 ctx: &mut Context<'_>,
320 ) -> core::task::Poll<Result<()>> {
321 self.display.poll_for_interest(interest, callback, ctx)
322 }
323}