inputd: correctly pass on resize events

Signed-off-by: Anhad Singh <andypython@protonmail.com>
This commit is contained in:
Anhad Singh
2023-07-20 19:20:56 +10:00
parent e457f03935
commit a153c8bc1c
10 changed files with 178 additions and 80 deletions
+89 -18
View File
@@ -1,6 +1,7 @@
#![feature(iter_next_chunk)]
use std::fs::File;
use std::io::{Error, Read};
use std::mem;
pub struct Handle(File);
@@ -19,33 +20,103 @@ impl Handle {
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)]
pub enum CommandTy {
enum CmdTy {
Unknown = 0,
Activate,
Deactivate,
Resize,
}
#[repr(C)]
pub struct Command {
pub ty: CommandTy,
pub value: usize,
impl From<u8> for CmdTy {
fn from(value: u8) -> Self {
match value {
1 => CmdTy::Activate,
2 => CmdTy::Deactivate,
3 => CmdTy::Resize,
_ => CmdTy::Unknown,
}
}
}
impl Command {
pub fn new(ty: CommandTy, value: usize) -> Self {
Self { ty, value }
}
pub enum Cmd {
// TODO(andypython): #VT should really need to be a `u8`.
Activate(usize /* #VT */),
Deactivate(usize /* #VT */),
Resize {
// TODO(andypython): do we really need to pass the VT here?
vt: usize,
/// ## Panics
/// This function panics if the buffer is not `sizeof::<Command>()` bytes wide.
pub fn parse<'a>(buffer: &'a [u8]) -> &'a Command {
assert_eq!(buffer.len(), core::mem::size_of::<Command>());
unsafe { &*(buffer.as_ptr() as *const Command) }
}
width: u32,
height: u32,
stride: u32,
},
}
pub fn into_bytes(self) -> [u8; mem::size_of::<Command>()] {
unsafe { core::mem::transmute(self) }
impl Cmd {
fn ty(&self) -> CmdTy {
match self {
Cmd::Activate(_) => CmdTy::Activate,
Cmd::Deactivate(_) => CmdTy::Deactivate,
Cmd::Resize { .. } => CmdTy::Resize,
}
}
}
pub fn send_comand(file: &mut File, command: Cmd) -> Result<(), syscall::Error> {
use std::os::fd::AsRawFd;
let mut result = vec![];
result.push(command.ty() as u8);
match command {
Cmd::Activate(vt) | Cmd::Deactivate(vt) => result.extend_from_slice(&vt.to_le_bytes()),
Cmd::Resize {
vt,
width,
height,
stride,
} => {
result.extend_from_slice(&vt.to_le_bytes());
result.extend(width.to_le_bytes());
result.extend(height.to_le_bytes());
result.extend(stride.to_le_bytes());
}
};
let written = syscall::write(file.as_raw_fd() as usize, &result)?;
// XXX: Ensure all of the data is written.
assert_eq!(written, result.len());
Ok(())
}
pub fn parse_command(buffer: &[u8]) -> Option<Cmd> {
const U32_SIZE: usize = core::mem::size_of::<u32>();
const USIZE_SIZE: usize = core::mem::size_of::<usize>();
let mut parser = buffer.iter().cloned();
let command = CmdTy::from(parser.next()?);
let vt = usize::from_le_bytes(parser.next_chunk::<USIZE_SIZE>().ok()?);
match command {
CmdTy::Activate => Some(Cmd::Activate(vt)),
CmdTy::Deactivate => Some(Cmd::Deactivate(vt)),
CmdTy::Resize => {
let width = parser.next_chunk::<U32_SIZE>().ok()?;
let height = parser.next_chunk::<U32_SIZE>().ok()?;
let stride = parser.next_chunk::<U32_SIZE>().ok()?;
Some(Cmd::Resize {
vt,
width: u32::from_le_bytes(width),
height: u32::from_le_bytes(height),
stride: u32::from_le_bytes(stride),
})
}
CmdTy::Unknown => None,
}
}
+23 -13
View File
@@ -13,11 +13,12 @@
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{self, Read, Write};
use std::io::{Read, Write};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use inputd::{Command, CommandTy};
use inputd::Cmd;
use orbclient::{Event, EventOption};
use syscall::{Error as SysError, EventFlags, Packet, SchemeMut, EINVAL};
@@ -166,15 +167,25 @@ impl SchemeMut for InputScheme {
_ => (),
},
EventOption::Resize(resize_event) => {
if let Some((_, file, current)) = self.active_vt.as_mut() {
inputd::send_comand(
file,
Cmd::Resize {
vt: current.clone(),
width: resize_event.width,
height: resize_event.height,
// TODO(andypython): Figure out how to get the stride.
stride: resize_event.width,
},
)?;
}
}
_ => continue,
}
let deactivate = |file: &mut File, id: usize| -> io::Result<()> {
let command = Command::new(CommandTy::Deactivate, id).into_bytes();
file.write(&command)?;
Ok(())
};
if let Some(new_active) = new_active_opt {
if let Some(vt) = self.vts.get(&new_active).cloned() {
if let Some((_, file, current)) = self.active_vt.as_mut() {
@@ -183,20 +194,19 @@ impl SchemeMut for InputScheme {
continue;
}
deactivate(file, *current).unwrap();
inputd::send_comand(file, Cmd::Deactivate(*current))?;
} else {
let id = self.next_vt_id.load(Ordering::SeqCst) - 1;
let mut vt = File::open(self.vts.get_mut(&id).unwrap().as_ref()).unwrap();
deactivate(&mut vt, id).unwrap();
inputd::send_comand(&mut vt, Cmd::Deactivate(id))?;
}
log::info!("inputd: switching to VT #{new_active} (`{vt}`)");
let mut file = File::open(vt.as_ref()).unwrap();
file.write(&Command::new(CommandTy::Activate, new_active).into_bytes())
.unwrap();
inputd::send_comand(&mut file, Cmd::Activate(new_active))?;
self.active_vt = Some((vt.clone(), file, new_active));
} else {
log::warn!("inputd: switch to non-existent VT #{new_active} was requested");
@@ -294,7 +304,7 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> {
last_allocated == *vt
};
// The activate VT is not the same as the VT that the consumer is listening to
// The activate VT is not the same as the VT that the consumer is listening to
// for events.
if !should_notify {
continue;