pub mod ext;
#[macro_use]
extern crate cfg_if;
cfg_if! {
if #[cfg(windows)] {
extern crate winapi;
use winapi::shared::windef::HWND;
use winapi::um::winuser::*;
use winapi::um::libloaderapi::GetModuleHandleW;
use winapi::ctypes::c_int;
use std::os::windows::ffi::OsStrExt;
use std::os::raw::c_char;
use std::io::Error;
use std::ffi::{CStr, OsStr, CString};
use std::iter::once;
mod winback;
pub use self::winback::*;
}
else if #[cfg(unix)] {
extern crate x11_dl;
use std::ffi::{CStr, CString};
use libc::c_char;
mod x11back;
pub use self::x11back::*;
}
}
extern crate image;
#[allow(unused_imports)]
use image::{ImageBuffer, Rgb, Pixel};
extern crate libc;
use std::mem;
use std::ptr::null_mut;
use std::ptr;
pub struct CWinRep {
pub title: String,
pub width: usize,
pub height: usize,
pub pixels: ImageBuffer<Rgb<u8>, Vec<u8>>,
init_flag: bool,
pub exit_flag: bool,
pub dirty_extents: [usize; 4],
#[cfg(unix)]
x11_disp_ptr: *mut x11_dl::xlib::Display,
#[cfg(unix)]
x11_window_ptr: std::os::raw::c_ulong,
#[cfg(unix)]
x11_gc_ptr: x11_dl::xlib::GC,
#[cfg(unix)]
xlib_dl_obj: x11_dl::xlib::Xlib,
#[cfg(windows)]
win32_win_ptr: winback::Window,
}
pub struct CWin {
pub rep: CWinRep,
event_callbacks: Vec<Box<extern fn(*mut CWinRep, String /* event string */)>>,
event_raw_callbacks: Vec<Box<extern fn(*mut CWinRep, *const c_char /* event string */)>>,
}
impl CWin {
pub fn new() -> CWin {
return CWin::new_detail("Untitled Window", 800, 600);
}
pub fn new_detail<S: Into<String>>(title: S, width: u32, height: u32) -> CWin {
let title = title.into();
return CWin {
rep: CWinRep {
title: title,
width: width as usize,
height: height as usize,
pixels: ImageBuffer::new(width, height),
init_flag: false,
exit_flag: false,
dirty_extents: [width as usize, height as usize, 0, 0],
#[cfg(unix)]
x11_window_ptr: unsafe { mem::uninitialized() },
#[cfg(unix)]
x11_gc_ptr: unsafe { mem::uninitialized() },
#[cfg(unix)]
x11_disp_ptr: unsafe { mem::uninitialized() },
#[cfg(unix)]
xlib_dl_obj: unsafe { mem::uninitialized() },
#[cfg(windows)]
win32_win_ptr: unsafe { mem::uninitialized() },
},
event_callbacks: vec![],
event_raw_callbacks: vec![],
};
}
pub fn to_ffi_ptr(self) -> *mut CWin {
let boxed = Box::new(self);
return Box::into_raw(boxed);
}
pub fn add_callback(&mut self, function: extern fn(*mut CWinRep, String)) {
self.event_callbacks.push(Box::new(function));
}
pub fn add_callback_raw(&mut self, function: extern fn(*mut CWinRep, *const c_char /* event string */)) {
self.event_raw_callbacks.push(Box::new(function));
}
pub fn call_callbacks(&mut self, event_string: String) {
let cwinrep : *mut CWinRep = &mut self.rep;
self.event_callbacks.iter_mut().for_each(|c| {
(c)(cwinrep, event_string.clone());
});
let safe_cstr : CString = CString::new(event_string).unwrap();
let cstr_ptr = safe_cstr.as_ptr();
self.call_raw_callbacks(cstr_ptr);
}
fn call_raw_callbacks(&mut self, event_string: *const c_char) {
let cwinrep : *mut CWinRep = &mut self.rep;
self.event_raw_callbacks.iter_mut().for_each(|c| {
(c)(cwinrep, event_string.clone());
});
}
pub fn write_px(&mut self, x: u32, y: u32, rgb: [u8; 3]) {
self.rep.write_px(x, y, rgb);
}
}
impl CWinRep {
pub fn write_px(&mut self, x: u32, y: u32, rgb: [u8; 3]) {
let x = x as usize;
let y = y as usize;
if x < self.dirty_extents[0] {
self.dirty_extents[0] = x;
}
if x > self.dirty_extents[2] {
self.dirty_extents[2] = x+1;
}
if y < self.dirty_extents[1] {
self.dirty_extents[1] = y;
}
if y > self.dirty_extents[3] {
self.dirty_extents[3] = y+1;
}
self.pixels.get_pixel_mut(x as u32, y as u32).data = rgb;
}
}
pub trait RenderBack {
fn init(&mut self);
fn redraw_dirty(&mut self);
fn redraw_box(&mut self, x1: usize, y1: usize, x2: usize, y2: usize);
fn event_tick(&self) -> String;
fn event_loop(&mut self);
}