Implicitly create a new VT for each consumer
Instead of requiring the graphics driver to create a fixed set of VTs in advance. This fixes the graphical interface when there is a graphics driver but no boot framebuffer. Previously in that case vesad would exit before it creates any VT and thus no consumer could show anything as their VT was missing. In the future creating new VTs on the fly could also allow a display manager to use a separate VT for each user session.
This commit is contained in:
@@ -46,7 +46,7 @@ pub struct Display {
|
||||
|
||||
impl Display {
|
||||
pub fn open_first_vt() -> io::Result<Self> {
|
||||
let input_handle = ConsumerHandle::for_vt(1)?;
|
||||
let input_handle = ConsumerHandle::new_vt()?;
|
||||
|
||||
let map = match input_handle.open_display() {
|
||||
Ok(display) => {
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct DisplayMap {
|
||||
|
||||
impl Display {
|
||||
pub fn open_vt(vt: usize) -> io::Result<Self> {
|
||||
let input_handle = ConsumerHandle::for_vt(vt)?;
|
||||
let input_handle = ConsumerHandle::new_vt()?;
|
||||
|
||||
if let Ok(display_handle) = Self::open_display(&input_handle) {
|
||||
let map = display_handle
|
||||
|
||||
@@ -15,12 +15,6 @@ mod framebuffer;
|
||||
mod scheme;
|
||||
|
||||
fn main() {
|
||||
let mut spec = Vec::new();
|
||||
|
||||
for _ in env::args().skip(1) {
|
||||
spec.push(());
|
||||
}
|
||||
|
||||
if env::var("FRAMEBUFFER_WIDTH").is_err() {
|
||||
println!("vesad: No boot framebuffer");
|
||||
return;
|
||||
@@ -78,16 +72,12 @@ fn main() {
|
||||
};
|
||||
}
|
||||
|
||||
redox_daemon::Daemon::new(|daemon| inner(daemon, framebuffers, &spec))
|
||||
redox_daemon::Daemon::new(|daemon| inner(daemon, framebuffers))
|
||||
.expect("failed to create daemon");
|
||||
}
|
||||
fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec<FrameBuffer>, spec: &[()]) -> ! {
|
||||
fn inner(daemon: redox_daemon::Daemon, framebuffers: Vec<FrameBuffer>) -> ! {
|
||||
let mut inputd_display_handle = DisplayHandle::new_early("vesa").unwrap();
|
||||
|
||||
for &() in spec.iter() {
|
||||
inputd_display_handle.register_vt().unwrap();
|
||||
}
|
||||
|
||||
let mut scheme = GraphicsScheme::new(FbAdapter { framebuffers }, "display.vesa".to_owned());
|
||||
|
||||
user_data! {
|
||||
|
||||
+2
-8
@@ -17,11 +17,11 @@ unsafe fn any_as_u8_slice_mut<T: Sized>(p: &mut T) -> &mut [u8] {
|
||||
pub struct ConsumerHandle(File);
|
||||
|
||||
impl ConsumerHandle {
|
||||
pub fn for_vt(vt: usize) -> Result<Self, Error> {
|
||||
pub fn new_vt() -> Result<Self, Error> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.custom_flags(O_NONBLOCK as i32)
|
||||
.open(format!("/scheme/input/consumer/{vt}"))?;
|
||||
.open(format!("/scheme/input/consumer"))?;
|
||||
Ok(Self(file))
|
||||
}
|
||||
|
||||
@@ -70,12 +70,6 @@ impl DisplayHandle {
|
||||
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,
|
||||
|
||||
+25
-24
@@ -131,17 +131,19 @@ impl Scheme for InputScheme {
|
||||
let handle_ty = match command {
|
||||
"producer" => Handle::Producer,
|
||||
"consumer" => {
|
||||
let target = path_parts
|
||||
.next()
|
||||
.and_then(|x| x.parse::<usize>().ok())
|
||||
.ok_or(SysError::new(EINVAL))?;
|
||||
let vt = self.next_vt_id.fetch_add(1, Ordering::Relaxed);
|
||||
self.vts.insert(vt);
|
||||
|
||||
if self.active_vt.is_none() {
|
||||
self.switch_vt(vt);
|
||||
}
|
||||
|
||||
Handle::Consumer {
|
||||
events: EventFlags::empty(),
|
||||
pending: Vec::new(),
|
||||
needs_handoff: false,
|
||||
notified: false,
|
||||
vt: target,
|
||||
vt,
|
||||
}
|
||||
}
|
||||
"handle" | "handle_early" => {
|
||||
@@ -258,24 +260,8 @@ impl Scheme for InputScheme {
|
||||
Ok(copy)
|
||||
}
|
||||
|
||||
Handle::Display {
|
||||
pending, device, ..
|
||||
} => {
|
||||
// FIXME Create new VT through a write instead and return a NewVt event on read
|
||||
// This allows also returning events for VT (de)activation from the display handle
|
||||
// rather than pushing them to the graphics driver.
|
||||
if buf.is_empty() {
|
||||
// Trying to do an empty read creates a new VT.
|
||||
let vt = self.next_vt_id.fetch_add(1, Ordering::SeqCst);
|
||||
log::info!("inputd: created VT #{vt} for {device}");
|
||||
self.vts.insert(vt);
|
||||
|
||||
if self.active_vt.is_none() {
|
||||
self.switch_vt(vt);
|
||||
}
|
||||
|
||||
Ok(vt)
|
||||
} else if buf.len() % size_of::<VtEvent>() == 0 {
|
||||
Handle::Display { pending, .. } => {
|
||||
if buf.len() % size_of::<VtEvent>() == 0 {
|
||||
let copy = core::cmp::min(pending.len(), buf.len() / size_of::<VtEvent>());
|
||||
|
||||
for (i, event) in pending.drain(..copy).enumerate() {
|
||||
@@ -472,7 +458,22 @@ impl Scheme for InputScheme {
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self, _id: usize) -> syscall::Result<usize> {
|
||||
fn close(&mut self, id: usize) -> syscall::Result<usize> {
|
||||
let handle = self.handles.get(&id).ok_or(SysError::new(EINVAL))?;
|
||||
|
||||
match *handle {
|
||||
Handle::Consumer { vt, .. } => {
|
||||
self.vts.remove(&vt);
|
||||
if self.active_vt == Some(vt) {
|
||||
if let Some(&new_vt) = self.vts.last() {
|
||||
self.switch_vt(new_vt);
|
||||
} else {
|
||||
self.active_vt = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user