Implemented callback for characters

This is so when typing input on the keyboard characters may not match the layout in non-english for example. Currently Mac has been implemented to support this.
This commit is contained in:
Daniel Collin 2016-05-01 16:02:29 +02:00
parent 3c3dcd7c07
commit eaf12ebb29
8 changed files with 68 additions and 5 deletions

View file

@ -1,9 +1,10 @@
extern crate time; extern crate time;
use std::mem; use std::mem;
use {Key, KeyRepeat}; use {Key, KeyRepeat, InputCallback};
pub struct KeyHandler { pub struct KeyHandler {
pub key_callback: Option<Box<InputCallback>>,
prev_time: f64, prev_time: f64,
delta_time: f32, delta_time: f32,
keys: [bool; 512], keys: [bool; 512],
@ -15,6 +16,7 @@ pub struct KeyHandler {
impl KeyHandler { impl KeyHandler {
pub fn new() -> KeyHandler { pub fn new() -> KeyHandler {
KeyHandler { KeyHandler {
key_callback: None,
keys: [false; 512], keys: [false; 512],
keys_down_duration: [-1.0; 512], keys_down_duration: [-1.0; 512],
prev_time: time::precise_time_s(), prev_time: time::precise_time_s(),
@ -65,6 +67,10 @@ impl KeyHandler {
} }
} }
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.key_callback = Some(callback);
}
pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> { pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> {
let mut index: u16 = 0; let mut index: u16 = 0;
let mut keys: Vec<Key> = Vec::new(); let mut keys: Vec<Key> = Vec::new();

View file

@ -54,6 +54,12 @@ pub enum MouseMode {
Discard, 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; extern crate libc;
use std::os::raw; use std::os::raw;
@ -433,6 +439,14 @@ impl Window {
self.0.is_active() self.0.is_active()
} }
///
/// Set input callback to recive callback on char input
///
#[inline]
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.0.set_input_callback(callback)
}
/// ///
/// This allows adding menus to your windows. As menus behaves a bit diffrently depending on /// 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. /// Operating system here is how it works. See [Menu] for description on each field.

View file

@ -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; OSXWindow* win = (OSXWindow*)window;
win->key_callback = key_callback; win->key_callback = key_callback;
win->char_callback = char_callback;
win->rust_data = rust_data; win->rust_data = rust_data;
} }

View file

@ -41,6 +41,7 @@ void build_submenu(NSMenu* menu, MenuDesc* desc);
{ {
NSView* childContentView; NSView* childContentView;
@public void (*key_callback)(void* user_data, int key, int state); @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 width;
@public int height; @public int height;
@public int scale; @public int scale;

View file

@ -71,6 +71,14 @@
key_callback(rust_data, [event keyCode], 1); 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]; [super keyDown:event];
} }

View file

@ -4,6 +4,7 @@ use {MouseButton, MouseMode, Scale, Key, KeyRepeat, WindowOptions};
use key_handler::KeyHandler; use key_handler::KeyHandler;
use error::Error; use error::Error;
use Result; use Result;
use InputCallback;
use mouse_handler; use mouse_handler;
use window_flags; use window_flags;
use menu::Menu; use menu::Menu;
@ -170,7 +171,9 @@ extern {
fn mfb_update(window: *mut c_void); fn mfb_update(window: *mut c_void);
fn mfb_update_with_buffer(window: *mut c_void, buffer: *const c_uchar); 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_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_set_mouse_data(window_handle: *mut c_void, shared_data: *mut SharedData);
fn mfb_should_close(window: *mut c_void) -> i32; fn mfb_should_close(window: *mut c_void) -> i32;
fn mfb_get_screen_size() -> u32; 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 { impl Window {
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> { pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> {
let n = match CString::new(name) { let n = match CString::new(name) {
@ -261,7 +277,7 @@ impl Window {
unsafe { unsafe {
mfb_update_with_buffer(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); 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 { unsafe {
mfb_update(self.window_handle); mfb_update(self.window_handle);
Self::set_mouse_data(self); 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) self.key_handler.is_key_pressed(key, repeat)
} }
#[inline]
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.key_handler.set_input_callback(callback)
}
pub fn is_menu_pressed(&mut self) -> Option<usize> { pub fn is_menu_pressed(&mut self) -> Option<usize> {
let menu_id = unsafe { mfb_active_menu(self.window_handle) }; let menu_id = unsafe { mfb_active_menu(self.window_handle) };

View file

@ -293,6 +293,11 @@ impl Window {
self.key_handler.is_key_pressed(key, repeat) self.key_handler.is_key_pressed(key, repeat)
} }
#[inline]
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.key_handler.set_input_callback(callback)
}
#[inline] #[inline]
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
unsafe { mfb_should_close(self.window_handle) == 1 } unsafe { mfb_should_close(self.window_handle) == 1 }

View file

@ -517,6 +517,11 @@ impl Window {
self.key_handler.is_key_down(key) self.key_handler.is_key_down(key)
} }
#[inline]
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.key_handler.set_input_callback(callback)
}
#[inline] #[inline]
pub fn set_key_repeat_delay(&mut self, delay: f32) { pub fn set_key_repeat_delay(&mut self, delay: f32) {
self.key_handler.set_key_repeat_delay(delay) self.key_handler.set_key_repeat_delay(delay)