aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-01-03 16:53:27 +0100
committerLoïc Hoguin <[email protected]>2018-01-03 16:53:48 +0100
commitb8c213eaf6183208f87bad4cd583958ae9967cc9 (patch)
tree01982b5f6c1eb27397e7898b7f6bf1add3cc852c
parent68220e90d79bddfce27afe1a6c3ba990986b239e (diff)
downloadesdl2-b8c213eaf6183208f87bad4cd583958ae9967cc9.tar.gz
esdl2-b8c213eaf6183208f87bad4cd583958ae9967cc9.tar.bz2
esdl2-b8c213eaf6183208f87bad4cd583958ae9967cc9.zip
Add many sdl_keyboard functions
-rw-r--r--README.asciidoc6
-rw-r--r--c_src/esdl2.h9
-rw-r--r--c_src/sdl_events.c2
-rw-r--r--c_src/sdl_keyboard.c173
-rw-r--r--c_src/sdl_keycode.c1
-rw-r--r--src/esdl2.erl32
-rw-r--r--src/sdl_keyboard.erl42
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().