feat(display): input routed via display server to focused app; input Subscribe; uses caps badged + Delegate

This commit is contained in:
2026-10-27 16:38:16 +01:00
parent 64ec5df379
commit 2845d190f0
18 changed files with 286 additions and 26 deletions

View File

@@ -0,0 +1,56 @@
//! Who gets input: the display server is the input server's only client
//! and passes events on to the app in focus, the one that subscribed last.
//! Apps out of focus get nothing.
/// Events received and not yet polled by the app in focus.
const QUEUED: usize = 32;
pub struct Focus<N: Copy> {
/// The app in focus: its badge and the notification it gave to be told.
holder: Option<(usize, N)>,
events: [[usize; 4]; QUEUED],
head: usize,
len: usize,
}
impl<N: Copy> Focus<N> {
pub const fn new() -> Self {
Self { holder: None, events: [[0; 4]; QUEUED], head: 0, len: 0 }
}
/// `badge` takes focus; what the last holder had not read is dropped.
pub fn subscribe(&mut self, badge: usize, notify: N) {
self.holder = Some((badge, notify));
self.len = 0;
}
/// Queues an event (as the input server sends it) for the holder;
/// returns whom to tell. With no holder the event goes nowhere.
pub fn push(&mut self, event: [usize; 4]) -> Option<N> {
let (_, notify) = self.holder?;
if self.len == QUEUED {
self.head = (self.head + 1) % QUEUED;
self.len -= 1;
}
self.events[(self.head + self.len) % QUEUED] = event;
self.len += 1;
Some(notify)
}
/// The next event for `badge`, if it is in focus and one is queued.
pub fn poll(&mut self, badge: usize) -> Option<[usize; 4]> {
if self.holder.is_none_or(|(b, _)| b != badge) || self.len == 0 {
return None;
}
let event = self.events[self.head];
self.head = (self.head + 1) % QUEUED;
self.len -= 1;
Some(event)
}
}
impl<N: Copy> Default for Focus<N> {
fn default() -> Self {
Self::new()
}
}