diff --git a/src/key_handler.rs b/src/key_handler.rs index 1f6233c..1a09d44 100644 --- a/src/key_handler.rs +++ b/src/key_handler.rs @@ -1,9 +1,10 @@ extern crate time; use std::mem; -use {Key, KeyRepeat}; +use {Key, KeyRepeat, InputCallback}; pub struct KeyHandler { + pub key_callback: Option>, prev_time: f64, delta_time: f32, keys: [bool; 512], @@ -15,6 +16,7 @@ pub struct KeyHandler { impl KeyHandler { pub fn new() -> KeyHandler { KeyHandler { + key_callback: None, keys: [false; 512], keys_down_duration: [-1.0; 512], prev_time: time::precise_time_s(), @@ -65,6 +67,10 @@ impl KeyHandler { } } + pub fn set_input_callback(&mut self, callback: Box) { + self.key_callback = Some(callback); + } + pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option> { let mut index: u16 = 0; let mut keys: Vec = Vec::new(); diff --git a/src/lib.rs b/src/lib.rs index c99e789..7b92226 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,12 @@ pub enum MouseMode { Discard, } +/// 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); +} + extern crate libc; use std::os::raw; @@ -433,6 +439,14 @@ impl Window { self.0.is_active() } + /// + /// Set input callback to recive callback on char input + /// + #[inline] + pub fn set_input_callback(&mut self, callback: Box) { + self.0.set_input_callback(callback) + } + /// /// This allows adding menus to your windows. As menus behaves a bit diffrently depending on /// Operating system here is how it works. See [Menu] for description on each field. diff --git a/src/native/macosx/MacMiniFB.m b/src/native/macosx/MacMiniFB.m index 5d8b157..70f9985 100644 --- a/src/native/macosx/MacMiniFB.m +++ b/src/native/macosx/MacMiniFB.m @@ -315,10 +315,13 @@ uint32_t mfb_get_screen_size() /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void mfb_set_key_callback(void* window, void* rust_data, void (*key_callback)(void* user_data, int key, int state)) +void mfb_set_key_callback(void* window, void* rust_data, + void (*key_callback)(void* user_data, int key, int state), + void (*char_callback)(void* user_data, uint32_t key)) { OSXWindow* win = (OSXWindow*)window; win->key_callback = key_callback; + win->char_callback = char_callback; win->rust_data = rust_data; } diff --git a/src/native/macosx/OSXWindow.h b/src/native/macosx/OSXWindow.h index 5d0dd20..d938024 100644 --- a/src/native/macosx/OSXWindow.h +++ b/src/native/macosx/OSXWindow.h @@ -41,6 +41,7 @@ void build_submenu(NSMenu* menu, MenuDesc* desc); { NSView* childContentView; @public void (*key_callback)(void* user_data, int key, int state); + @public void (*char_callback)(void* user_data, unsigned int key); @public int width; @public int height; @public int scale; diff --git a/src/native/macosx/OSXWindow.m b/src/native/macosx/OSXWindow.m index a468278..7cc1e02 100644 --- a/src/native/macosx/OSXWindow.m +++ b/src/native/macosx/OSXWindow.m @@ -71,6 +71,14 @@ key_callback(rust_data, [event keyCode], 1); } + if (char_callback) { + NSString* characters = [event characters]; + NSUInteger i, length = [characters length]; + + for (i = 0; i < length; i++) + char_callback(rust_data, [characters characterAtIndex:i]); + } + [super keyDown:event]; } diff --git a/src/os/macos/mod.rs b/src/os/macos/mod.rs index ca9fa35..bfd43d9 100644 --- a/src/os/macos/mod.rs +++ b/src/os/macos/mod.rs @@ -4,6 +4,7 @@ use {MouseButton, MouseMode, Scale, Key, KeyRepeat, WindowOptions}; use key_handler::KeyHandler; use error::Error; use Result; +use InputCallback; use mouse_handler; use window_flags; use menu::Menu; @@ -170,7 +171,9 @@ extern { 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_key_callback(window: *mut c_void, target: *mut c_void, + cb: unsafe extern fn(*mut c_void, i32, i32), + cb: unsafe extern fn(*mut c_void, u32)); fn mfb_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData); fn mfb_should_close(window: *mut c_void) -> i32; fn mfb_get_screen_size() -> u32; @@ -213,6 +216,19 @@ unsafe extern "C" fn key_callback(window: *mut c_void, key: i32, state: i32) { } } +unsafe extern "C" fn char_callback(window: *mut c_void, code_point: u32) { + let win: *mut Window = mem::transmute(window); + + // Taken from GLFW + if code_point < 32 || (code_point > 126 && code_point < 160) { + return; + } + + if let Some(ref mut callback) = (*win).key_handler.key_callback { + callback.add_char(code_point); + } +} + impl Window { pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result { let n = match CString::new(name) { @@ -261,7 +277,7 @@ impl Window { unsafe { 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); + mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback, char_callback); } } @@ -271,7 +287,7 @@ impl Window { unsafe { mfb_update(self.window_handle); Self::set_mouse_data(self); - mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback); + mfb_set_key_callback(self.window_handle, mem::transmute(self), key_callback, char_callback); } } @@ -341,6 +357,11 @@ impl Window { self.key_handler.is_key_pressed(key, repeat) } + #[inline] + pub fn set_input_callback(&mut self, callback: Box) { + self.key_handler.set_input_callback(callback) + } + pub fn is_menu_pressed(&mut self) -> Option { let menu_id = unsafe { mfb_active_menu(self.window_handle) }; diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs index 3adb5a3..30903d5 100644 --- a/src/os/unix/mod.rs +++ b/src/os/unix/mod.rs @@ -293,6 +293,11 @@ impl Window { self.key_handler.is_key_pressed(key, repeat) } + #[inline] + pub fn set_input_callback(&mut self, callback: Box) { + self.key_handler.set_input_callback(callback) + } + #[inline] pub fn is_open(&self) -> bool { unsafe { mfb_should_close(self.window_handle) == 1 } diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index c88af82..7669a69 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -517,6 +517,11 @@ impl Window { self.key_handler.is_key_down(key) } + #[inline] + pub fn set_input_callback(&mut self, callback: Box) { + self.key_handler.set_input_callback(callback) + } + #[inline] pub fn set_key_repeat_delay(&mut self, delay: f32) { self.key_handler.set_key_repeat_delay(delay)