feat(display): input routed via display server to focused app; input Subscribe; uses caps badged + Delegate
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use server_framework::Server;
|
||||
use server_framework::{Decode, Encode, MALFORMED, Server};
|
||||
|
||||
use port_input_device::{InputDevice, InputEvent};
|
||||
use types::bounded::CapSlot;
|
||||
@@ -14,12 +14,14 @@ pub struct InputServer<D: InputDevice> {
|
||||
events: [Option<InputEvent>; BUFFERED],
|
||||
head: usize,
|
||||
len: usize,
|
||||
/// Signalled when events arrive (the display server's notification).
|
||||
subscriber: Option<CapSlot>,
|
||||
}
|
||||
|
||||
impl<D: InputDevice> InputServer<D> {
|
||||
/// A server that reads the device only when a client asks.
|
||||
pub fn new(device: D) -> Self {
|
||||
Self { device, irq: None, events: [None; BUFFERED], head: 0, len: 0 }
|
||||
Self { device, irq: None, events: [None; BUFFERED], head: 0, len: 0, subscriber: None }
|
||||
}
|
||||
|
||||
/// A server woken by `irq` (routed and bound by the caller): it drains
|
||||
@@ -61,6 +63,10 @@ impl<D: InputDevice> InputServer<D> {
|
||||
&self.device
|
||||
}
|
||||
|
||||
pub fn subscriber(&self) -> Option<CapSlot> {
|
||||
self.subscriber
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn replace_device_for_test(&mut self, device: D) {
|
||||
self.device = device;
|
||||
@@ -82,9 +88,25 @@ impl<D: InputDevice> Server for InputServer<D> {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_call(&mut self, _badge: usize, words: [usize; 4], cap: Option<CapSlot>) -> ([usize; 4], Option<CapSlot>) {
|
||||
if words[0] == types::input::SUBSCRIBE {
|
||||
self.subscriber = cap;
|
||||
return ([0; 4], None);
|
||||
}
|
||||
match InputRequest::decode(words) {
|
||||
Some(request) => (self.handle(request).encode(), None),
|
||||
None => ([MALFORMED, 0, 0, 0], None),
|
||||
}
|
||||
}
|
||||
|
||||
fn signal(&mut self, _bits: usize) {
|
||||
let mut arrived = false;
|
||||
while let Some(event) = self.device.poll() {
|
||||
self.push(event);
|
||||
arrived = true;
|
||||
}
|
||||
if let (true, Some(subscriber)) = (arrived, self.subscriber) {
|
||||
let _ = libkos::syscall::signal(subscriber);
|
||||
}
|
||||
self.device.acknowledge();
|
||||
if let Some(irq) = self.irq {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::adapters::mock::MockInputDevice;
|
||||
use crate::protocol::*;
|
||||
use crate::server::InputServer;
|
||||
use server_framework::Server;
|
||||
use server_framework::{Decode, Encode, Server};
|
||||
|
||||
fn test_server() -> InputServer<MockInputDevice> {
|
||||
InputServer::new(MockInputDevice::new())
|
||||
@@ -85,3 +85,14 @@ fn a_full_buffer_drops_the_oldest_event() {
|
||||
InputResponse::Event(InputEvent::KeyDown(Key::Char(8)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_subscription_is_kept_and_other_requests_still_work() {
|
||||
let mut server = test_server();
|
||||
let note = types::bounded::CapSlot::new(7);
|
||||
let (reply, _) = server.handle_call(0, [types::input::SUBSCRIBE, 0, 0, 0], note);
|
||||
assert_eq!(reply, [0; 4]);
|
||||
assert_eq!(server.subscriber(), note);
|
||||
let (reply, _) = server.handle_call(0, InputRequest::PollEvent.encode(), None);
|
||||
assert_eq!(InputResponse::decode(reply), Some(InputResponse::NoEvent));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user