scheme.rs 9.37 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};
Jeremy Soller's avatar
Jeremy Soller committed
5
use syscall::{Result, Error, EACCES, EBADF, EINVAL, ENOENT, O_NONBLOCK, 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 11 12 13 14 15 16 17 18 19 20 21
#[derive(Clone)]
enum HandleKind {
    Input,
    Screen(usize),
}

#[derive(Clone)]
struct Handle {
    kind: HandleKind,
    flags: usize,
}

Jeremy Soller's avatar
Jeremy Soller committed
22
pub struct DisplayScheme {
23 24
    width: usize,
    height: usize,
25
    active: usize,
26 27 28
    pub screens: BTreeMap<usize, Box<Screen>>,
    next_id: usize,
    handles: BTreeMap<usize, Handle>,
Jeremy Soller's avatar
Jeremy Soller committed
29 30 31
}

impl DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
32
    pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme {
Jeremy Soller's avatar
Jeremy Soller committed
33
        let mut screens: BTreeMap<usize, Box<Screen>> = BTreeMap::new();
Jeremy Soller's avatar
Jeremy Soller committed
34 35 36 37 38 39 40 41 42 43

        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
44 45

        DisplayScheme {
46 47
            width: width,
            height: height,
48
            active: 1,
49 50 51
            screens: screens,
            next_id: 0,
            handles: BTreeMap::new(),
Jeremy Soller's avatar
Jeremy Soller committed
52 53 54
        }
    }

55 56 57 58 59 60 61 62 63 64 65 66 67 68
    pub fn can_read(&self, id: usize) -> Option<usize> {
        if let Some(handle) = self.handles.get(&id) {
            if let HandleKind::Screen(screen_i) = handle.kind {
                if let Some(screen) = self.screens.get(&screen_i) {
                    match screen.can_read() {
                        Some(count) => return Some(count),
                        None => if handle.flags & O_NONBLOCK == O_NONBLOCK {
                            return Some(0);
                        } else {
                            return None;
                        }
                    }
                }
            }
Jeremy Soller's avatar
Jeremy Soller committed
69
        }
70 71

        Some(0)
Jeremy Soller's avatar
Jeremy Soller committed
72 73 74
    }
}

75
impl SchemeMut for DisplayScheme {
76
    fn open(&mut self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
77
        if path == b"input" {
Jeremy Soller's avatar
Jeremy Soller committed
78
            if uid == 0 {
79 80 81 82 83 84 85 86 87
                let id = self.next_id;
                self.next_id += 1;

                self.handles.insert(id, Handle {
                    kind: HandleKind::Input,
                    flags: flags
                });

                Ok(id)
Jeremy Soller's avatar
Jeremy Soller committed
88 89 90
            } else {
                Err(Error::new(EACCES))
            }
Jeremy Soller's avatar
Jeremy Soller committed
91
        } else {
92 93
            let path_str = str::from_utf8(path).unwrap_or("").trim_matches('/');
            let mut parts = path_str.split('/');
94 95
            let screen_i = parts.next().unwrap_or("").parse::<usize>().unwrap_or(0);
            if self.screens.contains_key(&screen_i) {
96 97
                for cmd in parts {
                    if cmd == "activate" {
98
                        self.active = screen_i;
99 100
                    }
                }
101 102 103 104 105 106 107 108 109

                let id = self.next_id;
                self.next_id += 1;

                self.handles.insert(id, Handle {
                    kind: HandleKind::Screen(screen_i),
                    flags: flags
                });

Jeremy Soller's avatar
Jeremy Soller committed
110 111 112 113 114 115 116
                Ok(id)
            } else {
                Err(Error::new(ENOENT))
            }
        }
    }

117 118 119 120 121
    fn dup(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
        if ! buf.is_empty() {
            return Err(Error::new(EINVAL));
        }

122 123 124 125 126 127 128 129
        let handle = self.handles.get(&id).map(|handle| handle.clone()).ok_or(Error::new(EBADF))?;

        let new_id = self.next_id;
        self.next_id += 1;

        self.handles.insert(new_id, handle.clone());

        Ok(new_id)
Jeremy Soller's avatar
Jeremy Soller committed
130 131
    }

132
    fn fevent(&mut self, id: usize, flags: usize) -> Result<usize> {
133 134 135
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        if let HandleKind::Screen(screen_i) = handle.kind {
Jeremy Soller's avatar
Jeremy Soller committed
136
            if let Some(screen) = self.screens.get_mut(&screen_i) {
137 138
                return screen.event(flags).and(Ok(screen_i));
            }
Jeremy Soller's avatar
Jeremy Soller committed
139
        }
140 141

        Err(Error::new(EBADF))
Jeremy Soller's avatar
Jeremy Soller committed
142 143
    }

144
    fn fmap(&mut self, id: usize, offset: usize, size: usize) -> Result<usize> {
145 146 147 148 149 150
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        if let HandleKind::Screen(screen_i) = handle.kind {
            if let Some(screen) = self.screens.get(&screen_i) {
                return screen.map(offset, size);
            }
151
        }
152 153

        Err(Error::new(EBADF))
154 155
    }

156
    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
157 158 159 160 161 162 163 164 165 166 167
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        let path_str = match handle.kind {
            HandleKind::Input => {
                format!("display:input/{}/{}", self.width, self.height)
            },
            HandleKind::Screen(screen_i) => if let Some(screen) = self.screens.get(&screen_i) {
                format!("display:{}/{}/{}", screen_i, screen.width(), screen.height())
            } else {
                return Err(Error::new(EBADF));
            }
Jeremy Soller's avatar
Jeremy Soller committed
168 169 170 171 172 173 174 175 176 177 178 179 180
        };

        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)
    }

181
    fn fsync(&mut self, id: usize) -> Result<usize> {
182 183 184
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        if let HandleKind::Screen(screen_i) = handle.kind {
Jeremy Soller's avatar
Jeremy Soller committed
185
            if let Some(screen) = self.screens.get_mut(&screen_i) {
186 187 188 189
                if screen_i == self.active {
                    screen.sync();
                }
                return Ok(0);
Jeremy Soller's avatar
Jeremy Soller committed
190 191
            }
        }
192 193

        Err(Error::new(EBADF))
Jeremy Soller's avatar
Jeremy Soller committed
194 195
    }

196
    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
197 198 199
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        if let HandleKind::Screen(screen_i) = handle.kind {
Jeremy Soller's avatar
Jeremy Soller committed
200
            if let Some(screen) = self.screens.get_mut(&screen_i) {
201 202
                return screen.read(buf);
            }
Jeremy Soller's avatar
Jeremy Soller committed
203
        }
204 205

        Err(Error::new(EBADF))
Jeremy Soller's avatar
Jeremy Soller committed
206 207
    }

208
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
209 210 211 212
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        match handle.kind {
            HandleKind::Input => if buf.len() == 1 && buf[0] >= 0xF4 {
Jeremy Soller's avatar
Jeremy Soller committed
213
                let new_active = (buf[0] - 0xF4) as usize + 1;
Jeremy Soller's avatar
Jeremy Soller committed
214
                if let Some(screen) = self.screens.get_mut(&new_active) {
215
                    self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
216 217 218 219
                    screen.redraw();
                }
                Ok(1)
            } else {
Jeremy Soller's avatar
Jeremy Soller committed
220 221 222
                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
223 224 225
                    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
226
                            f @ 0x3B ... 0x44 => { // F1 through F10
Jeremy Soller's avatar
Jeremy Soller committed
227
                                new_active_opt = Some((f - 0x3A) as usize);
Jeremy Soller's avatar
Jeremy Soller committed
228 229
                            },
                            0x57 => { // F11
Jeremy Soller's avatar
Jeremy Soller committed
230
                                new_active_opt = Some(11);
Jeremy Soller's avatar
Jeremy Soller committed
231 232
                            },
                            0x58 => { // F12
Jeremy Soller's avatar
Jeremy Soller committed
233
                                new_active_opt = Some(12);
Jeremy Soller's avatar
Jeremy Soller committed
234
                            },
Jeremy Soller's avatar
Jeremy Soller committed
235 236 237 238
                            _ => ()
                        },
                        EventOption::Resize(resize_event) => {
                            println!("Resizing to {}, {}", resize_event.width, resize_event.height);
239 240
                            self.width = resize_event.width as usize;
                            self.height = resize_event.height as usize;
241
                            for (screen_i, screen) in self.screens.iter_mut() {
Jeremy Soller's avatar
Jeremy Soller committed
242
                                screen.resize(resize_event.width as usize, resize_event.height as usize);
243
                                if *screen_i == self.active {
Jeremy Soller's avatar
Jeremy Soller committed
244 245
                                    screen.redraw();
                                }
Jeremy Soller's avatar
Jeremy Soller committed
246 247 248
                            }
                        },
                        _ => ()
Jeremy Soller's avatar
Jeremy Soller committed
249 250 251
                    };

                    if let Some(new_active) = new_active_opt {
Jeremy Soller's avatar
Jeremy Soller committed
252
                        if let Some(screen) = self.screens.get_mut(&new_active) {
253
                            self.active = new_active;
Jeremy Soller's avatar
Jeremy Soller committed
254 255 256
                            screen.redraw();
                        }
                    } else {
Jeremy Soller's avatar
Jeremy Soller committed
257
                        if let Some(screen) = self.screens.get_mut(&self.active) {
Jeremy Soller's avatar
Jeremy Soller committed
258 259 260
                            screen.input(event);
                        }
                    }
Jeremy Soller's avatar
Jeremy Soller committed
261
                }
Jeremy Soller's avatar
Jeremy Soller committed
262 263

                Ok(events.len() * mem::size_of::<Event>())
264
            },
Jeremy Soller's avatar
Jeremy Soller committed
265
            HandleKind::Screen(screen_i) => if let Some(screen) = self.screens.get_mut(&screen_i) {
266 267 268
                screen.write(buf, screen_i == self.active)
            } else {
                Err(Error::new(EBADF))
Jeremy Soller's avatar
Jeremy Soller committed
269 270 271 272
            }
        }
    }

273
    fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
274 275 276
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;

        if let HandleKind::Screen(screen_i) = handle.kind {
Jeremy Soller's avatar
Jeremy Soller committed
277
            if let Some(screen) = self.screens.get_mut(&screen_i) {
278 279
                return screen.seek(pos, whence);
            }
Jeremy Soller's avatar
Jeremy Soller committed
280
        }
281 282

        Err(Error::new(EBADF))
Jeremy Soller's avatar
Jeremy Soller committed
283 284
    }

285 286
    fn close(&mut self, id: usize) -> Result<usize> {
        self.handles.remove(&id).ok_or(Error::new(EBADF))?;
Jeremy Soller's avatar
Jeremy Soller committed
287 288 289
        Ok(0)
    }
}