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;
use std::mem;
use {Key, KeyRepeat};
use {Key, KeyRepeat, InputCallback};
pub struct KeyHandler {
pub key_callback: Option<Box<InputCallback>>,
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<InputCallback>) {
self.key_callback = Some(callback);
}
pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> {
let mut index: u16 = 0;
let mut keys: Vec<Key> = Vec::new();

View file

@ -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<InputCallback>) {
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.

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;
win->key_callback = key_callback;
win->char_callback = char_callback;
win->rust_data = rust_data;
}

View file

@ -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;

View file

@ -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];
}

View file

@ -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<Window> {
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<InputCallback>) {
self.key_handler.set_input_callback(callback)
}
pub fn is_menu_pressed(&mut self) -> Option<usize> {
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)
}
#[inline]
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
self.key_handler.set_input_callback(callback)
}
#[inline]
pub fn is_open(&self) -> bool {
unsafe { mfb_should_close(self.window_handle) == 1 }

View file

@ -517,6 +517,11 @@ impl Window {
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]
pub fn set_key_repeat_delay(&mut self, delay: f32) {
self.key_handler.set_key_repeat_delay(delay)