feat(pointer): virtio tablet as 2nd input dev (driver per-instance VAs, abs/btn decode), input server serves 2 devices on one notif; display software cursor, bar click switches window, presses/releases to front window in its px; k-ui hit-tests (press focuses, release on same presses, field only focuses)

This commit is contained in:
2026-10-28 16:50:20 +01:00
parent 0de13f124d
commit 1401af3d82
22 changed files with 545 additions and 46 deletions

View File

@@ -4,6 +4,8 @@
extern crate libkos;
use driver_input_virtio::VirtioInputDevice;
use input_server::server::{InputServer, MAX_DEVICES, Pair};
use libkos::device::{self, KIND_UART_16550, KIND_VIRTIO};
use port_input_device::InputDevice;
use types::bounded::CapSlot;
@@ -12,17 +14,24 @@ libkos::entry!(main);
fn main() {
let ep = CapSlot::new(0).unwrap();
// Init hands over the keyboard (virtio) or, failing that, the UART.
let dev = device::receive_device(ep);
match (dev.kind, dev.mmio) {
// Init hands over the input devices, two (a keyboard, a tablet), each
// virtio or, failing a keyboard, the UART; either may be none.
let first = device::receive_device(ep);
let second = device::receive_device(ep);
let irqs = [first.irq, second.irq];
let tablet = match (second.kind, second.mmio) {
(KIND_VIRTIO, Some(mmio)) => VirtioInputDevice::try_new(mmio, 1),
_ => None,
};
match (first.kind, first.mmio) {
(KIND_VIRTIO, Some(mmio)) => {
if let Some(d) = driver_input_virtio::VirtioInputDevice::try_new(mmio) {
run(d, dev.irq, ep);
if let Some(d) = VirtioInputDevice::try_new(mmio, 0) {
run(Pair { first: d, second: tablet }, irqs, ep);
}
}
(KIND_UART_16550, Some(mmio)) => {
if let Some(d) = driver_input_uart::UartInputDevice::new(mmio) {
run(d, dev.irq, ep);
run(Pair { first: d, second: tablet }, irqs, ep);
}
}
_ => {}
@@ -31,12 +40,18 @@ fn main() {
libkos::syscall::exit();
}
/// Serves `device`, woken by its interrupt when it has one.
/// Serves `device`, woken by its interrupts when it has them.
#[inline(never)]
fn run<D: InputDevice>(device: D, irq: Option<CapSlot>, ep: CapSlot) -> ! {
let mut srv = match irq.filter(|irq| device::bind_irq(*irq).is_ok()) {
Some(irq) => input_server::server::InputServer::with_irq(device, irq),
None => input_server::server::InputServer::new(device),
fn run<D: InputDevice>(device: D, irqs: [Option<CapSlot>; MAX_DEVICES], ep: CapSlot) -> ! {
let mut lines = [CapSlot::const_new(0); MAX_DEVICES];
let mut n = 0;
for irq in irqs.into_iter().flatten() {
lines[n] = irq;
n += 1;
}
let mut srv = match n > 0 && device::bind_irqs(&lines[..n]).is_ok() {
true => InputServer::with_irqs(device, irqs),
false => InputServer::new(device),
};
server_framework::serve(&mut srv, ep)
}