Added set_title and set_cursor_style

This commit is contained in:
Daniel Collin 2016-06-24 13:08:01 +02:00
parent b231ee1b5a
commit 495f7c4cca
9 changed files with 621 additions and 314 deletions

View file

@ -14,7 +14,6 @@ build = "build.rs"
gcc = "0.3.19"
[dependencies]
libc = "0.2"
time = "0.1.34"
[target.x86_64-pc-windows-msvc.dependencies]

79
examples/title_cursor.rs Normal file
View file

@ -0,0 +1,79 @@
extern crate minifb;
use minifb::{CursorStyle, Window, Key, Scale, WindowOptions, MouseMode};
const WIDTH: usize = 640;
const HEIGHT: usize = 360;
struct Rect {
x: usize,
y: usize,
width: usize,
height: usize,
color: u32,
cursor_style: CursorStyle,
}
impl Rect {
pub fn is_inside(&self, xf: f32, yf: f32) -> bool {
let x = xf as usize;
let y = yf as usize;
let xe = self.x + self.width;
let ye = self.y + self.height;
if (y >= self.y) && (y <= ye) &&
(x >= self.x) && (x <= xe) {
true
} else {
false
}
}
}
fn fill_rect(dest: &mut [u32], rect: &Rect) {
for y in 0..rect.height {
for x in 0..rect.width {
dest[((rect.y + y) * WIDTH) + rect.x + x] = rect.color;
}
}
}
fn main() {
let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
let mut window = Window::new("I haz no title :(",
WIDTH,
HEIGHT,
WindowOptions {
resize: true,
scale: Scale::X2,
..WindowOptions::default()
})
.expect("Unable to Open Window");
let rects = [
Rect { x: 0, y: 0, width: 160, height: 180, color: 0x00b27474, cursor_style: CursorStyle::Arrow },
Rect { x: 160, y: 0, width: 160, height: 180, color: 0x00b28050, cursor_style: CursorStyle::Ibeam },
Rect { x: 320, y: 0, width: 160, height: 180, color: 0x00a9b250, cursor_style: CursorStyle::Crosshair },
Rect { x: 480, y: 0, width: 160, height: 180, color: 0x0060b250, cursor_style: CursorStyle::ClosedHand },
Rect { x: 0, y: 180, width: 160, height: 180, color: 0x004fb292, cursor_style: CursorStyle::OpenHand },
Rect { x: 160, y: 180, width: 160, height: 180, color: 0x004f71b2, cursor_style: CursorStyle::ResizeLeftRight },
Rect { x: 320, y: 180, width: 160, height: 180, color: 0x008850b2, cursor_style: CursorStyle::ResizeUpDown },
Rect { x: 480, y: 180, width: 160, height: 180, color: 0x00b25091, cursor_style: CursorStyle::ResizeAll }
];
window.set_title("Diffrent cursor on each color region");
while window.is_open() && !window.is_key_down(Key::Escape) {
let (mx, my) = window.get_mouse_pos(MouseMode::Clamp).unwrap();
for rect in &rects {
fill_rect(&mut buffer, rect);
if rect.is_inside(mx, my) {
window.set_cursor_style(rect.cursor_style);
}
}
window.update_with_buffer(&buffer);
}
}

View file

@ -2,8 +2,6 @@
//! open windows (usually native to the running operating system) and can optionally show a 32-bit
//! buffer. minifb also support keyboard, mouse input and menus on selected operating systems.
//!
extern crate libc;
use std::os::raw;
/// Scale will scale the frame buffer and the window that is being sent in when calling the update
@ -51,7 +49,7 @@ pub enum MouseButton
}
/// Key is used by the get key functions to check if some keys on the keyboard has been pressed
/// The diffrent modes that can be used to decide how mouse coordinates should be handled
#[derive(PartialEq, Clone, Copy)]
pub enum MouseMode {
/// Return mouse coords from outside of the window (may be negative)
@ -62,14 +60,33 @@ pub enum MouseMode {
Discard,
}
/// Different style of cursors that can be used
#[derive(PartialEq, Clone, Copy)]
pub enum CursorStyle {
/// Regular arrow style (this is what the cursor normal looks like)
Arrow,
/// Used when indicating insertion (like text field)
Ibeam,
/// Cross-hair cursor
Crosshair,
/// Closed hand which useful for dragging things, may use default hand on unsupported OSes.
ClosedHand,
/// Open hand which useful for indicating drangable things, may use default hand on unsupported OSes.
OpenHand,
/// Rezining left-rigth direction
ResizeLeftRight,
/// Rezining up-down direction
ResizeUpDown,
/// Resize in all directions
ResizeAll,
}
/// This trait can be implemented and set with ```set_input_callback``` to reieve a callback
/// whene there is inputs incoming. Currently only support unicode chars.
pub trait InputCallback {
fn add_char(&mut self, uni_char: u32);
}
#[doc(hidden)]
mod error;
pub use self::error::Error;
@ -163,6 +180,21 @@ impl Window {
imp::Window::new(name, width, height, opts).map(Window)
}
///
/// Allows you to set a new title of the window after creation
///
/// # Examples
///
/// ```ignore
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
///
/// window.set_title("My New Title!");
/// ```
///
pub fn set_title(&mut self, title: &str) {
self.0.set_title(title)
}
///
/// Returns the native handle for a window which is an opaque pointer/handle which
/// dependens on the current operating system:
@ -314,6 +346,20 @@ impl Window {
self.0.get_scroll_wheel()
}
///
/// Set a diffrent cursor style. This can be used if you have resizing
/// elements or something like that
///
/// # Examples
///
/// ```ignore
/// window.set_cursor_style(CursorStyle::ResizeLeftRight);
/// ```
///
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
self.0.set_cursor_style(cursor)
}
///
/// Get the current keys that are down.
///

View file

@ -13,6 +13,34 @@ const uint32_t WINDOW_TITLE = 1 << 3;
static void create_standard_menu();
// Needs to match lib.rs enum
enum CursorStyle {
CursorStyle_Arrow,
CursorStyle_Ibeam,
CursorStyle_Crosshair,
CursorStyle_ClosedHand,
CursorStyle_OpenHand,
CursorStyle_ResizeLeftRight,
CursorStyle_ResizeUpDown,
CursorStyle_SizeAll,
CursorStyle_Count,
};
static NSCursor* s_cursors[CursorStyle_Count];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void cursor_init() {
s_cursors[CursorStyle_Arrow] = [[NSCursor arrowCursor] retain];
s_cursors[CursorStyle_Ibeam] = [[NSCursor IBeamCursor] retain];
s_cursors[CursorStyle_Crosshair] = [[NSCursor crosshairCursor] retain];
s_cursors[CursorStyle_ClosedHand] = [[NSCursor closedHandCursor] retain];
s_cursors[CursorStyle_OpenHand] = [[NSCursor openHandCursor] retain];
s_cursors[CursorStyle_ResizeLeftRight] = [[NSCursor resizeLeftRightCursor] retain];
s_cursors[CursorStyle_ResizeUpDown] = [[NSCursor resizeUpDownCursor] retain];
s_cursors[CursorStyle_SizeAll] = [[NSCursor closedHandCursor] retain];
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __clang__
@ -31,6 +59,7 @@ void* mfb_open(const char* name, int width, int height, uint32_t flags, int scal
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
create_standard_menu();
cursor_init();
s_init = true;
}
@ -63,6 +92,7 @@ void* mfb_open(const char* name, int width, int height, uint32_t flags, int scal
window->key_callback = 0;
window->shared_data = 0;
window->active_menu_id = -1;
window->prev_cursor = 0;
window->menu_data = malloc(sizeof(MenuData));
memset(window->menu_data, 0, sizeof(MenuData));
@ -195,6 +225,14 @@ static void create_standard_menu(void)
//[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_title(void* window, const char* title)
{
OSXWindow* win = (OSXWindow*)window;
NSString* ns_title = [NSString stringWithUTF8String: title];
[win setTitle: ns_title];
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -336,6 +374,25 @@ void mfb_set_mouse_data(void* window, SharedData* shared_data)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_cursor_style(void* window, int cursor)
{
OSXWindow* win = (OSXWindow*)window;
if (win->prev_cursor == cursor)
return;
if (cursor < 0 || cursor >= CursorStyle_Count) {
printf("cursor out of range %d\n", cursor);
return;
}
[s_cursors[cursor] set];
win->prev_cursor = cursor;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t mfb_is_active(void* window)
{
OSXWindow* win = (OSXWindow*)window;

View file

@ -51,6 +51,7 @@ void build_submenu(NSMenu* menu, MenuDesc* desc);
@public bool should_close;
@public bool is_active;
@public int active_menu_id;
@public int prev_cursor;
@public MenuData* menu_data;
}

View file

@ -1,6 +1,7 @@
#include <X11/Xresource.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xcursor/Xcursor.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -34,6 +35,21 @@ static int s_screen_height;
static XContext s_context;
static Atom s_wm_delete_window;
// Needs to match lib.rs enum
enum CursorStyle {
CursorStyle_Arrow,
CursorStyle_Ibeam,
CursorStyle_Crosshair,
CursorStyle_ClosedHand,
CursorStyle_OpenHand,
CursorStyle_ResizeLeftRight,
CursorStyle_ResizeUpDown,
CursorStyle_SizeAll,
CursorStyle_Count,
};
static Cursor s_cursors[CursorStyle_Count];
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct SharedData {
@ -60,10 +76,24 @@ typedef struct WindowInfo {
int width;
int height;
int update;
int prev_cursor;
} WindowInfo;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void init_cursors() {
s_cursors[CursorStyle_Arrow] = XcursorLibraryLoadCursor(s_display, "arrow");
s_cursors[CursorStyle_Ibeam] = XcursorLibraryLoadCursor(s_display, "xterm");
s_cursors[CursorStyle_Crosshair] = XcursorLibraryLoadCursor(s_display, "crosshair");
s_cursors[CursorStyle_ClosedHand] = XcursorLibraryLoadCursor(s_display, "hand2");
s_cursors[CursorStyle_OpenHand] = XcursorLibraryLoadCursor(s_display, "hand2");
s_cursors[CursorStyle_ResizeLeftRight] = XcursorLibraryLoadCursor(s_display, "sb_h_double_arrow");
s_cursors[CursorStyle_ResizeUpDown] = XcursorLibraryLoadCursor(s_display, "sb_v_double_arrow");
s_cursors[CursorStyle_SizeAll] = XcursorLibraryLoadCursor(s_display, "diamond_cross");
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int setup_display() {
int depth, i, formatCount, convDepth = -1;
XPixmapFormatValues* formats;
@ -113,6 +143,8 @@ static int setup_display() {
s_setup_done = 1;
init_cursors();
return 1;
}
@ -205,6 +237,14 @@ void* mfb_open(const char* title, int width, int height, unsigned int flags, int
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_title(void* window_info, const char* title)
{
WindowInfo* info = (WindowInfo*)window_info;
XStoreName(s_display, info->window, title);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static WindowInfo* find_handle(Window handle)
{
WindowInfo* info;
@ -218,6 +258,25 @@ static WindowInfo* find_handle(Window handle)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void mfb_set_cursor_style(void* window_info, int cursor)
{
WindowInfo* info = (WindowInfo*)window_info;
if (info->prev_cursor == cursor)
return;
if (cursor < 0 || cursor >= CursorStyle_Count) {
printf("cursor out of range %d\n", cursor);
return;
}
XDefineCursor(s_display, info->window, s_cursors[cursor]);
info->prev_cursor = cursor;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int process_event(XEvent* event) {
KeySym sym;

View file

@ -8,10 +8,10 @@ use Result;
use InputCallback;
use mouse_handler;
use window_flags;
use {MenuItem, MenuItemHandle, MenuHandle};
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
// use menu::Menu;
use libc::{c_void, c_char, c_uchar};
use std::os::raw::{c_void, c_char, c_uchar};
use std::ffi::CString;
use std::ptr;
use std::mem;
@ -159,6 +159,7 @@ extern "C" {
flags: u32,
scale: i32)
-> *mut c_void;
fn mfb_set_title(window: *mut c_void, title: *const c_char);
fn mfb_close(window: *mut c_void);
fn mfb_update(window: *mut c_void);
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
@ -168,6 +169,7 @@ extern "C" {
cb: unsafe extern "C" fn(*mut c_void, i32, i32),
cb: unsafe extern "C" fn(*mut c_void, u32));
fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData);
fn mfb_set_cursor_style(window: *mut c_void, cursor: u32);
fn mfb_should_close(window: *mut c_void) -> i32;
fn mfb_get_screen_size() -> u32;
fn mfb_is_active(window: *mut c_void) -> u32;
@ -271,6 +273,14 @@ impl Window {
}
}
#[inline]
pub fn set_title(&mut self, title: &str) {
unsafe {
let t = CString::new(title).unwrap();
mfb_set_title(self.window_handle, t.as_ptr());
}
}
#[inline]
pub fn get_window_handle(&self) -> *mut raw::c_void {
self.window_handle as *mut raw::c_void
@ -349,6 +359,13 @@ impl Window {
h)
}
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
mfb_set_cursor_style(self.window_handle, cursor as u32);
}
}
#[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()

View file

@ -8,13 +8,12 @@ extern crate x11_dl;
use {MouseMode, MouseButton, Scale, Key, KeyRepeat, WindowOptions, InputCallback};
use key_handler::KeyHandler;
//use menu::Menu;
use self::x11_dl::keysym::*;
use error::Error;
use Result;
use {MenuItem, MenuItemHandle, MenuHandle, UnixMenu, UnixMenuItem};
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle, UnixMenu, UnixMenuItem};
use libc::{c_void, c_char, c_uchar};
use std::os::raw::{c_void, c_char, c_uchar};
use std::ffi::{CString};
use std::ptr;
use std::mem;
@ -23,8 +22,10 @@ use mouse_handler;
use window_flags;
#[link(name = "X11")]
#[link(name = "Xcursor")]
extern {
fn mfb_open(name: *const c_char, width: u32, height: u32, flags: u32, scale: i32) -> *mut c_void;
fn mfb_set_title(window: *mut c_void, title: *const c_char);
fn mfb_close(window: *mut c_void);
fn mfb_update(window: *mut c_void);
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar);
@ -33,6 +34,7 @@ extern {
fn mfb_set_shared_data(window: *mut c_void, target: *mut SharedData);
fn mfb_should_close(window: *mut c_void) -> i32;
fn mfb_get_screen_size() -> u32;
fn mfb_set_cursor_style(window: *mut c_void, cursor: u32);
fn mfb_get_window_handle(window: *mut c_void) -> *mut c_void;
}
@ -204,6 +206,13 @@ impl Window {
}
}
pub fn set_title(&mut self, title: &str) {
unsafe {
let t = CString::new(title).unwrap();
mfb_set_title(self.window_handle, t.as_ptr());
}
}
unsafe fn set_shared_data(&mut self) {
mfb_set_shared_data(self.window_handle, &mut self.shared_data);
}
@ -268,6 +277,13 @@ impl Window {
}
}
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
mfb_set_cursor_style(self.window_handle, cursor as u32);
}
}
#[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()

View file

@ -12,7 +12,7 @@ use {Scale, Key, KeyRepeat, MouseButton, MouseMode, WindowOptions, InputCallback
use key_handler::KeyHandler;
use error::Error;
use Result;
use {MenuItem, MenuItemHandle, MenuHandle};
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
use {MENU_KEY_WIN, MENU_KEY_SHIFT, MENU_KEY_CTRL, MENU_KEY_ALT};
use std::ptr;
@ -331,6 +331,8 @@ pub struct Window {
key_handler: KeyHandler,
accel_table: HACCEL,
accel_key: usize,
prev_cursor: CursorStyle,
cursors: [winapi::HCURSOR; 8],
}
// TranslateAccelerator is currently missing in win-rs
@ -454,12 +456,31 @@ impl Window {
menus: Vec::new(),
accel_table: ptr::null_mut(),
accel_key: INVALID_ACCEL,
prev_cursor: CursorStyle::Arrow,
cursors: [
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_ARROW),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_IBEAM),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_CROSS),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_HAND),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_HAND),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZENS),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZEWE),
user32::LoadCursorW(ptr::null_mut(), winuser::IDC_SIZEALL),
],
};
Ok(window)
}
}
#[inline]
pub fn set_title(&mut self, title: &str) {
unsafe {
let title_name = to_wstring(title);
user32::SetWindowTextW(self.window.unwrap(), title_name.as_ptr());
}
}
#[inline]
pub fn get_window_handle(&self) -> *mut raw::c_void {
self.window.unwrap() as *mut raw::c_void
@ -503,6 +524,19 @@ impl Window {
}
}
#[inline]
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
unsafe {
if self.prev_cursor == cursor {
return;
}
user32::SetCursor(self.cursors[cursor as usize]);
self.prev_cursor = cursor;
}
}
#[inline]
pub fn get_keys(&self) -> Option<Vec<Key>> {
self.key_handler.get_keys()
@ -538,7 +572,6 @@ impl Window {
self.key_handler.is_key_pressed(key, repeat)
}
#[inline]
pub fn is_open(&self) -> bool {
return self.is_open