Files
RedBear-OS/inputd/src/lib.rs
T
2024-12-23 19:02:24 +01:00

124 lines
3.0 KiB
Rust

#![feature(iter_next_chunk)]
use std::cmp;
use std::fs::File;
use std::io::{Error, Read, Write};
use std::mem::size_of;
use std::os::fd::{AsFd, BorrowedFd};
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
std::slice::from_raw_parts((p as *const T) as *const u8, size_of::<T>())
}
unsafe fn any_as_u8_slice_mut<T: Sized>(p: &mut T) -> &mut [u8] {
std::slice::from_raw_parts_mut((p as *mut T) as *mut u8, size_of::<T>())
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct VtActivate {
pub vt: usize,
}
pub struct DisplayHandle(File);
impl DisplayHandle {
pub fn new<S: Into<String>>(device_name: S) -> Result<Self, Error> {
let path = format!("/scheme/input/handle/display/{}", device_name.into());
Ok(Self(File::open(path)?))
}
pub fn new_early<S: Into<String>>(device_name: S) -> Result<Self, Error> {
let path = format!("/scheme/input/handle_early/display/{}", device_name.into());
Ok(Self(File::open(path)?))
}
// The return value is the display identifier. It will be used to uniquely
// identify the display on activation events.
pub fn register_vt(&mut self) -> Result<usize, Error> {
self.0.read(&mut [])
}
pub fn read_vt_event(&mut self) -> Result<Option<VtEvent>, Error> {
let mut event = VtEvent {
kind: VtEventKind::Resize,
vt: usize::MAX,
width: u32::MAX,
height: u32::MAX,
stride: u32::MAX,
};
let nread = self.0.read(unsafe { any_as_u8_slice_mut(&mut event) })?;
if nread == 0 {
Ok(None)
} else {
assert_eq!(nread, size_of::<VtEvent>());
Ok(Some(event))
}
}
pub fn inner(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
pub struct ControlHandle(File);
impl ControlHandle {
pub fn new() -> Result<Self, Error> {
let path = format!("/scheme/input/control");
Ok(Self(File::open(path)?))
}
pub fn activate_vt(&mut self, vt: usize) -> Result<usize, Error> {
let cmd = VtActivate { vt };
self.0.write(unsafe { any_as_u8_slice(&cmd) })
}
}
#[derive(Debug)]
#[repr(usize)]
pub enum VtEventKind {
Activate,
Deactivate,
Resize,
}
#[derive(Debug)]
#[repr(C)]
pub struct VtEvent {
pub kind: VtEventKind,
pub vt: usize,
pub width: u32,
pub height: u32,
pub stride: u32,
}
// Keep synced with orbital's SyncRect
#[derive(Debug, Copy, Clone)]
#[repr(packed)]
pub struct Damage {
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
}
impl Damage {
#[must_use]
pub fn clip(mut self, width: i32, height: i32) -> Self {
// Clip damage
self.x = cmp::min(self.x, width);
if self.x + self.width > width {
self.width -= cmp::min(self.width, width - self.x);
}
self.y = cmp::min(self.y, height);
if self.y + self.height > height {
self.height = cmp::min(self.height, height - self.y);
}
self
}
}