#![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(p: &T) -> &[u8] { std::slice::from_raw_parts((p as *const T) as *const u8, size_of::()) } unsafe fn any_as_u8_slice_mut(p: &mut T) -> &mut [u8] { std::slice::from_raw_parts_mut((p as *mut T) as *mut u8, size_of::()) } #[derive(Debug, Clone)] #[repr(C)] pub struct VtActivate { pub vt: usize, } pub struct DisplayHandle(File); impl DisplayHandle { pub fn new>(device_name: S) -> Result { let path = format!("/scheme/input/handle/display/{}", device_name.into()); Ok(Self(File::open(path)?)) } pub fn new_early>(device_name: S) -> Result { 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 { self.0.read(&mut []) } pub fn read_vt_event(&mut self) -> Result, 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::()); Ok(Some(event)) } } pub fn inner(&self) -> BorrowedFd<'_> { self.0.as_fd() } } pub struct ControlHandle(File); impl ControlHandle { pub fn new() -> Result { let path = format!("/scheme/input/control"); Ok(Self(File::open(path)?)) } pub fn activate_vt(&mut self, vt: usize) -> Result { 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 } }