1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use num::FromPrimitive;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ptr;

use keycode::KeyCode;
use rect::Rect;
use scancode::ScanCode;
use video::Window;

use sys::keyboard as ll;

bitflags! {
    flags Mod: u32 {
        const NOMOD = 0x0000,
        const LSHIFTMOD = 0x0001,
        const RSHIFTMOD = 0x0002,
        const LCTRLMOD = 0x0040,
        const RCTRLMOD = 0x0080,
        const LALTMOD = 0x0100,
        const RALTMOD = 0x0200,
        const LGUIMOD = 0x0400,
        const RGUIMOD = 0x0800,
        const NUMMOD = 0x1000,
        const CAPSMOD = 0x2000,
        const MODEMOD = 0x4000,
        const RESERVEDMOD = 0x8000
    }
}

pub fn get_keyboard_focus() -> Option<Window> {
    let raw = unsafe { ll::SDL_GetKeyboardFocus() };
    if raw == ptr::null_mut() {
        None
    } else {
        unsafe { Some(Window::from_ll(raw, false)) }
    }
}

pub fn get_keyboard_state() -> HashMap<ScanCode, bool> {
    let mut state: HashMap<ScanCode, bool> = HashMap::new();
    let mut count = 0;

    let state_ptr = unsafe { ll::SDL_GetKeyboardState(&mut count) };
    let raw = unsafe { ::std::slice::from_raw_parts(state_ptr,
                                          count as usize) };

    let mut current = 0;
    while current < raw.len() {
        state.insert(FromPrimitive::from_isize(current as isize)
                        .unwrap_or(ScanCode::Unknown),
                     raw[current] == 1);
        current += 1;
    }

    return state;
}

pub fn get_mod_state() -> Mod {
    unsafe { Mod::from_bits(ll::SDL_GetModState()).unwrap() }
}

pub fn set_mod_state(flags: Mod) {
    unsafe { ll::SDL_SetModState(flags.bits()); }
}

pub fn get_key_from_scancode(scancode: ScanCode) -> KeyCode {
    unsafe {
        FromPrimitive::from_isize(ll::SDL_GetKeyFromScancode(scancode as u32) as isize)
            .unwrap_or(KeyCode::Unknown)
    }
}

pub fn get_scancode_from_key(key: KeyCode) -> ScanCode {
    unsafe {
        FromPrimitive::from_isize(ll::SDL_GetScancodeFromKey(key as i32) as isize)
            .unwrap_or(ScanCode::Unknown)
    }
}

pub fn get_scancode_name(scancode: ScanCode) -> String {
    unsafe {
        let scancode_name = ll::SDL_GetScancodeName(scancode as u32);
        String::from_utf8_lossy(CStr::from_ptr(scancode_name).to_bytes()).into_owned()
    }
}

pub fn get_scancode_from_name(name: &str) -> ScanCode {
    unsafe {
        match CString::new(name) {
            Ok(name) => FromPrimitive::from_isize(ll::SDL_GetScancodeFromName(name.as_ptr()) as isize).unwrap_or(ScanCode::Unknown),
            // string contains a nul byte - it won't match anything.
            Err(_) => ScanCode::Unknown
        }
    }
}

pub fn get_key_name(key: KeyCode) -> String {
    unsafe {
        let key_name = ll::SDL_GetKeyName(key as i32);
        String::from_utf8_lossy(CStr::from_ptr(key_name).to_bytes()).to_string()
    }
}

pub fn get_key_from_name(name: &str) -> KeyCode {
    unsafe {
        match CString::new(name) {
            Ok(name) => FromPrimitive::from_isize(ll::SDL_GetKeyFromName(name.as_ptr()) as isize).unwrap_or(KeyCode::Unknown),
            // string contains a nul byte - it won't match anything.
            Err(_) => KeyCode::Unknown
        }
    }
}

pub fn start_text_input() {
    unsafe { ll::SDL_StartTextInput(); }
}

pub fn is_text_input_active() -> bool {
    unsafe { ll::SDL_IsTextInputActive() == 1 }
}

pub fn stop_text_input() {
    unsafe { ll::SDL_StopTextInput(); }
}

pub fn set_text_input_rect(rect: &Rect) {
    unsafe { ll::SDL_SetTextInputRect(rect); }
}

pub fn has_screen_keyboard_support() -> bool {
    unsafe { ll::SDL_HasScreenKeyboardSupport() == 1 }
}

pub fn is_screen_keyboard_shown(window: &Window) -> bool {
    unsafe { ll::SDL_IsScreenKeyboardShown(window.raw()) == 1 }
}