mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2024-12-23 19:31:30 +11:00
Merged window-opts to master
commit 53e9cd45567a1308fdbd2e46763e15b2a3fa3d4c Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:31:38 2016 +0100 Correct header for v0.4.0 commit fcf64d5dfad0796fee16ce8985e66d1b3e82c5a4 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:30:12 2016 +0100 More cleanup commit b7f4b187569a753656f19a74b78d8ada3fd95b70 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:29:23 2016 +0100 Minor cleanup commit 7392cd4a5aaad7f0d8332082c75d6cbc41d50ca6 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:28:06 2016 +0100 Updated example added Changelog link commit 236a82883a68e576ceb1e38a54b0a18fdc2e4465 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:24:58 2016 +0100 Updated readme commit e6bc68721513ca66c5566a19e6bfad33875b3280 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:20:42 2016 +0100 Doc fixes commit edfd688f045764b66c944d4aa616c6d48246816d Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 18:20:35 2016 +0100 Updated with 0.4.0 release info commit 784628fa9a1de93280592e634b522fd916a7588a Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 15:45:37 2016 +0100 Fixed bad comment commit 2c6d8730b566193b573afb5dc95a82987d1c4ce4 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 15:37:52 2016 +0100 Linux support for WindowOptions commit cbf7c17c3a92d676f5707095781071016e8b90e1 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 15:05:10 2016 +0100 Updated Windows version with WindowOptions commit ed1254245384e3e64c082a8368cbbe4a9f679efa Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 14:32:04 2016 +0100 Added get_window_handle commit e4a15f98c70facda7e7b2f30ba95a42091fa078c Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 14:30:34 2016 +0100 Cleanup + links commit 7dadb090d1037eade525093e2a541c99940e6a3a Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 14:25:41 2016 +0100 And again commit 70bdb0f88812e12bf9ca9adc55c1e52cc36c3ef9 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 14:24:44 2016 +0100 Try link again commit b4b7b3c4cda1d958e8f9cf6a2418db68ac32bcc5 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 14:21:54 2016 +0100 Some cleanup commit fb9845bae37f6ce9ba309b8a57128ce8c426fbca Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 13:16:23 2016 +0100 Renamed resizeable to resize commit 89c5af826612dbd887855dca3937e99856c9fcf2 Author: Daniel Collin <daniel@collin.com> Date: Sun Jan 31 12:59:57 2016 +0100 Working on making Windows a bit more generic * Added WindowOptions that can configure how the Window should look and behave better (resize, title, borderless) * Renamed update -> update_with_buffer * Added update which doesn't take a buffer (used to updated the window without buffers)
This commit is contained in:
parent
1eb052fa27
commit
73813b63f4
20
CHANGELOG.md
20
CHANGELOG.md
|
@ -2,14 +2,24 @@
|
|||
|
||||
This project follows semantic versioning.
|
||||
|
||||
### v0.4.0 (2016-01-31)
|
||||
|
||||
This release breaks some of the API by changing names and parameters to some functions.
|
||||
|
||||
- [changed] ```Window::new(...)``` now takes WindowOptions struct to configure the creation of the Window. [doc](http://prodbg.com/minifb/minifb/struct.Window.html#method.new)
|
||||
- [changed] ```window.update()``` Doesn't take a buffer anymore. See ```window.update_with_buffer``` [doc](http://prodbg.com/minifb/minifb/struct.Window.html#method.update)
|
||||
- [added] ```window.update_with_buffer()``` Old update version that takes buffer as input parameter [doc](http://prodbg.com/minifb/minifb/struct.Window.html#method.update_with_buffer)
|
||||
- [added] ```window.get_window_handle()``` Returns the native handle (os dependant) [doc](http://prodbg.com/minifb/minifb/struct.Window.html#method.get_window_handle)
|
||||
|
||||
### v0.3.1 (2016-01-29)
|
||||
|
||||
- [fixed] ```get_mouse_pos(MouseMode::Clamp)``` now is in the region [(0, 0) - (width - 1, height - 1)] instead of (width, height)
|
||||
- [fixed] ```get_mouse_pos(Clamp)``` clamps to ```[(0, 0) - (width - 1, height - 1)]``` instead of ```(width, height)```
|
||||
|
||||
### v0.3.0 (2016-01-29)
|
||||
|
||||
- [added] ```get_mouse_pos```
|
||||
- [added] ```get_mouse_down```
|
||||
- [added] ```get_scroll_wheel```
|
||||
This release adds support for mouse input. See the documentation and the examples for usage
|
||||
|
||||
- [added] [get_mouse_pos](http://prodbg.com/minifb/minifb/struct.Window.html#method.get_mouse_pos)
|
||||
- [added] [get_mouse_down](http://prodbg.com/minifb/minifb/struct.Window.html#method.get_mouse_down)
|
||||
- [added] [get_scroll_wheel](http://prodbg.com/minifb/minifb/struct.Window.html#method.get_scroll_wheel)
|
||||
|
||||
This relase adds support for mouse input. See the documentation and the examples for usage
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[package]
|
||||
name = "minifb"
|
||||
version = "0.3.1"
|
||||
version = "0.4.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
authors = ["Daniel Collin <daniel@collin.com>"]
|
||||
description = "Cross-platform window setup for bitmap rendering"
|
||||
keywords = ["windowing", "framebuffer"]
|
||||
description = "Cross-platform window setup with optional bitmap rendering"
|
||||
keywords = ["windowing", "window", "framebuffer"]
|
||||
repository = "https://github.com/emoon/rust_minifb"
|
||||
homepage = "https://github.com/emoon/rust_minifb"
|
||||
documentation = "http://prodbg.com/minifb/minifb/index.html"
|
||||
|
|
13
README.md
13
README.md
|
@ -2,9 +2,11 @@
|
|||
[![Build Status](https://travis-ci.org/emoon/rust_minifb.svg)](https://travis-ci.org/emoon/rust_minifb)
|
||||
[![Build Status](https://ci.appveyor.com/api/projects/status/sfvgqq4d4sjulkbx?svg=true)](https://ci.appveyor.com/project/emoon/rust-minifb)
|
||||
|
||||
minifb (Mini FrameBuffer) is a small cross platform library written in [Rust](https://www.rust-lang.org) and that makes it easy to render (32-bit) pixels in a window. An example is the best way to show how it works:
|
||||
minifb is a cross platform library written in [Rust](https://www.rust-lang.org) and that makes it easy to setup a window and to (optional) display 32-bit a pixel buffer. It also makes it easy to get input from keyboard and mouse.
|
||||
An example is the best way to show how it works:
|
||||
|
||||
[Documentation](http://prodbg.com/minifb/minifb/index.html)
|
||||
[Changelog](https://github.com/emoon/rust_minifb/blob/window-opts/CHANGELOG.md)
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
@ -12,7 +14,7 @@ Usage
|
|||
```toml
|
||||
# Cargo.toml
|
||||
[dependencies]
|
||||
minifb = "0.3.1"
|
||||
minifb = "0.4.0"
|
||||
```
|
||||
|
||||
Example
|
||||
|
@ -21,7 +23,7 @@ Example
|
|||
```rust
|
||||
extern crate minifb;
|
||||
|
||||
use minifb::{Key, Scale};
|
||||
use minifb::{Key, Scale, WindowOptions};
|
||||
|
||||
const WIDTH: usize = 640;
|
||||
const HEIGHT: usize = 360;
|
||||
|
@ -29,7 +31,8 @@ const HEIGHT: usize = 360;
|
|||
fn main() {
|
||||
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
|
||||
|
||||
let mut window = match minifb::Window::new("Test - ESC to exit", WIDTH, HEIGHT, Scale::X1) {
|
||||
let mut window = match minifb::Window::new("Test - ESC to exit", WIDTH, HEIGHT,
|
||||
WindowOptions::default()) {
|
||||
Ok(win) => win,
|
||||
Err(err) => {
|
||||
println!("Unable to create window {}", err);
|
||||
|
@ -42,7 +45,7 @@ fn main() {
|
|||
*i = 0; // write something more funny here!
|
||||
}
|
||||
|
||||
window.update(&buffer);
|
||||
window.update_with_buffer(&buffer);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extern crate minifb;
|
||||
|
||||
use minifb::{MouseButton, MouseMode, Window, Key, Scale};
|
||||
use minifb::{MouseButton, MouseMode, Window, Key, Scale, WindowOptions};
|
||||
|
||||
const WIDTH: usize = 640;
|
||||
const HEIGHT: usize = 360;
|
||||
|
@ -8,7 +8,11 @@ const HEIGHT: usize = 360;
|
|||
fn main() {
|
||||
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
|
||||
|
||||
let mut window = match Window::new("Mouse Draw - Press ESC to exit", WIDTH, HEIGHT, Scale::X2) {
|
||||
let mut window = match Window::new("Mouse Draw - Press ESC to exit", WIDTH, HEIGHT,
|
||||
WindowOptions {
|
||||
scale: Scale::X2,
|
||||
..WindowOptions::default()
|
||||
}) {
|
||||
Ok(win) => win,
|
||||
Err(err) => {
|
||||
println!("Unable to create window {}", err);
|
||||
|
@ -33,6 +37,6 @@ fn main() {
|
|||
println!("Scrolling {} - {}", scroll.0, scroll.1);
|
||||
});
|
||||
|
||||
window.update(&buffer);
|
||||
window.update_with_buffer(&buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
extern crate minifb;
|
||||
|
||||
use minifb::{Window, Key, Scale};
|
||||
use minifb::{Window, Key, Scale, WindowOptions};
|
||||
|
||||
const WIDTH: usize = 640;
|
||||
const HEIGHT: usize = 360;
|
||||
|
@ -12,7 +12,12 @@ fn main() {
|
|||
|
||||
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
|
||||
|
||||
let mut window = match Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT, Scale::X2) {
|
||||
let mut window = match Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT,
|
||||
WindowOptions {
|
||||
resize: true,
|
||||
scale: Scale::X2,
|
||||
..WindowOptions::default()
|
||||
}) {
|
||||
Ok(win) => win,
|
||||
Err(err) => {
|
||||
println!("Unable to create window {}", err);
|
||||
|
@ -43,6 +48,6 @@ fn main() {
|
|||
}
|
||||
});
|
||||
|
||||
window.update(&buffer);
|
||||
window.update_with_buffer(&buffer);
|
||||
}
|
||||
}
|
||||
|
|
124
src/lib.rs
124
src/lib.rs
|
@ -183,10 +183,13 @@ pub enum MouseMode {
|
|||
|
||||
extern crate libc;
|
||||
|
||||
use std::os::raw;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod os;
|
||||
mod mouse_handler;
|
||||
mod key_handler;
|
||||
mod window_flags;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use self::os::macos as imp;
|
||||
|
@ -199,36 +202,58 @@ use self::os::windows as imp;
|
|||
target_os="openbsd"))]
|
||||
use self::os::unix as imp;
|
||||
|
||||
pub struct Window(imp::Window);
|
||||
|
||||
///
|
||||
/// Window used for displaying a 32-bit RGB buffer. Here is a small example on how to use it:
|
||||
/// (without error checking
|
||||
/// WindowOptions is creation settings for the window. By default the settings are defined for
|
||||
/// displayng a 32-bit buffer (no scaling of window is possible)
|
||||
///
|
||||
pub struct WindowOptions {
|
||||
/// If the window should be borderless (default: false)
|
||||
pub borderless: bool,
|
||||
/// If the window should have a title (default: true)
|
||||
pub title: bool,
|
||||
/// If it should be possible to resize the window (default: false)
|
||||
pub resize: bool,
|
||||
/// Scale of the window that used in conjunction with update_with_buffer (default: X1)
|
||||
pub scale: Scale
|
||||
}
|
||||
|
||||
///
|
||||
/// Window is used to open up a window. It's possible to optionally display a 32-bit buffer when
|
||||
/// the widow is set as non-resizable.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Open up a window and display a 32-bit RGB buffer (without error checking)
|
||||
///
|
||||
/// ```ignore
|
||||
///
|
||||
/// const WIDTH: usize = 640;
|
||||
/// const HEIGHT: usize = 360;
|
||||
///
|
||||
/// let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
|
||||
///
|
||||
/// let mut window = match Window::new("Test - Press ESC to exit", WIDTH, HEIGHT, Scale::X1).unwrap()
|
||||
/// let mut window = match Window::new("Test - Press ESC to exit", WIDTH, HEIGHT,
|
||||
/// WindowOptions::default()).unwrap()
|
||||
///
|
||||
/// while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||
/// for i in buffer.iter_mut() {
|
||||
/// *i = 0; // write something interesting here
|
||||
/// }
|
||||
/// window.update(&buffer);
|
||||
/// window.update_with_buffer(&buffer);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
||||
pub struct Window(imp::Window);
|
||||
|
||||
impl Window {
|
||||
///
|
||||
/// Opens up a new window
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Open up a window with default settings
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut window = match Window::new("Test", 640, 400, Scale::X1) {
|
||||
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()) {
|
||||
/// Ok(win) => win,
|
||||
/// Err(err) => {
|
||||
/// println!("Unable to create window {}", err);
|
||||
|
@ -236,8 +261,39 @@ impl Window {
|
|||
/// }
|
||||
///};
|
||||
/// ```
|
||||
pub fn new(name: &str, width: usize, height: usize, scale: Scale) -> Result<Window, &str> {
|
||||
imp::Window::new(name, width, height, scale).map(Window)
|
||||
///
|
||||
/// Open up a window that is resizeable
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut window = match Window::new("Test", 640, 400,
|
||||
/// WindowOptions {
|
||||
/// resize: true,
|
||||
/// ..WindowOptions::default()
|
||||
/// }) {
|
||||
/// Ok(win) => win,
|
||||
/// Err(err) => {
|
||||
/// println!("Unable to create window {}", err);
|
||||
/// return;
|
||||
/// }
|
||||
///};
|
||||
/// ```
|
||||
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window, &str> {
|
||||
imp::Window::new(name, width, height, opts).map(Window)
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the native handle for a window which is an opaque pointer/handle which
|
||||
/// dependens on the current operating system:
|
||||
///
|
||||
/// ```ignore
|
||||
/// Windows HWND
|
||||
/// MacOS NSWindow
|
||||
/// X11 XWindow
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
pub fn get_window_handle(&self) -> *mut raw::c_void {
|
||||
self.0.get_window_handle()
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -249,12 +305,30 @@ impl Window {
|
|||
/// ```ignore
|
||||
/// let mut buffer: Vec<u32> = vec![0; 640 * 400];
|
||||
///
|
||||
/// let mut window = match Window::new("Test", 640, 400, Scale::X1).unwrap();
|
||||
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
|
||||
///
|
||||
/// window.update(&buffer);
|
||||
/// window.update_with_buffer(&buffer);
|
||||
/// ```
|
||||
pub fn update(&mut self, buffer: &[u32]) {
|
||||
self.0.update(buffer)
|
||||
#[inline]
|
||||
pub fn update_with_buffer(&mut self, buffer: &[u32]) {
|
||||
self.0.update_with_buffer(buffer)
|
||||
}
|
||||
|
||||
///
|
||||
/// Updates the window (this is required to call in order to get keyboard/mouse input, etc)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// let mut buffer: Vec<u32> = vec![0; 640 * 400];
|
||||
///
|
||||
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
|
||||
///
|
||||
/// window.update();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn update(&mut self) {
|
||||
self.0.update()
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -281,7 +355,7 @@ impl Window {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```ignore
|
||||
/// // Moves the window to pixel postion 20, 20 on the screen
|
||||
/// // Moves the window to pixel position 20, 20 on the screen
|
||||
/// window.set_position(20, 20);
|
||||
/// ```
|
||||
///
|
||||
|
@ -435,7 +509,7 @@ impl Window {
|
|||
}
|
||||
|
||||
///
|
||||
/// Sets the rate in between when the keys has passed the intital repeat_delay. The default
|
||||
/// Sets the rate in between when the keys has passed the initial repeat_delay. The default
|
||||
/// value is 0.05 sec
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -449,3 +523,19 @@ impl Window {
|
|||
self.0.set_key_repeat_rate(rate)
|
||||
}
|
||||
}
|
||||
|
||||
// Impl for WindowOptions
|
||||
|
||||
#[doc(hidden)]
|
||||
impl Default for WindowOptions {
|
||||
fn default() -> WindowOptions {
|
||||
WindowOptions {
|
||||
borderless: false,
|
||||
title: true,
|
||||
resize: false,
|
||||
scale: Scale::X1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
static bool s_init = false;
|
||||
|
||||
// window_handler.rs
|
||||
const uint32_t WINDOW_BORDERLESS = 1 << 1;
|
||||
const uint32_t WINDOW_RESIZE = 1 << 2;
|
||||
const uint32_t WINDOW_TITLE = 1 << 3;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __clang__
|
||||
|
@ -14,7 +19,7 @@ static bool s_init = false;
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* mfb_open(const char* name, int width, int height, int scale)
|
||||
void* mfb_open(const char* name, int width, int height, uint32_t flags, int scale)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
@ -24,7 +29,17 @@ void* mfb_open(const char* name, int width, int height, int scale)
|
|||
s_init = true;
|
||||
}
|
||||
|
||||
unsigned int styles = NSClosableWindowMask | NSTitledWindowMask;
|
||||
uint32_t styles = NSClosableWindowMask | NSMiniaturizableWindowMask;
|
||||
|
||||
if (flags & WINDOW_BORDERLESS)
|
||||
styles |= NSBorderlessWindowMask;
|
||||
|
||||
if (flags & WINDOW_RESIZE)
|
||||
styles |= NSResizableWindowMask;
|
||||
|
||||
if (flags & WINDOW_TITLE)
|
||||
styles |= NSTitledWindowMask;
|
||||
|
||||
NSRect rectangle = NSMakeRect(0, 0, width * scale, (height * scale));
|
||||
|
||||
OSXWindow* window = [[OSXWindow alloc] initWithContentRect:rectangle styleMask:styles backing:NSBackingStoreBuffered defer:NO];
|
||||
|
@ -88,11 +103,7 @@ static int update_events()
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_update(void* window, void* buffer)
|
||||
{
|
||||
OSXWindow* win = (OSXWindow*)window;
|
||||
memcpy(win->draw_buffer, buffer, win->width * win->height * 4);
|
||||
|
||||
static int generic_update(OSXWindow* win) {
|
||||
int state = update_events();
|
||||
|
||||
if (win->shared_data) {
|
||||
|
@ -103,6 +114,26 @@ int mfb_update(void* window, void* buffer)
|
|||
win->shared_data->mouse_y = contentRect.size.height - p.y;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_update(void* window, void* buffer)
|
||||
{
|
||||
OSXWindow* win = (OSXWindow*)window;
|
||||
return generic_update(win);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int mfb_update_with_buffer(void* window, void* buffer)
|
||||
{
|
||||
OSXWindow* win = (OSXWindow*)window;
|
||||
memcpy(win->draw_buffer, buffer, win->width * win->height * 4);
|
||||
|
||||
int state = generic_update(win);
|
||||
|
||||
[[win contentView] setNeedsDisplay:YES];
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
#define Button6 6
|
||||
#define Button7 7
|
||||
|
||||
// window_handler.rs
|
||||
const uint32_t WINDOW_BORDERLESS = 1 << 1;
|
||||
const uint32_t WINDOW_RESIZE = 1 << 2;
|
||||
const uint32_t WINDOW_TITLE = 1 << 3;
|
||||
|
||||
void mfb_close(void* window_info);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -113,7 +118,7 @@ static int setup_display() {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* mfb_open(const char* title, int width, int height, int scale)
|
||||
void* mfb_open(const char* title, int width, int height, unsigned int flags, int scale)
|
||||
{
|
||||
XSetWindowAttributes windowAttributes;
|
||||
XSizeHints sizeHints;
|
||||
|
@ -125,6 +130,9 @@ void* mfb_open(const char* title, int width, int height, int scale)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//TODO: Handle no title/borderless
|
||||
(void)flags;
|
||||
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
|
||||
|
@ -146,16 +154,19 @@ void* mfb_open(const char* title, int width, int height, int scale)
|
|||
//XSelectInput(s_display, s_window, KeyPressMask | KeyReleaseMask);
|
||||
XStoreName(s_display, window, title);
|
||||
|
||||
sizeHints.flags = PPosition | PMinSize | PMaxSize;
|
||||
sizeHints.x = 0;
|
||||
sizeHints.y = 0;
|
||||
sizeHints.min_width = width;
|
||||
sizeHints.max_width = width;
|
||||
sizeHints.min_height = height;
|
||||
sizeHints.max_height = height;
|
||||
|
||||
XSelectInput(s_display, window, ButtonPressMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask);
|
||||
XSetWMNormalHints(s_display, window, &sizeHints);
|
||||
|
||||
if (!(flags & WINDOW_RESIZE)) {
|
||||
sizeHints.flags = PPosition | PMinSize | PMaxSize;
|
||||
sizeHints.x = 0;
|
||||
sizeHints.y = 0;
|
||||
sizeHints.min_width = width;
|
||||
sizeHints.max_width = width;
|
||||
sizeHints.min_height = height;
|
||||
sizeHints.max_height = height;
|
||||
XSetWMNormalHints(s_display, window, &sizeHints);
|
||||
}
|
||||
|
||||
XClearWindow(s_display, window);
|
||||
XMapRaised(s_display, window);
|
||||
XFlush(s_display);
|
||||
|
@ -376,14 +387,14 @@ static void scale_4x(unsigned int* dest, unsigned int* source, int width, int he
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mfb_update(void* window_info, void* buffer)
|
||||
void mfb_update_with_buffer(void* window_info, void* buffer)
|
||||
{
|
||||
WindowInfo* info = (WindowInfo*)window_info;
|
||||
int width = info->width;
|
||||
int height = info->height;
|
||||
int scale = info->scale;
|
||||
|
||||
if (info->update) {
|
||||
if (info->update && buffer) {
|
||||
switch (scale) {
|
||||
case 1: {
|
||||
memcpy(info->draw_buffer, buffer, width * height * 4);
|
||||
|
@ -417,6 +428,13 @@ void mfb_update(void* window_info, void* buffer)
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mfb_update(void* window_info, void* buffer)
|
||||
{
|
||||
mfb_update_with_buffer(window_info, 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mfb_set_position(void* window, int x, int y)
|
||||
{
|
||||
WindowInfo* info = (WindowInfo*)window;
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#![cfg(target_os = "macos")]
|
||||
|
||||
use {MouseButton, MouseMode, Scale, Key, KeyRepeat};
|
||||
use {MouseButton, MouseMode, Scale, Key, KeyRepeat, WindowOptions};
|
||||
use key_handler::KeyHandler;
|
||||
use mouse_handler;
|
||||
use window_flags;
|
||||
|
||||
use libc::{c_void, c_char, c_uchar};
|
||||
use std::ffi::{CString};
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
use std::os::raw;
|
||||
|
||||
// Table taken from GLFW and slightly modified
|
||||
|
||||
|
@ -144,9 +146,10 @@ static KEY_MAPPINGS: [Key; 128] = [
|
|||
|
||||
#[link(name = "Cocoa", kind = "framework")]
|
||||
extern {
|
||||
fn mfb_open(name: *const c_char, width: u32, height: u32, scale: i32) -> *mut c_void;
|
||||
fn mfb_open(name: *const c_char, width: u32, height: u32, flags: u32, scale: i32) -> *mut c_void;
|
||||
fn mfb_close(window: *mut c_void);
|
||||
fn mfb_update(window: *mut c_void, buffer: *const c_uchar);
|
||||
fn mfb_update(window: *mut c_void);
|
||||
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
|
||||
fn mfb_set_position(window: *mut c_void, x: i32, y: i32);
|
||||
fn mfb_set_key_callback(window: *mut c_void, target: *mut c_void, cb: unsafe extern fn(*mut c_void, i32, i32));
|
||||
fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData);
|
||||
|
@ -187,7 +190,7 @@ unsafe extern "C" fn key_callback(window: *mut c_void, key: i32, state: i32) {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(name: &str, width: usize, height: usize, scale: Scale) -> Result<Window, &str> {
|
||||
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window, &str> {
|
||||
let n = match CString::new(name) {
|
||||
Err(_) => {
|
||||
println!("Unable to convert {} to c_string", name);
|
||||
|
@ -197,8 +200,8 @@ impl Window {
|
|||
};
|
||||
|
||||
unsafe {
|
||||
let scale_factor = Self::get_scale_factor(width, height, scale) as usize;
|
||||
let handle = mfb_open(n.as_ptr(), width as u32, height as u32, scale_factor as i32);
|
||||
let scale_factor = Self::get_scale_factor(width, height, opts.scale) as usize;
|
||||
let handle = mfb_open(n.as_ptr(), width as u32, height as u32, window_flags::get_flags(opts), scale_factor as i32);
|
||||
|
||||
if handle == ptr::null_mut() {
|
||||
return Err("Unable to open Window");
|
||||
|
@ -218,15 +221,31 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_window_handle(&self) -> *mut raw::c_void {
|
||||
self.window_handle as *mut raw::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn set_mouse_data(&mut self) {
|
||||
mfb_set_mouse_data(self.window_handle, &mut self.shared_data);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buffer: &[u32]) {
|
||||
pub fn update_with_buffer(&mut self, buffer: &[u32]) {
|
||||
self.key_handler.update();
|
||||
|
||||
unsafe {
|
||||
mfb_update(self.window_handle, buffer.as_ptr() as *const u8);
|
||||
mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8);
|
||||
Self::set_mouse_data(self);
|
||||
mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
self.key_handler.update();
|
||||
|
||||
unsafe {
|
||||
mfb_update(self.window_handle);
|
||||
Self::set_mouse_data(self);
|
||||
mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
extern crate x11_dl;
|
||||
|
||||
use {MouseMode, MouseButton, Scale, Key, KeyRepeat};
|
||||
use {MouseMode, MouseButton, Scale, Key, KeyRepeat, WindowOptions};
|
||||
use key_handler::KeyHandler;
|
||||
use self::x11_dl::keysym::*;
|
||||
|
||||
|
@ -14,13 +14,16 @@ use libc::{c_void, c_char, c_uchar};
|
|||
use std::ffi::{CString};
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
use std::os::raw;
|
||||
use mouse_handler;
|
||||
use window_flags;
|
||||
|
||||
#[link(name = "X11")]
|
||||
extern {
|
||||
fn mfb_open(name: *const c_char, width: u32, height: u32, scale: i32) -> *mut c_void;
|
||||
fn mfb_open(name: *const c_char, width: u32, height: u32, flags: u32, scale: i32) -> *mut c_void;
|
||||
fn mfb_close(window: *mut c_void);
|
||||
fn mfb_update(window: *mut c_void, buffer: *const c_uchar);
|
||||
fn mfb_update(window: *mut c_void);
|
||||
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
|
||||
fn mfb_set_position(window: *mut c_void, x: i32, y: i32);
|
||||
fn mfb_set_key_callback(window: *mut c_void, target: *mut c_void, cb: unsafe extern fn(*mut c_void, i32, i32));
|
||||
fn mfb_set_shared_data(window: *mut c_void, target: *mut SharedData);
|
||||
|
@ -160,7 +163,7 @@ unsafe extern "C" fn key_callback(window: *mut c_void, key: i32, s: i32) {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
pub fn new(name: &str, width: usize, height: usize, scale: Scale) -> Result<Window, &str> {
|
||||
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window, &str> {
|
||||
let n = match CString::new(name) {
|
||||
Err(_) => {
|
||||
println!("Unable to convert {} to c_string", name);
|
||||
|
@ -170,8 +173,12 @@ impl Window {
|
|||
};
|
||||
|
||||
unsafe {
|
||||
let scale = Self::get_scale_factor(width, height, scale);
|
||||
let handle = mfb_open(n.as_ptr(), width as u32, height as u32, scale);
|
||||
let scale = Self::get_scale_factor(width, height, opts.scale);
|
||||
let handle = mfb_open(n.as_ptr(),
|
||||
width as u32,
|
||||
height as u32,
|
||||
window_flags::get_flags(opts),
|
||||
scale);
|
||||
|
||||
if handle == ptr::null_mut() {
|
||||
return Err("Unable to open Window");
|
||||
|
@ -192,16 +199,31 @@ impl Window {
|
|||
mfb_set_shared_data(self.window_handle, &mut self.shared_data);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buffer: &[u32]) {
|
||||
pub fn update_with_buffer(&mut self, buffer: &[u32]) {
|
||||
self.key_handler.update();
|
||||
|
||||
unsafe {
|
||||
Self::set_shared_data(self);
|
||||
mfb_update(self.window_handle, buffer.as_ptr() as *const u8);
|
||||
mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8);
|
||||
mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
self.key_handler.update();
|
||||
|
||||
unsafe {
|
||||
Self::set_shared_data(self);
|
||||
mfb_update(self.window_handle);
|
||||
mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_window_handle(&self) -> *mut raw::c_void {
|
||||
self.window_handle as *mut raw::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&mut self, x: isize, y: isize) {
|
||||
unsafe { mfb_set_position(self.window_handle, x as i32, y as i32) }
|
||||
|
|
|
@ -6,7 +6,7 @@ extern crate winapi;
|
|||
extern crate gdi32;
|
||||
extern crate time;
|
||||
|
||||
use {Scale, Key, KeyRepeat, MouseButton, MouseMode};
|
||||
use {Scale, Key, KeyRepeat, MouseButton, MouseMode, WindowOptions};
|
||||
|
||||
use key_handler::KeyHandler;
|
||||
|
||||
|
@ -14,6 +14,7 @@ use std::ptr;
|
|||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ffi::OsStr;
|
||||
use std::mem;
|
||||
use std::os::raw;
|
||||
use mouse_handler;
|
||||
|
||||
use self::winapi::windef::HWND;
|
||||
|
@ -226,6 +227,12 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
|
|||
}
|
||||
|
||||
winapi::winuser::WM_PAINT => {
|
||||
|
||||
// if we have nothing to draw here we return the default function
|
||||
if wnd.buffer.len() == 0 {
|
||||
return user32::DefWindowProcW(window, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
let mut bitmap_info: BitmapInfo = mem::zeroed();
|
||||
|
||||
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
|
||||
|
@ -294,7 +301,7 @@ pub struct Window {
|
|||
}
|
||||
|
||||
impl Window {
|
||||
fn open_window(name: &str, width: usize, height: usize, scale_factor: i32) -> Option<HWND> {
|
||||
fn open_window(name: &str, width: usize, height: usize, opts: WindowOptions, scale_factor: i32) -> Option<HWND> {
|
||||
unsafe {
|
||||
let class_name = to_wstring("minifb_window");
|
||||
let class = WNDCLASSW {
|
||||
|
@ -337,12 +344,28 @@ impl Window {
|
|||
|
||||
let window_name = to_wstring(name);
|
||||
|
||||
let mut flags = 0;
|
||||
|
||||
if opts.title {
|
||||
flags |= winapi::WS_OVERLAPPEDWINDOW as u32;
|
||||
}
|
||||
|
||||
if opts.resize {
|
||||
flags |= winapi::WS_THICKFRAME as u32 | winapi::WS_MAXIMIZEBOX as u32 ;
|
||||
|
||||
} else {
|
||||
flags &= !winapi::WS_MAXIMIZEBOX;
|
||||
flags &= !winapi::WS_THICKFRAME;
|
||||
}
|
||||
|
||||
if opts.borderless {
|
||||
flags &= !winapi::WS_THICKFRAME;
|
||||
}
|
||||
|
||||
let handle = user32::CreateWindowExW(0,
|
||||
class_name.as_ptr(),
|
||||
window_name.as_ptr(),
|
||||
winapi::WS_OVERLAPPEDWINDOW &
|
||||
!winapi::WS_MAXIMIZEBOX &
|
||||
!winapi::WS_THICKFRAME,
|
||||
flags,
|
||||
winapi::CW_USEDEFAULT,
|
||||
winapi::CW_USEDEFAULT,
|
||||
rect.right,
|
||||
|
@ -365,12 +388,12 @@ impl Window {
|
|||
pub fn new(name: &str,
|
||||
width: usize,
|
||||
height: usize,
|
||||
scale: Scale)
|
||||
opts: WindowOptions)
|
||||
-> Result<Window, &str> {
|
||||
unsafe {
|
||||
let scale_factor = Self::get_scale_factor(width, height, scale);
|
||||
let scale_factor = Self::get_scale_factor(width, height, opts.scale);
|
||||
|
||||
let handle = Self::open_window(name, width, height, scale_factor);
|
||||
let handle = Self::open_window(name, width, height, opts, scale_factor);
|
||||
|
||||
if handle.is_none() {
|
||||
return Err("Unable to create Window");
|
||||
|
@ -392,6 +415,11 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_window_handle(&self) -> *mut raw::c_void {
|
||||
self.window.unwrap() as *mut raw::c_void
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&mut self, x: isize, y: isize) {
|
||||
unsafe {
|
||||
|
@ -461,10 +489,8 @@ impl Window {
|
|||
return self.is_open
|
||||
}
|
||||
|
||||
pub fn update(&mut self, buffer: &[u32]) {
|
||||
fn generic_update(&mut self, window: HWND) {
|
||||
unsafe {
|
||||
let mut msg = mem::uninitialized();
|
||||
let window = self.window.unwrap();
|
||||
|
||||
let mut point: winapi::POINT = mem::uninitialized();
|
||||
user32::GetCursorPos(&mut point);
|
||||
|
@ -474,18 +500,15 @@ impl Window {
|
|||
self.mouse.y = point.y as f32;
|
||||
self.mouse.scroll = 0.0;
|
||||
|
||||
//self.mouse_data.x
|
||||
|
||||
//println!("{} {}", point.x, point.y);
|
||||
|
||||
self.key_handler.update();
|
||||
|
||||
// TODO: Optimize
|
||||
|
||||
self.buffer = buffer.iter().cloned().collect();
|
||||
|
||||
set_window_long(window, mem::transmute(self));
|
||||
user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
fn message_loop(&mut self, window: HWND) {
|
||||
unsafe {
|
||||
let mut msg = mem::uninitialized();
|
||||
|
||||
while user32::PeekMessageW(&mut msg, window, 0, 0, winapi::winuser::PM_REMOVE) != 0 {
|
||||
user32::TranslateMessage(&mut msg);
|
||||
|
@ -494,6 +517,26 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_with_buffer(&mut self, buffer: &[u32]) {
|
||||
let window = self.window.unwrap();
|
||||
|
||||
Self::generic_update(self, window);
|
||||
|
||||
self.buffer = buffer.iter().cloned().collect();
|
||||
unsafe {
|
||||
user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE);
|
||||
}
|
||||
|
||||
Self::message_loop(self, window);
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
let window = self.window.unwrap();
|
||||
|
||||
Self::generic_update(self, window);
|
||||
Self::message_loop(self, window);
|
||||
}
|
||||
|
||||
unsafe fn get_scale_factor(width: usize, height: usize, scale: Scale) -> i32 {
|
||||
let factor: i32 = match scale {
|
||||
Scale::X1 => 1,
|
||||
|
|
30
src/window_flags.rs
Normal file
30
src/window_flags.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
#[allow(dead_code)]
|
||||
const WINDOW_BORDERLESS: u32 = 1 << 1;
|
||||
#[allow(dead_code)]
|
||||
const WINDOW_RESIZE: u32 = 1 << 2;
|
||||
#[allow(dead_code)]
|
||||
const WINDOW_TITLE: u32 = 1 << 3;
|
||||
|
||||
use WindowOptions;
|
||||
|
||||
//
|
||||
// Construct a bitmask of flags (sent to backends) from WindowOpts
|
||||
//
|
||||
#[allow(dead_code)]
|
||||
pub fn get_flags(opts: WindowOptions) -> u32 {
|
||||
let mut flags = 0u32;
|
||||
|
||||
if opts.borderless {
|
||||
flags |= WINDOW_BORDERLESS;
|
||||
}
|
||||
|
||||
if opts.title {
|
||||
flags |= WINDOW_TITLE;
|
||||
}
|
||||
|
||||
if opts.resize {
|
||||
flags |= WINDOW_RESIZE;
|
||||
}
|
||||
|
||||
flags
|
||||
}
|
Loading…
Reference in a new issue