scheme.rs 6.46 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1
use std::collections::BTreeMap;
Jeremy Soller's avatar
Jeremy Soller committed
2
use std::{mem, slice, str};
Jeremy Soller's avatar
Jeremy Soller committed
3

Jeremy Soller's avatar
Jeremy Soller committed
4
use orbclient::{Event, EventOption};
5
use syscall::{Result, Error, EACCES, EBADF, ENOENT, SchemeMut};
Jeremy Soller's avatar
Jeremy Soller committed
6 7

use display::Display;
Jeremy Soller's avatar
Jeremy Soller committed
8
use screen::{Screen, GraphicScreen, TextScreen};
Jeremy Soller's avatar
Jeremy Soller committed
9 10

pub struct DisplayScheme {
11 12
    width: usize,
    height: usize,
13 14
    active: usize,
    pub screens: BTreeMap<usize, Box<Screen>>
Jeremy Soller's avatar
Jeremy Soller committed
15 16 17
}

impl DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
18
    pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
19
        let mut screens: BTreeMap<usize, Box<Screen>> = BTreeMap::new();
Jeremy Soller's avatar
Jeremy Soller committed
20 21 22 23 24 25 26 27 28 29

        let mut screen_i = 1;
        for &screen_type in spec.iter() {
            if screen_type {
                screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height, onscreen))));
            } else {
                screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height, onscreen))));
            }
            screen_i += 1;
        }
Jeremy Soller's avatar
Jeremy Soller committed
30 31

        DisplayScheme {
32 33
            width: width,
            height: height,
34 35
            active: 1,
            screens: screens
Jeremy Soller's avatar
Jeremy Soller committed
36 37 38 39
        }
    }

    pub fn will_block(&self, id: usize) -> bool {
40
        if let Some(screen) = self.screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
41 42 43 44 45 46 47
            screen.will_block()
        } else {
            false
        }
    }
}

48 49
impl SchemeMut for DisplayScheme {
    fn open(&mut self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
50
        if path == b"input" {
Jeremy Soller's avatar
Jeremy Soller committed
51 52 53 54 55
            if uid == 0 {
                Ok(0)
            } else {
                Err(Error::new(EACCES))
            }
Jeremy Soller's avatar
Jeremy Soller committed
56
        } else {
57 58 59
            let path_str = str::from_utf8(path).unwrap_or("").trim_matches('/');
            let mut parts = path_str.split('/');
            let id = parts.next().unwrap_or("").parse::<usize>().unwrap_or(0);
60
            if self.screens.contains_key(&id) {
61 62 63 64 65
                for cmd in parts {
                    if cmd == "activate" {
                        self.active = id;
                    }
                }
Jeremy Soller's avatar
Jeremy Soller committed
66 67 68 69 70 71 72
                Ok(id)
            } else {
                Err(Error::new(ENOENT))
            }
        }
    }

Jeremy Soller's avatar
Jeremy Soller committed
73
    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
74 75 76
        Ok(id)
    }

77 78
    fn fevent(&mut self, id: usize, flags: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
79
            screen.event(flags).and(Ok(id))
Jeremy Soller's avatar
Jeremy Soller committed
80 81 82 83 84
        } else {
            Err(Error::new(EBADF))
        }
    }

85 86 87 88 89 90 91 92
    fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result<usize> {
        if let Some(screen) = self.screens.get(&id) {
            screen.map(offset, size)
        } else {
            Err(Error::new(EBADF))
        }
    }

93
    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
94
        let path_str = if id == 0 {
95
            format!("display:input/{}/{}", self.width, self.height)
96
        } else if let Some(screen) = self.screens.get(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
97
            format!("display:{}/{}/{}", id, screen.width(), screen.height())
Jeremy Soller's avatar
Jeremy Soller committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
        } else {
            return Err(Error::new(EBADF));
        };

        let path = path_str.as_bytes();

        let mut i = 0;
        while i < buf.len() && i < path.len() {
            buf[i] = path[i];
            i += 1;
        }

        Ok(i)
    }

113 114 115
    fn fsync(&mut self, id: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
            if id == self.active {
Jeremy Soller's avatar
Jeremy Soller committed
116 117 118 119 120 121 122 123
                screen.sync();
            }
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }

124 125
    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
126 127 128 129 130 131
            screen.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

132
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
133 134 135
        if id == 0 {
            if buf.len() == 1 && buf[0] >= 0xF4 {
                let new_active = (buf[0] - 0xF4) as usize + 1;
136 137
                if let Some(mut screen) = self.screens.get_mut(&new_active) {
                    self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
138 139 140 141
                    screen.redraw();
                }
                Ok(1)
            } else {
Jeremy Soller's avatar
Jeremy Soller committed
142 143 144
                let events = unsafe { slice::from_raw_parts(buf.as_ptr() as *const Event, buf.len()/mem::size_of::<Event>()) };

                for event in events.iter() {
Jeremy Soller's avatar
Jeremy Soller committed
145 146 147
                    let mut new_active_opt = None;
                    match event.to_option() {
                        EventOption::Key(key_event) => match key_event.scancode {
Jeremy Soller's avatar
Jeremy Soller committed
148
                            f @ 0x3B ... 0x44 => { // F1 through F10
Jeremy Soller's avatar
Jeremy Soller committed
149
                                new_active_opt = Some((f - 0x3A) as usize);
Jeremy Soller's avatar
Jeremy Soller committed
150 151
                            },
                            0x57 => { // F11
Jeremy Soller's avatar
Jeremy Soller committed
152
                                new_active_opt = Some(11);
Jeremy Soller's avatar
Jeremy Soller committed
153 154
                            },
                            0x58 => { // F12
Jeremy Soller's avatar
Jeremy Soller committed
155
                                new_active_opt = Some(12);
Jeremy Soller's avatar
Jeremy Soller committed
156
                            },
Jeremy Soller's avatar
Jeremy Soller committed
157 158 159 160 161 162 163 164 165
                            _ => ()
                        },
                        EventOption::Resize(resize_event) => {
                            println!("Resizing to {}, {}", resize_event.width, resize_event.height);
                            for (_screen_id, screen) in self.screens.iter_mut() {
                                screen.resize(resize_event.width as usize, resize_event.height as usize);
                            }
                        },
                        _ => ()
Jeremy Soller's avatar
Jeremy Soller committed
166 167 168
                    };

                    if let Some(new_active) = new_active_opt {
169 170
                        if let Some(mut screen) = self.screens.get_mut(&new_active) {
                            self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
171 172 173
                            screen.redraw();
                        }
                    } else {
174
                        if let Some(mut screen) = self.screens.get_mut(&self.active) {
Jeremy Soller's avatar
Jeremy Soller committed
175 176 177
                            screen.input(event);
                        }
                    }
Jeremy Soller's avatar
Jeremy Soller committed
178
                }
Jeremy Soller's avatar
Jeremy Soller committed
179 180

                Ok(events.len() * mem::size_of::<Event>())
Jeremy Soller's avatar
Jeremy Soller committed
181
            }
182 183
        } else if let Some(mut screen) = self.screens.get_mut(&id) {
            screen.write(buf, id == self.active)
Jeremy Soller's avatar
Jeremy Soller committed
184 185 186 187 188
        } else {
            Err(Error::new(EBADF))
        }
    }

189 190
    fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
        if let Some(mut screen) = self.screens.get_mut(&id) {
Jeremy Soller's avatar
Jeremy Soller committed
191 192 193 194 195 196
            screen.seek(pos, whence)
        } else {
            Err(Error::new(EBADF))
        }
    }

197
    fn close(&mut self, _id: usize) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
198 199 200
        Ok(0)
    }
}