From b8c213eaf6183208f87bad4cd583958ae9967cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Wed, 3 Jan 2018 16:53:27 +0100 Subject: Add many sdl_keyboard functions --- README.asciidoc | 6 +- c_src/esdl2.h | 9 +++ c_src/sdl_events.c | 2 +- c_src/sdl_keyboard.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++ c_src/sdl_keycode.c | 1 + src/esdl2.erl | 32 ++++++++++ src/sdl_keyboard.erl | 42 +++++++++++++ 7 files changed, 261 insertions(+), 4 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 035d91b..b3f2f19 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -57,7 +57,7 @@ corresponding to the public headers. ** `SDL_EventState` and `SDL_GetEventState` ** `SDL_RegisterEvents` * 'SDL_hints.h': We only have a proof of concept callback system. -* 'SDL_keyboard.h': Most of it is missing. +* 'SDL_keyboard.h': A few more functions are missing. * 'SDL_render.h': The following elements are missing: ** `SDL_TextureAccess` enum ** `SDL_TextureModulate` enum @@ -149,13 +149,13 @@ corresponding to the public headers. * 'SDL_gesture.h' * 'SDL_haptic.h' * 'SDL_joystick.h' -* 'SDL_keycode.h' +* 'SDL_keycode.h' (have a header containing the values) * 'SDL_messagebox.h' * 'SDL_pixels.h' * 'SDL_platform.h' * 'SDL_rect.h' (though we have a rect data type in sdl_renderer) * 'SDL_rwops.h' (unclear if we need it) -* 'SDL_scancode.h' +* 'SDL_scancode.h' (have a header containing the values) * 'SDL_shape.h' * 'SDL_system.h' * 'SDL_syswm.h' diff --git a/c_src/esdl2.h b/c_src/esdl2.h index 6899997..7fa237f 100644 --- a/c_src/esdl2.h +++ b/c_src/esdl2.h @@ -269,7 +269,15 @@ /* sdl_hints */ \ F(add_hint_callback, 3) \ /* sdl_keyboard */ \ + F(get_key_from_name, 1) \ + F(get_key_from_scancode, 1) \ + F(get_key_name, 1) \ + F(get_mod_state, 0) \ + F(get_scancode_from_key, 1) \ + F(get_scancode_from_name, 1) \ + F(get_scancode_name, 1) \ F(is_text_input_active, 0) \ + F(set_mod_state, 1) \ F(start_text_input, 0) \ F(stop_text_input, 0) \ /* sdl_mouse */ \ @@ -373,6 +381,7 @@ NIF_ENUM_TO_ATOM_FUNCTION_DECL(button_to_atom, Uint8) NIF_ENUM_TO_ATOM_FUNCTION_DECL(mousewheel_direction_to_atom, Uint32) NIF_ENUM_TO_ATOM_FUNCTION_DECL(window_event_to_atom, Uint8) +NIF_LIST_TO_FLAGS_FUNCTION_DECL(keymod_list_to_flags, Uint16) NIF_FLAGS_TO_LIST_FUNCTION_DECL(keymod_flags_to_list, Uint16) ERL_NIF_TERM mouse_state_to_list(ErlNifEnv*, Uint32); diff --git a/c_src/sdl_events.c b/c_src/sdl_events.c index 1d46760..653d5e1 100644 --- a/c_src/sdl_events.c +++ b/c_src/sdl_events.c @@ -101,7 +101,7 @@ static ERL_NIF_TERM keyboard_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_ enif_make_map_put(env, map, atom_scancode, enif_make_uint(env, event->key.keysym.scancode), &map); enif_make_map_put(env, map, atom_sym, - enif_make_uint(env, event->key.keysym.sym), &map); + enif_make_int(env, event->key.keysym.sym), &map); enif_make_map_put(env, map, atom_mod, keymod_flags_to_list(env, event->key.keysym.mod), &map); diff --git a/c_src/sdl_keyboard.c b/c_src/sdl_keyboard.c index f88b5ca..0e961a8 100644 --- a/c_src/sdl_keyboard.c +++ b/c_src/sdl_keyboard.c @@ -14,6 +14,161 @@ #include "esdl2.h" +// get_key_from_name + +NIF_FUNCTION(get_key_from_name) +{ + ErlNifBinary bin; + char* name; + SDL_Keycode key; + + BADARG_IF(!enif_inspect_binary(env, argv[0], &bin)); + + name = malloc(bin.size + 1); + memcpy(name, bin.data, bin.size); + name[bin.size] = '\0'; + + key = SDL_GetKeyFromName(name); + + free(name); + + if (key == SDLK_UNKNOWN) + return atom_undefined; + + return enif_make_int(env, key); +} + +// get_key_from_scancode + +NIF_FUNCTION(get_key_from_scancode) +{ + SDL_Scancode scancode; + SDL_Keycode key; + + BADARG_IF(!enif_get_uint(env, argv[0], &scancode)); + + key = SDL_GetKeyFromScancode(scancode); + + if (key == SDLK_UNKNOWN) + return atom_undefined; + + return enif_make_int(env, key); +} + +// get_key_name +// +// SDL_GetKeyName is not thread-safe as it stores the returned +// value in a static array in at least some cases. We use the +// NIF thread to avoid any issues. + +NIF_CALL_HANDLER(thread_get_key_name) +{ + const char* name; + ErlNifBinary bin; + + name = SDL_GetKeyName((long)args[0]); + + enif_alloc_binary(strlen(name), &bin); + + memcpy(bin.data, name, bin.size); + + return enif_make_binary(env, &bin); +} + +NIF_FUNCTION(get_key_name) +{ + SDL_Keycode key; + + BADARG_IF(!enif_get_int(env, argv[0], &key)); + + return nif_thread_call(env, thread_get_key_name, 1, key); +} + +// get_scancode_from_key + +NIF_FUNCTION(get_scancode_from_key) +{ + SDL_Keycode key; + SDL_Scancode scancode; + + BADARG_IF(!enif_get_int(env, argv[0], &key)); + + scancode = SDL_GetScancodeFromKey(key); + + if (scancode == SDL_SCANCODE_UNKNOWN) + return atom_undefined; + + return enif_make_uint(env, scancode); +} + +// get_scancode_from_name + +NIF_FUNCTION(get_scancode_from_name) +{ + ErlNifBinary bin; + char* name; + SDL_Scancode scancode; + + BADARG_IF(!enif_inspect_binary(env, argv[0], &bin)); + + name = malloc(bin.size + 1); + memcpy(name, bin.data, bin.size); + name[bin.size] = '\0'; + + scancode = SDL_GetScancodeFromName(name); + + free(name); + + if (scancode == SDL_SCANCODE_UNKNOWN) + return atom_undefined; + + return enif_make_uint(env, scancode); +} + +// get_scancode_name +// +// The SDL_GetScancodeName function only ever points to static +// data and is therefore thread-safe, unlike SDL_GetKeyName. + +NIF_FUNCTION(get_scancode_name) +{ + SDL_Scancode scancode; + const char* name; + ErlNifBinary bin; + + BADARG_IF(!enif_get_uint(env, argv[0], &scancode)); + + name = SDL_GetScancodeName(scancode); + + enif_alloc_binary(strlen(name), &bin); + + memcpy(bin.data, name, bin.size); + + return enif_make_binary(env, &bin); +} + +// @todo get_keyboard_focus +// @todo get_keyboard_state + +// get_mod_state + +NIF_CALL_HANDLER(thread_get_mod_state) +{ + SDL_Keymod mod; + + mod = SDL_GetModState(); + + return keymod_flags_to_list(env, mod); +} + +NIF_FUNCTION(get_mod_state) +{ + return nif_thread_call(env, thread_get_mod_state, 0); +} + +// @todo has_screen_keyboard_support +// @todo is_screen_keyboard_shown + // is_text_input_active NIF_CALL_HANDLER(thread_is_text_input_active) @@ -29,6 +184,24 @@ NIF_FUNCTION(is_text_input_active) return nif_thread_call(env, thread_is_text_input_active, 0); } +// set_mod_state + +NIF_CAST_HANDLER(thread_set_mod_state) +{ + SDL_SetModState((long)args[0]); +} + +NIF_FUNCTION(set_mod_state) +{ + Uint16 mod; + + BADARG_IF(!keymod_list_to_flags(env, argv[0], &mod)); + + return nif_thread_cast(env, thread_set_mod_state, 1, mod); +} + +// @todo set_text_input_rect + // start_text_input NIF_CAST_HANDLER(thread_start_text_input) diff --git a/c_src/sdl_keycode.c b/c_src/sdl_keycode.c index f558f83..fda2016 100644 --- a/c_src/sdl_keycode.c +++ b/c_src/sdl_keycode.c @@ -27,4 +27,5 @@ F(caps, KMOD_CAPS) \ F(mode, KMOD_MODE) +NIF_LIST_TO_FLAGS_FUNCTION(keymod_list_to_flags, Uint16, KEYMOD_FLAGS) NIF_FLAGS_TO_LIST_FUNCTION(keymod_flags_to_list, Uint16, KEYMOD_FLAGS) diff --git a/src/esdl2.erl b/src/esdl2.erl index 8470940..a8a1f61 100644 --- a/src/esdl2.erl +++ b/src/esdl2.erl @@ -80,7 +80,15 @@ -export([add_hint_callback/3]). %% sdl_keyboard +-export([get_key_from_name/1]). +-export([get_key_from_scancode/1]). +-export([get_key_name/1]). +-export([get_mod_state/0]). +-export([get_scancode_from_key/1]). +-export([get_scancode_from_name/1]). +-export([get_scancode_name/1]). -export([is_text_input_active/0]). +-export([set_mod_state/1]). -export([start_text_input/0]). -export([stop_text_input/0]). @@ -343,9 +351,33 @@ add_hint_callback(_, _, _) -> %% sdl_keyboard +get_key_from_name(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_key_from_scancode(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_key_name(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_mod_state() -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_scancode_from_key(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_scancode_from_name(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + +get_scancode_name(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + is_text_input_active() -> erlang:nif_error({not_loaded, ?MODULE}). +set_mod_state(_) -> + erlang:nif_error({not_loaded, ?MODULE}). + start_text_input() -> erlang:nif_error({not_loaded, ?MODULE}). diff --git a/src/sdl_keyboard.erl b/src/sdl_keyboard.erl index 0fc05f9..325c727 100644 --- a/src/sdl_keyboard.erl +++ b/src/sdl_keyboard.erl @@ -14,15 +14,57 @@ -module(sdl_keyboard). +-export([get_key_from_name/1]). +-export([get_key_from_scancode/1]). +-export([get_key_name/1]). +-export([get_mod_state/0]). +-export([get_scancode_from_key/1]). +-export([get_scancode_from_name/1]). +-export([get_scancode_name/1]). -export([is_text_input_active/0]). +-export([set_mod_state/1]). -export([start_text_input/0]). -export([stop_text_input/0]). +-spec get_key_from_name(binary()) -> non_neg_integer() | undefined. +get_key_from_name(Name) -> + esdl2:get_key_from_name(Name). + +-spec get_key_from_scancode(non_neg_integer()) -> non_neg_integer() | undefined. +get_key_from_scancode(Scancode) -> + esdl2:get_key_from_scancode(Scancode). + +-spec get_key_name(non_neg_integer()) -> binary(). +get_key_name(Key) -> + esdl2:get_key_name(Key), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_mod_state() -> [sdl_keycode:keymod()]. +get_mod_state() -> + esdl2:get_mod_state(), + receive {'_nif_thread_ret_', Ret} -> Ret end. + +-spec get_scancode_from_key(non_neg_integer()) -> non_neg_integer() | undefined. +get_scancode_from_key(Key) -> + esdl2:get_scancode_from_key(Key). + +-spec get_scancode_from_name(binary()) -> non_neg_integer() | undefined. +get_scancode_from_name(Name) -> + esdl2:get_scancode_from_name(Name). + +-spec get_scancode_name(non_neg_integer()) -> binary(). +get_scancode_name(Scancode) -> + esdl2:get_scancode_name(Scancode). + -spec is_text_input_active() -> boolean(). is_text_input_active() -> esdl2:is_text_input_active(), receive {'_nif_thread_ret_', Ret} -> Ret end. +-spec set_mod_state([sdl_keycode:keymod()]) -> ok. +set_mod_state(Mod) -> + esdl2:set_mod_state(Mod). + -spec start_text_input() -> ok. start_text_input() -> esdl2:start_text_input(). -- cgit v1.2.3