mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-10 02:51:32 +11:00
WIP on latest Mac version
This commit is contained in:
parent
29e744bc19
commit
99e106fe93
|
@ -6,15 +6,26 @@ const WIDTH: usize = 640;
|
||||||
const HEIGHT: usize = 360;
|
const HEIGHT: usize = 360;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut noise;
|
//let mut noise;
|
||||||
let mut carry;
|
//let mut carry;
|
||||||
let mut seed = 0xbeefu32;
|
//let mut seed = 0xbeefu32;
|
||||||
|
|
||||||
let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
//let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
||||||
|
|
||||||
let mut mfb = Minifb::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT).unwrap();
|
let window = match macos::Window::new("Noise Test - Press ESC to exit",
|
||||||
|
WIDTH,
|
||||||
|
HEIGHT,
|
||||||
|
Scale::X1,
|
||||||
|
Vsync::No) {
|
||||||
|
Ok(window) => window,
|
||||||
|
Err(info) => {
|
||||||
|
println!("{}", info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while mfb.update(&buffer) {
|
loop {
|
||||||
|
/*
|
||||||
for i in buffer.iter_mut() {
|
for i in buffer.iter_mut() {
|
||||||
noise = seed;
|
noise = seed;
|
||||||
noise >>= 3;
|
noise >>= 3;
|
||||||
|
@ -26,5 +37,6 @@ fn main() {
|
||||||
noise &= 0xFF;
|
noise &= 0xFF;
|
||||||
*i = (noise << 16) | (noise << 8) | noise;
|
*i = (noise << 16) | (noise << 8) | noise;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
197
src/lib.rs
197
src/lib.rs
|
@ -11,20 +11,119 @@ extern crate cocoa;
|
||||||
extern crate core_foundation;
|
extern crate core_foundation;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
|
||||||
/// Error that can happen while creating a window or a headless renderer.
|
/// Scale will scale the frame buffer and the window that is being sent in when calling the update
|
||||||
#[derive(Debug)]
|
/// function. This is useful if you for example want to display a 320 x 256 window on a screen with
|
||||||
pub enum CreationError {
|
/// much higher resolution which would result in that the window is very small.
|
||||||
OsError(String),
|
pub enum Scale {
|
||||||
NotSupported,
|
/// This mode checks your current screen resolution and will caluclate the largest window size
|
||||||
|
/// that can be used within that limit and resize it. Useful if you have a small buffer to
|
||||||
|
/// display on a high resolution screen.
|
||||||
|
FitScreen,
|
||||||
|
/// 1X scale (which means leave the corrdinates sent into Window::new untouched)
|
||||||
|
X1,
|
||||||
|
/// 2X window scale (Example: 320 x 200 -> 640 x 400)
|
||||||
|
X2,
|
||||||
|
/// 4X window scale (Example: 320 x 200 -> 1280 x 800)
|
||||||
|
X4,
|
||||||
|
/// 8X window scale (Example: 320 x 200 -> 2560 x 1600)
|
||||||
|
X8,
|
||||||
|
/// 16X window scale (Example: 320 x 200 -> 5120 x 3200)
|
||||||
|
X16,
|
||||||
|
/// 32 window scale (Example: 320 x 200 -> 10240 x 6400)
|
||||||
|
X32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreationError {
|
/// Vsync will allow syncronized rendering with the screen refresh rate.
|
||||||
fn to_string(&self) -> &str {
|
pub enum Vsync {
|
||||||
match *self {
|
/// No vsync
|
||||||
CreationError::OsError(ref text) => &text,
|
No,
|
||||||
CreationError::NotSupported => "Some of the requested attributes are not supported",
|
/// Require accurate vsync. Notice that if the library is unable to to setup an accurate
|
||||||
}
|
/// syncing the window creation will fail.
|
||||||
}
|
Accurate,
|
||||||
|
/// Setup a best guess syncing with the screen. This will always succesed but may not be
|
||||||
|
/// accurate. What this means is if the lib is unable to create a accurate syncing approach
|
||||||
|
/// a 'emulated' one will be used (for example using a timer to approximate syncing)
|
||||||
|
BestGuess,
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pub enum Key {
|
||||||
|
Space,
|
||||||
|
/// The '1' key over the letters.
|
||||||
|
Key1,
|
||||||
|
/// The '2' key over the letters.
|
||||||
|
Key2,
|
||||||
|
/// The '3' key over the letters.
|
||||||
|
Key3,
|
||||||
|
/// The '4' key over the letters.
|
||||||
|
Key4,
|
||||||
|
/// The '5' key over the letters.
|
||||||
|
Key5,
|
||||||
|
/// The '6' key over the letters.
|
||||||
|
Key6,
|
||||||
|
/// The '7' key over the letters.
|
||||||
|
Key7,
|
||||||
|
/// The '8' key over the letters.
|
||||||
|
Key8,
|
||||||
|
/// The '9' key over the letters.
|
||||||
|
Key9,
|
||||||
|
/// The '0' key over the 'O' and 'P' keys.
|
||||||
|
Key0,
|
||||||
|
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L,
|
||||||
|
M,
|
||||||
|
N,
|
||||||
|
O,
|
||||||
|
P,
|
||||||
|
Q,
|
||||||
|
R,
|
||||||
|
S,
|
||||||
|
T,
|
||||||
|
U,
|
||||||
|
V,
|
||||||
|
W,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
|
||||||
|
Escape,
|
||||||
|
|
||||||
|
F1,
|
||||||
|
F2,
|
||||||
|
F3,
|
||||||
|
F4,
|
||||||
|
F5,
|
||||||
|
F6,
|
||||||
|
F7,
|
||||||
|
F8,
|
||||||
|
F9,
|
||||||
|
F10,
|
||||||
|
F11,
|
||||||
|
F12,
|
||||||
|
F13,
|
||||||
|
F14,
|
||||||
|
F15,
|
||||||
|
|
||||||
|
ArrowLeft,
|
||||||
|
ArrowRight,
|
||||||
|
ArrowUp,
|
||||||
|
ArrowDown,
|
||||||
|
|
||||||
|
Backspace,
|
||||||
|
Delete,
|
||||||
|
Comma,
|
||||||
|
Semicollon
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -38,77 +137,3 @@ pub mod macos;
|
||||||
pub use macos::*;
|
pub use macos::*;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
#[link(name = "Cocoa", kind = "framework")]
|
|
||||||
extern {
|
|
||||||
fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int;
|
|
||||||
fn mfb_update(buffer: *mut c_void) -> c_int;
|
|
||||||
fn mfb_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
#[link(name = "gdi32")]
|
|
||||||
extern {
|
|
||||||
fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int;
|
|
||||||
fn mfb_update(buffer: *mut c_void) -> c_int;
|
|
||||||
fn mfb_close();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
#[link(name = "X11")]
|
|
||||||
extern {
|
|
||||||
fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int;
|
|
||||||
fn mfb_update(buffer: *mut c_void) -> c_int;
|
|
||||||
fn mfb_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Open up a window
|
|
||||||
///
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "mac"))]
|
|
||||||
pub fn open(name: &str, width: usize, height: usize) -> bool {
|
|
||||||
let s = CString::new(name).unwrap();
|
|
||||||
let ret;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ret = mfb_open(s.as_ptr(), width as c_int, height as c_int);
|
|
||||||
}
|
|
||||||
|
|
||||||
match ret {
|
|
||||||
0 => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Update
|
|
||||||
///
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "mac"))]
|
|
||||||
pub fn update(buffer: &[u32]) -> bool {
|
|
||||||
let ret;
|
|
||||||
unsafe {
|
|
||||||
ret = mfb_update(transmute(buffer.as_ptr()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret < 0 {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Close
|
|
||||||
///
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "mac"))]
|
|
||||||
pub fn close() {
|
|
||||||
unsafe {
|
|
||||||
mfb_close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
124
src/macos.rs
124
src/macos.rs
|
@ -1,36 +1,69 @@
|
||||||
#![cfg(target_os = "macos")]
|
#![cfg(target_os = "macos")]
|
||||||
|
|
||||||
use CreationError;
|
use Scale;
|
||||||
use CreationError::OsError;
|
use Vsync;
|
||||||
|
use Key;
|
||||||
|
|
||||||
use libc;
|
//use libc;
|
||||||
use cocoa::appkit;
|
//use cocoa::appkit;
|
||||||
use cocoa::appkit::*;
|
use cocoa::appkit::*;
|
||||||
use cocoa::appkit::NSEventSubtype::*;
|
//use cocoa::appkit::NSEventSubtype::*;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
use cocoa::base::{id, nil};
|
use cocoa::base::{id, nil};
|
||||||
|
#[allow(unused_imports)]
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
|
use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize,
|
||||||
NSString, NSUInteger};
|
NSString, NSUInteger};
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
struct Minifb {
|
pub struct Window {
|
||||||
temp: isize,
|
view: IdRef,
|
||||||
|
window: IdRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Minifb {
|
impl Window {
|
||||||
pub unsafe fn new(name: &str, width: isize, height: isize) -> Result<Minifb, CreationError> {
|
pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> {
|
||||||
let app = match Self::create_app() {
|
unsafe {
|
||||||
Some(app) => app,
|
let app = match Self::create_app() {
|
||||||
None => { return Err(OsError(format!("Couldn't create NSApplication"))); },
|
Some(app) => app,
|
||||||
};
|
None => {
|
||||||
|
return Err("Couldn't create NSApplication");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let masks = 0u64;
|
let window = match Self::create_window(name, width, height) {
|
||||||
|
Some(window) => window,
|
||||||
|
None => {
|
||||||
|
return Err("Unable to create NSWindow");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//let masks = NSResizableWindowMask as NSUInteger |
|
let view = match Self::create_view(*window) {
|
||||||
// NSClosableWindowMask as NSUInteger |
|
Some(view) => view,
|
||||||
// NSTitledWindowMaskas as NSUInteger;
|
None => {
|
||||||
|
return Err("Unable to create NSView");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
app.activateIgnoringOtherApps_(YES);
|
||||||
|
|
||||||
|
println!("Created window and view");
|
||||||
|
|
||||||
|
return Ok(Window {
|
||||||
|
window: window,
|
||||||
|
view: view
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_window(name: &str, width: usize, height: usize) -> Option<IdRef> {
|
||||||
|
let masks = NSResizableWindowMask as NSUInteger |
|
||||||
|
NSClosableWindowMask as NSUInteger |
|
||||||
|
NSTitledWindowMask as NSUInteger;
|
||||||
|
|
||||||
let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));
|
let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64));
|
||||||
|
|
||||||
|
@ -41,9 +74,34 @@ impl Minifb {
|
||||||
NO,
|
NO,
|
||||||
));
|
));
|
||||||
|
|
||||||
if window.is_nil() {
|
window.non_nil().map(|window| {
|
||||||
return Err(OsError(format!("Unable to create window")));
|
let title = IdRef::new(NSString::alloc(nil).init_str(name));
|
||||||
}
|
window.setTitle_(*title);
|
||||||
|
window.center();
|
||||||
|
window
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn create_view(window: id) -> Option<IdRef> {
|
||||||
|
let view = IdRef::new(NSView::alloc(nil).init());
|
||||||
|
view.non_nil().map(|view| {
|
||||||
|
window.setContentView_(*view);
|
||||||
|
view
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(_: &[u32]) {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_keys() -> Option<Vec<Key>> {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_esc_pressed() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +116,10 @@ impl Minifb {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct IdRef(id);
|
struct IdRef(id);
|
||||||
|
|
||||||
impl IdRef {
|
impl IdRef {
|
||||||
|
@ -82,4 +140,26 @@ impl IdRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for IdRef {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.0 != nil {
|
||||||
|
let _: () = unsafe { msg_send![self.0, release] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for IdRef {
|
||||||
|
type Target = id;
|
||||||
|
fn deref<'a>(&'a self) -> &'a id {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for IdRef {
|
||||||
|
fn clone(&self) -> IdRef {
|
||||||
|
if self.0 != nil {
|
||||||
|
let _: id = unsafe { msg_send![self.0, retain] };
|
||||||
|
}
|
||||||
|
IdRef(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue