Commit c6388ba0 authored by Jeremy Soller's avatar Jeremy Soller

Reorganize, update to add scroll event and WindowFlag for resize

parent 72ea1793
......@@ -2,20 +2,23 @@ use core::{char, mem, slice};
use core::ops::{Deref, DerefMut};
pub const EVENT_NONE: i64 = 0;
pub const EVENT_MOUSE: i64 = 1;
pub const EVENT_KEY: i64 = 2;
pub const EVENT_QUIT: i64 = 3;
pub const EVENT_FOCUS: i64 = 4;
pub const EVENT_MOVE: i64 = 5;
pub const EVENT_RESIZE: i64 = 6;
pub const EVENT_KEY: i64 = 1;
pub const EVENT_MOUSE: i64 = 2;
pub const EVENT_SCROLL: i64 = 3;
pub const EVENT_QUIT: i64 = 4;
pub const EVENT_FOCUS: i64 = 5;
pub const EVENT_MOVE: i64 = 6;
pub const EVENT_RESIZE: i64 = 7;
/// An optional event
#[derive(Copy, Clone, Debug)]
pub enum EventOption {
/// A mouse event
Mouse(MouseEvent),
/// A key event
Key(KeyEvent),
/// A mouse event
Mouse(MouseEvent),
/// A scroll event
Scroll(ScrollEvent),
/// A quit request event
Quit(QuitEvent),
/// A focus event
......@@ -56,8 +59,9 @@ impl Event {
pub fn to_option(self) -> EventOption {
match self.code {
EVENT_NONE => EventOption::None,
EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
......@@ -84,45 +88,6 @@ impl DerefMut for Event {
}
}
/// A event related to the mouse
#[derive(Copy, Clone, Debug)]
pub struct MouseEvent {
/// The x coordinate of the mouse
pub x: i32,
/// The y coordinate of the mouse
pub y: i32,
/// Was the left button pressed?
pub left_button: bool,
/// Was the middle button pressed?
pub middle_button: bool,
/// Was the right button pressed?
pub right_button: bool,
}
impl MouseEvent {
/// Convert to an `Event`
pub fn to_event(&self) -> Event {
Event {
code: EVENT_MOUSE,
a: self.x as i64,
b: self.y as i64,
c: self.left_button as i64 | (self.middle_button as i64) << 1 |
(self.right_button as i64) << 2,
}
}
/// Convert an `Event` to a `MouseEvent`
pub fn from_event(event: Event) -> MouseEvent {
MouseEvent {
x: event.a as i32,
y: event.b as i32,
left_button: event.c & 1 == 1,
middle_button: event.c & 2 == 2,
right_button: event.c & 4 == 4,
}
}
}
pub const K_A: u8 = 0x1E;
pub const K_B: u8 = 0x30;
pub const K_C: u8 = 0x2E;
......@@ -277,6 +242,74 @@ impl KeyEvent {
}
}
/// A event related to the mouse
#[derive(Copy, Clone, Debug)]
pub struct MouseEvent {
/// The x coordinate of the mouse
pub x: i32,
/// The y coordinate of the mouse
pub y: i32,
/// Was the left button pressed?
pub left_button: bool,
/// Was the middle button pressed?
pub middle_button: bool,
/// Was the right button pressed?
pub right_button: bool,
}
impl MouseEvent {
/// Convert to an `Event`
pub fn to_event(&self) -> Event {
Event {
code: EVENT_MOUSE,
a: self.x as i64,
b: self.y as i64,
c: self.left_button as i64 | (self.middle_button as i64) << 1 |
(self.right_button as i64) << 2,
}
}
/// Convert an `Event` to a `MouseEvent`
pub fn from_event(event: Event) -> MouseEvent {
MouseEvent {
x: event.a as i32,
y: event.b as i32,
left_button: event.c & 1 == 1,
middle_button: event.c & 2 == 2,
right_button: event.c & 4 == 4,
}
}
}
/// A event for scrolling the mouse
#[derive(Copy, Clone, Debug)]
pub struct ScrollEvent {
/// The x distance of the scroll
pub x: i32,
/// The y distance of the scroll
pub y: i32,
}
impl ScrollEvent {
/// Convert to an `Event`
pub fn to_event(&self) -> Event {
Event {
code: EVENT_SCROLL,
a: self.x as i64,
b: self.y as i64,
c: 0,
}
}
/// Convert an `Event` to a `ScrollEvent`
pub fn from_event(event: Event) -> ScrollEvent {
ScrollEvent {
x: event.a as i32,
y: event.b as i32,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct QuitEvent;
......
use std::{mem, slice, thread};
extern crate syscall;
use std::{env, mem, slice, thread};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, RawFd};
use super::syscall;
use color::Color;
use event::Event;
use event::{Event, EVENT_RESIZE};
use renderer::Renderer;
use WindowFlag;
pub fn get_display_size() -> Result<(u32, u32), String> {
let display_path = try!(env::var("DISPLAY").or(Err("DISPLAY not set")));
match File::open(&display_path) {
Ok(display) => {
let mut buf: [u8; 4096] = [0; 4096];
let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf).map_err(|err| format!("{}", err))?;
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
let res = path.split(":").nth(1).unwrap_or("");
let width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
let height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
Ok((width, height))
},
Err(err) => Err(format!("{}", err))
}
}
/// A window
pub struct Window {
......@@ -23,6 +40,8 @@ pub struct Window {
t: String,
/// True if the window should not wait for events
async: bool,
/// True if the window can be resized
resizable: bool,
/// The input scheme
file: File,
/// Window data
......@@ -59,12 +78,26 @@ impl Renderer for Window {
impl Window {
/// Create a new window
pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
Window::new_flags(x, y, w, h, title, false)
Window::new_flags(x, y, w, h, title, &[])
}
/// Create a new window with flags
pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, async: bool) -> Option<Self> {
if let Ok(file) = File::open(&format!("orbital:{}/{}/{}/{}/{}/{}", if async { "a" } else { "" }, x, y, w, h, title)) {
pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, flags: &[WindowFlag]) -> Option<Self> {
let mut async = false;
let mut resizable = false;
for &flag in flags.iter() {
match flag {
WindowFlag::Async => async = true,
WindowFlag::Resizable => resizable = true,
}
}
if let Ok(file) = File::open(&format!(
"orbital:{}{}/{}/{}/{}/{}/{}",
if async { "a" } else { "" },
if resizable { "r" } else { "" },
x, y, w, h, title
)) {
if let Ok(address) = unsafe { syscall::fmap(file.as_raw_fd(), 0, (w * h * 4) as usize) } {
Some(Window {
x: x,
......@@ -73,6 +106,7 @@ impl Window {
h: h,
t: title.to_string(),
async: async,
resizable: resizable,
file: file,
data: unsafe { slice::from_raw_parts_mut(address as *mut Color, (w * h) as usize) },
})
......@@ -169,6 +203,18 @@ impl Window {
},
Ok(count) => {
iter.count = count/mem::size_of::<Event>();
if self.resizable {
let mut resize = None;
for i in 0..iter.count {
let event = &iter.events[i];
if event.code == EVENT_RESIZE {
resize = Some((event.a as u32, event.b as u32));
}
}
if let Some((w, h)) = resize {
self.set_size(w, h);
}
}
break 'blocking;
},
Err(_) => break 'blocking,
......
extern crate sdl2;
use std::{mem, slice};
use std::{mem, ptr, slice};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use color::Color;
use event::*;
use super::{init, SDL_CTX, VIDEO_CTX, EVENT_PUMP};
use renderer::Renderer;
use WindowFlag;
static SDL_USAGES: AtomicUsize = ATOMIC_USIZE_INIT;
/// SDL2 Context
static mut SDL_CTX: *mut sdl2::Sdl = ptr::null_mut();
/// Video Context
static mut VIDEO_CTX: *mut sdl2::VideoSubsystem = ptr::null_mut();
/// Event Pump
static mut EVENT_PUMP: *mut sdl2::EventPump = ptr::null_mut();
//Call this when the CTX needs to be used is created
#[inline]
unsafe fn init() {
if SDL_USAGES.fetch_add(1, Ordering::Relaxed) == 0 {
SDL_CTX = Box::into_raw(Box::new(sdl2::init().unwrap()));
VIDEO_CTX = Box::into_raw(Box::new((&mut *SDL_CTX).video().unwrap()));
EVENT_PUMP = Box::into_raw(Box::new((&mut *SDL_CTX).event_pump().unwrap()));
}
}
pub fn get_display_size() -> Result<(u32, u32), String> {
unsafe { init() };
unsafe { & *VIDEO_CTX }.display_bounds(0)
.map(|rect| (rect.width(), rect.height()))
.map_err(|err| format!("{}", err))
}
/// A window
#[allow(dead_code)]
......@@ -63,16 +89,29 @@ impl Renderer for Window {
impl Window {
/// Create a new window
pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
Window::new_flags(x, y, w, h, title, false)
Window::new_flags(x, y, w, h, title, &[])
}
/// Create a new window with flags
pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, async: bool) -> Option<Self> {
pub fn new_flags(x: i32, y: i32, w: u32, h: u32, title: &str, flags: &[WindowFlag]) -> Option<Self> {
//Insure that init has been called
unsafe { init() };
let mut async = false;
let mut resizable = false;
for &flag in flags.iter() {
match flag {
WindowFlag::Async => async = true,
WindowFlag::Resizable => resizable = true,
}
}
let mut builder = unsafe { & *VIDEO_CTX }.window(title, w, h);
if resizable {
builder.resizable();
}
if x >= 0 || y >= 0 {
builder.position(x, y);
}
......@@ -284,6 +323,10 @@ impl Window {
sdl2::event::Event::MouseMotion { .. } => events.push(mouse_event()),
sdl2::event::Event::MouseButtonDown { .. } => events.push(mouse_event()),
sdl2::event::Event::MouseButtonUp { .. } => events.push(mouse_event()),
sdl2::event::Event::MouseWheel { x, y, .. } => events.push(ScrollEvent {
x: x,
y: y
}.to_event()),
sdl2::event::Event::KeyDown { scancode, .. } => if let Some(code) = self.convert_scancode(scancode, shift) {
events.push(KeyEvent {
character: code.0,
......
......@@ -11,19 +11,25 @@ pub static FONT: &'static [u8] = include_bytes!("../res/unifont.font");
pub use color::Color;
pub use event::*;
pub use imp::*;
pub use renderer::Renderer;
pub use imp::{get_display_size, EventIter, Window};
pub use graphicspath::GraphicsPath;
pub use renderer::Renderer;
pub mod color;
pub mod event;
pub mod graphicspath;
pub mod renderer;
#[derive(Clone, Copy, Debug)]
pub enum WindowFlag {
Async,
Resizable
}
#[cfg(target_os = "redox")]
#[path="orbital/mod.rs"]
pub mod imp;
#[path="imp/orbital.rs"]
mod imp;
#[cfg(not(target_os = "redox"))]
#[path="sdl2/mod.rs"]
pub mod imp;
#[path="imp/sdl2.rs"]
mod imp;
use std::env;
use std::fs::File;
use std::os::unix::io::AsRawFd;
use super::syscall;
pub fn get_display_size() -> Result<(u32, u32), String> {
let display_path = try!(env::var("DISPLAY").or(Err("DISPLAY not set")));
match File::open(&display_path) {
Ok(display) => {
let mut buf: [u8; 4096] = [0; 4096];
let count = syscall::fpath(display.as_raw_fd() as usize, &mut buf).map_err(|err| format!("{}", err))?;
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
let res = path.split(":").nth(1).unwrap_or("");
let width = res.split("/").nth(1).unwrap_or("").parse::<u32>().unwrap_or(0);
let height = res.split("/").nth(2).unwrap_or("").parse::<u32>().unwrap_or(0);
Ok((width, height))
},
Err(err) => Err(format!("{}", err))
}
}
extern crate syscall;
pub use self::display::*;
pub use self::window::*;
mod display;
mod window;
use super::{init, VIDEO_CTX};
pub fn get_display_size() -> Result<(u32, u32), String> {
unsafe { init() };
unsafe { & *VIDEO_CTX }.display_bounds(0)
.map(|rect| (rect.width(), rect.height()))
.map_err(|err| format!("{}", err))
}
extern crate sdl2;
use std::ptr;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
pub use self::display::*;
pub use self::window::*;
mod display;
mod window;
pub static SDL_USAGES: AtomicUsize = ATOMIC_USIZE_INIT;
/// SDL2 Context
pub static mut SDL_CTX: *mut sdl2::Sdl = ptr::null_mut();
/// Video Context
pub static mut VIDEO_CTX: *mut sdl2::VideoSubsystem = ptr::null_mut();
/// Event Pump
pub static mut EVENT_PUMP: *mut sdl2::EventPump = ptr::null_mut();
//Call this when the CTX needs to be used is created
#[inline]
unsafe fn init() {
if SDL_USAGES.fetch_add(1, Ordering::Relaxed) == 0 {
SDL_CTX = Box::into_raw(Box::new(sdl2::init().unwrap()));
VIDEO_CTX = Box::into_raw(Box::new((&mut *SDL_CTX).video().unwrap()));
EVENT_PUMP = Box::into_raw(Box::new((&mut *SDL_CTX).event_pump().unwrap()));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment