aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2018-01-02 12:47:39 +0100
committerLoïc Hoguin <[email protected]>2018-01-02 12:47:39 +0100
commitb30bc1ccd23e909f281c742629281e822854e802 (patch)
tree6e9ee7f064626c121edfec2d1ca58acc21fa0b8b
parent1284144bc49474dc2377047cdd99502247dbded2 (diff)
downloadesdl2-b30bc1ccd23e909f281c742629281e822854e802.tar.gz
esdl2-b30bc1ccd23e909f281c742629281e822854e802.tar.bz2
esdl2-b30bc1ccd23e909f281c742629281e822854e802.zip
Add many events and event functions
-rw-r--r--c_src/esdl2.h61
-rw-r--r--c_src/sdl_events.c504
-rw-r--r--c_src/sdl_keycode.c30
-rw-r--r--c_src/sdl_mouse.c18
-rw-r--r--c_src/sdl_window.c20
-rw-r--r--ebin/esdl2.app2
-rw-r--r--src/esdl2.erl24
-rw-r--r--src/sdl_events.erl98
-rw-r--r--src/sdl_keycode.erl19
-rw-r--r--src/sdl_mouse.erl15
-rw-r--r--src/sdl_window.erl5
11 files changed, 623 insertions, 173 deletions
diff --git a/c_src/esdl2.h b/c_src/esdl2.h
index 5a1ec99..bd80acf 100644
--- a/c_src/esdl2.h
+++ b/c_src/esdl2.h
@@ -23,8 +23,16 @@
A(accelerated) \
A(add) \
A(allow_high_dpi) \
+ A(app_did_enter_background) \
+ A(app_did_enter_foreground) \
+ A(app_low_memory) \
+ A(app_terminating) \
+ A(app_will_enter_background) \
+ A(app_will_enter_foreground) \
A(arrow) \
A(audio) \
+ A(audio_device_added) \
+ A(audio_device_removed) \
A(blend) \
A(borderless) \
A(button) \
@@ -34,10 +42,24 @@
A(charged) \
A(charging) \
A(clicks) \
+ A(clipboard_update) \
A(close) \
+ A(controller_axis_motion) \
+ A(controller_button_down) \
+ A(controller_button_up) \
+ A(controller_device_added) \
+ A(controller_device_remapped) \
+ A(controller_device_removed) \
A(crosshair) \
- A(data) \
+ A(data1) \
+ A(data2) \
A(direction) \
+ A(dollar_gesture) \
+ A(dollar_record) \
+ A(drop_begin) \
+ A(drop_complete) \
+ A(drop_file) \
+ A(drop_text) \
A(dst_alpha) \
A(dst_color) \
A(enter) \
@@ -47,6 +69,10 @@
A(everything) \
A(exposed) \
A(false) \
+ A(finger_down) \
+ A(finger_motion) \
+ A(finger_up) \
+ A(first) \
A(flipped) \
A(focus_gained) \
A(focus_lost) \
@@ -54,18 +80,29 @@
A(fullscreen) \
A(fullscreen_desktop) \
A(game_controller) \
+ A(get) \
A(h) \
A(hand) \
A(haptic) \
A(hidden) \
+ A(hit_test) \
A(horizontal) \
A(ibeam) \
A(input_focus) \
A(input_grabbed) \
A(invalid) \
+ A(joy_axis_motion) \
+ A(joy_ball_motion) \
+ A(joy_button_down) \
+ A(joy_button_up) \
+ A(joy_device_added) \
+ A(joy_device_removed) \
+ A(joy_hat_motion) \
A(joystick) \
A(key_down) \
A(key_up) \
+ A(keymap_changed) \
+ A(last) \
A(leave) \
A(left) \
A(left_alt) \
@@ -91,6 +128,7 @@
A(mouse_up) \
A(mouse_wheel) \
A(moved) \
+ A(multi_gesture) \
A(no) \
A(no_battery) \
A(none) \
@@ -99,8 +137,13 @@
A(on_battery) \
A(one) \
A(opengl) \
+ A(peek) \
A(present_vsync) \
+ A(pressed) \
A(quit) \
+ A(released) \
+ A(render_targets_reset) \
+ A(render_device_reset) \
A(repeat) \
A(resizable) \
A(resized) \
@@ -125,7 +168,11 @@
A(state) \
A(substract) \
A(sym) \
+ A(syswm) \
+ A(take_focus) \
A(target_texture) \
+ A(text_editing) \
+ A(text_input) \
A(touch) \
A(true) \
A(timer) \
@@ -206,7 +253,13 @@
F(set_cursor, 1) \
F(show_cursor, 1) \
/* sdl_events */ \
+ F(flush_event, 1) \
+ F(flush_events, 2) \
+ F(has_event, 1) \
+ F(has_events, 2) \
+ F(peep_events, 4) \
F(poll_event, 0) \
+ F(pump_events, 0) \
/* sdl_filesystem */ \
F(get_base_path, 0) \
F(get_pref_path, 2) \
@@ -316,7 +369,13 @@ NIF_FUNCTIONS(NIF_FUNCTION_H_DECL)
NIF_ATOM_TO_ENUM_FUNCTION_DECL(atom_to_bool, SDL_bool)
NIF_ATOM_TO_ENUM_FUNCTION_DECL(atom_to_blend_mode, SDL_BlendMode)
NIF_ENUM_TO_ATOM_FUNCTION_DECL(blend_mode_to_atom, SDL_BlendMode)
+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_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 9b212ce..bf91356 100644
--- a/c_src/sdl_events.c
+++ b/c_src/sdl_events.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2015, Loïc Hoguin <[email protected]>
+// Copyright (c) 2014-2017, Loïc Hoguin <[email protected]>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
@@ -15,175 +15,391 @@
#include "esdl2.h"
#define EVENT_TYPE_ENUM(E) \
+ E(first, SDL_FIRSTEVENT) \
+ E(quit, SDL_QUIT) \
+ E(app_terminating, SDL_APP_TERMINATING) \
+ E(app_low_memory, SDL_APP_LOWMEMORY) \
+ E(app_will_enter_background, SDL_APP_WILLENTERBACKGROUND) \
+ E(app_did_enter_background, SDL_APP_DIDENTERBACKGROUND) \
+ E(app_will_enter_foreground, SDL_APP_WILLENTERFOREGROUND) \
+ E(app_did_enter_foreground, SDL_APP_DIDENTERFOREGROUND) \
E(window, SDL_WINDOWEVENT) \
+ E(syswm, SDL_SYSWMEVENT) \
E(key_down, SDL_KEYDOWN) \
E(key_up, SDL_KEYUP) \
+ E(text_editing, SDL_TEXTEDITING) \
+ E(text_input, SDL_TEXTINPUT) \
+ E(keymap_changed, SDL_KEYMAPCHANGED) \
E(mouse_motion, SDL_MOUSEMOTION) \
E(mouse_down, SDL_MOUSEBUTTONDOWN) \
E(mouse_up, SDL_MOUSEBUTTONUP) \
E(mouse_wheel, SDL_MOUSEWHEEL) \
- E(quit, SDL_QUIT)
+ E(joy_axis_motion, SDL_JOYAXISMOTION) \
+ E(joy_ball_motion, SDL_JOYBALLMOTION) \
+ E(joy_hat_motion, SDL_JOYHATMOTION) \
+ E(joy_button_down, SDL_JOYBUTTONDOWN) \
+ E(joy_button_up, SDL_JOYBUTTONUP) \
+ E(joy_device_added, SDL_JOYDEVICEADDED) \
+ E(joy_device_removed, SDL_JOYDEVICEREMOVED) \
+ E(controller_axis_motion, SDL_CONTROLLERAXISMOTION) \
+ E(controller_button_down, SDL_CONTROLLERBUTTONDOWN) \
+ E(controller_button_up, SDL_CONTROLLERBUTTONUP) \
+ E(controller_device_added, SDL_CONTROLLERDEVICEADDED) \
+ E(controller_device_removed, SDL_CONTROLLERDEVICEREMOVED) \
+ E(controller_device_remapped, SDL_CONTROLLERDEVICEREMAPPED) \
+ E(finger_down, SDL_FINGERDOWN) \
+ E(finger_up, SDL_FINGERUP) \
+ E(finger_motion, SDL_FINGERMOTION) \
+ E(dollar_gesture, SDL_DOLLARGESTURE) \
+ E(dollar_record, SDL_DOLLARRECORD) \
+ E(multi_gesture, SDL_MULTIGESTURE) \
+ E(clipboard_update, SDL_CLIPBOARDUPDATE) \
+ E(drop_file, SDL_DROPFILE) \
+ E(drop_text, SDL_DROPTEXT) \
+ E(drop_begin, SDL_DROPBEGIN) \
+ E(drop_complete, SDL_DROPCOMPLETE) \
+ E(audio_device_added, SDL_AUDIODEVICEADDED) \
+ E(audio_device_removed, SDL_AUDIODEVICEREMOVED) \
+ E(render_targets_reset, SDL_RENDER_TARGETS_RESET) \
+ E(render_device_reset, SDL_RENDER_DEVICE_RESET) \
+ E(last, SDL_LASTEVENT)
static NIF_ENUM_TO_ATOM_FUNCTION(event_type_to_atom, Uint32, EVENT_TYPE_ENUM)
+static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_event_type, Uint32, EVENT_TYPE_ENUM)
-#define WINDOW_EVENT_ENUM(E) \
- E(shown, SDL_WINDOWEVENT_SHOWN) \
- E(hidden, SDL_WINDOWEVENT_HIDDEN) \
- E(exposed, SDL_WINDOWEVENT_EXPOSED) \
- E(moved, SDL_WINDOWEVENT_MOVED) \
- E(resized, SDL_WINDOWEVENT_RESIZED) \
- E(size_changed, SDL_WINDOWEVENT_SIZE_CHANGED) \
- E(minimized, SDL_WINDOWEVENT_MINIMIZED) \
- E(maximized, SDL_WINDOWEVENT_MAXIMIZED) \
- E(restored, SDL_WINDOWEVENT_RESTORED) \
- E(enter, SDL_WINDOWEVENT_ENTER) \
- E(leave, SDL_WINDOWEVENT_LEAVE) \
- E(focus_gained, SDL_WINDOWEVENT_FOCUS_GAINED) \
- E(focus_lost, SDL_WINDOWEVENT_FOCUS_LOST) \
- E(close, SDL_WINDOWEVENT_CLOSE)
-
-static NIF_ENUM_TO_ATOM_FUNCTION(window_event_to_atom, Uint8, WINDOW_EVENT_ENUM)
-
-#define KEYMOD_FLAGS(F) \
- F(left_shift, KMOD_LSHIFT) \
- F(right_shift, KMOD_RSHIFT) \
- F(left_ctrl, KMOD_LCTRL) \
- F(right_ctrl, KMOD_RCTRL) \
- F(left_alt, KMOD_LALT) \
- F(right_alt, KMOD_RALT) \
- F(left_gui, KMOD_LGUI) \
- F(right_gui, KMOD_RGUI) \
- F(num, KMOD_NUM) \
- F(caps, KMOD_CAPS) \
- F(mode, KMOD_MODE)
-
-static NIF_FLAGS_TO_LIST_FUNCTION(keymod_flags_to_list, Uint16, KEYMOD_FLAGS)
-
-#define BUTTON_ENUM(E) \
- E(left, SDL_BUTTON_LEFT) \
- E(middle, SDL_BUTTON_MIDDLE) \
- E(right, SDL_BUTTON_RIGHT) \
- E(x1, SDL_BUTTON_X1) \
- E(x2, SDL_BUTTON_X2)
-
-static NIF_ENUM_TO_ATOM_FUNCTION(button_to_atom, Uint8, BUTTON_ENUM)
+#define EVENT_ACTION_ENUM(E) \
+ E(add, SDL_ADDEVENT) \
+ E(peek, SDL_PEEKEVENT) \
+ E(get, SDL_GETEVENT)
-// poll_event
+static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_event_action, SDL_eventaction, EVENT_ACTION_ENUM)
-NIF_CALL_HANDLER(thread_poll_event)
+// Event conversion functions.
+
+static ERL_NIF_TERM window_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_NIF_TERM map)
{
- SDL_Event event;
- ERL_NIF_TERM map;
+ enif_make_map_put(env, map, atom_window_id,
+ enif_make_uint(env, event->window.windowID), &map);
+ enif_make_map_put(env, map, atom_event,
+ window_event_to_atom(event->window.event), &map);
+ enif_make_map_put(env, map, atom_data1,
+ enif_make_int(env, event->window.data1), &map);
+ enif_make_map_put(env, map, atom_data2,
+ enif_make_int(env, event->window.data2), &map);
- if (SDL_PollEvent(&event) == 0)
- return atom_false;
+ return map;
+}
+
+static ERL_NIF_TERM keyboard_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_NIF_TERM map)
+{
+ enif_make_map_put(env, map, atom_window_id,
+ enif_make_uint(env, event->key.windowID), &map);
+ enif_make_map_put(env, map, atom_state,
+ event->key.state == SDL_RELEASED ? atom_released : atom_pressed, &map);
+ enif_make_map_put(env, map, atom_repeat,
+ event->key.repeat == 0 ? atom_false : atom_true, &map);
+ 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_map_put(env, map, atom_mod,
+ keymod_flags_to_list(env, event->key.keysym.mod), &map);
+
+ return map;
+}
+
+static ERL_NIF_TERM mouse_motion_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_NIF_TERM map)
+{
+ enif_make_map_put(env, map, atom_window_id,
+ enif_make_uint(env, event->motion.windowID), &map);
+ enif_make_map_put(env, map, atom_which,
+ (event->motion.which == SDL_TOUCH_MOUSEID)
+ ? atom_touch
+ : enif_make_uint(env, event->motion.which),
+ &map);
+ enif_make_map_put(env, map, atom_state,
+ mouse_state_to_list(env, event->motion.state), &map);
+ enif_make_map_put(env, map, atom_x,
+ enif_make_int(env, event->motion.x), &map);
+ enif_make_map_put(env, map, atom_y,
+ enif_make_int(env, event->motion.y), &map);
+ enif_make_map_put(env, map, atom_xrel,
+ enif_make_int(env, event->motion.xrel), &map);
+ enif_make_map_put(env, map, atom_yrel,
+ enif_make_int(env, event->motion.yrel), &map);
+
+ return map;
+}
+
+static ERL_NIF_TERM mouse_button_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_NIF_TERM map)
+{
+ enif_make_map_put(env, map, atom_window_id,
+ enif_make_uint(env, event->button.windowID), &map);
+ enif_make_map_put(env, map, atom_which,
+ (event->button.which == SDL_TOUCH_MOUSEID)
+ ? atom_touch
+ : enif_make_uint(env, event->button.which),
+ &map);
+ enif_make_map_put(env, map, atom_button,
+ button_to_atom(event->button.button), &map);
+ enif_make_map_put(env, map, atom_state,
+ event->button.state == SDL_RELEASED ? atom_released : atom_pressed, &map);
+ enif_make_map_put(env, map, atom_clicks,
+ enif_make_uint(env, event->button.clicks), &map);
+ enif_make_map_put(env, map, atom_x,
+ enif_make_int(env, event->button.x), &map);
+ enif_make_map_put(env, map, atom_y,
+ enif_make_int(env, event->button.y), &map);
+
+ return map;
+}
+
+static ERL_NIF_TERM mouse_wheel_event_to_map(ErlNifEnv* env, SDL_Event* event, ERL_NIF_TERM map)
+{
+ enif_make_map_put(env, map, atom_window_id,
+ enif_make_uint(env, event->wheel.windowID), &map);
+ enif_make_map_put(env, map, atom_which,
+ (event->wheel.which == SDL_TOUCH_MOUSEID)
+ ? atom_touch
+ : enif_make_uint(env, event->wheel.which),
+ &map);
+ enif_make_map_put(env, map, atom_x,
+ enif_make_int(env, event->wheel.x), &map);
+ enif_make_map_put(env, map, atom_y,
+ enif_make_int(env, event->wheel.y), &map);
+ enif_make_map_put(env, map, atom_direction,
+ mousewheel_direction_to_atom(event->wheel.direction), &map);
+
+ return map;
+}
+
+static ERL_NIF_TERM event_to_map(ErlNifEnv* env, SDL_Event* event)
+{
+ ERL_NIF_TERM map;
map = enif_make_new_map(env);
// All events have a type and a timestamp.
+
enif_make_map_put(env, map, atom_type,
- event_type_to_atom(event.type), &map);
+ event_type_to_atom(event->type), &map);
enif_make_map_put(env, map, atom_timestamp,
- enif_make_uint(env, event.common.timestamp), &map);
-
- // Some events have additional information.
- if (event.type == SDL_WINDOWEVENT) {
- enif_make_map_put(env, map, atom_window_id,
- enif_make_uint(env, event.window.windowID), &map);
- enif_make_map_put(env, map, atom_event,
- window_event_to_atom(event.window.event), &map);
- enif_make_map_put(env, map, atom_data,
- enif_make_tuple2(env,
- enif_make_int(env, event.window.data1),
- enif_make_int(env, event.window.data2)),
- &map);
- } else if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
- enif_make_map_put(env, map, atom_window_id,
- enif_make_uint(env, event.key.windowID), &map);
- // We don't pass the state as this information is redundant with the type.
- enif_make_map_put(env, map, atom_repeat,
- event.key.repeat == 0 ? atom_false : atom_true, &map);
- 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_map_put(env, map, atom_mod,
- keymod_flags_to_list(env, event.key.keysym.mod), &map);
- } else if (event.type == SDL_MOUSEMOTION) {
- enif_make_map_put(env, map, atom_window_id,
- enif_make_uint(env, event.motion.windowID), &map);
- enif_make_map_put(env, map, atom_which,
- (event.motion.which == SDL_TOUCH_MOUSEID)
- ? atom_touch
- : enif_make_uint(env, event.motion.which),
- &map);
- // @todo We may want the state value here as it's a bitmask.
- // Question is how do we represent it to the Erlang code?
- enif_make_map_put(env, map, atom_x,
- enif_make_int(env, event.motion.x), &map);
- enif_make_map_put(env, map, atom_y,
- enif_make_int(env, event.motion.y), &map);
- enif_make_map_put(env, map, atom_xrel,
- enif_make_int(env, event.motion.xrel), &map);
- enif_make_map_put(env, map, atom_yrel,
- enif_make_int(env, event.motion.yrel), &map);
- } else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
- enif_make_map_put(env, map, atom_window_id,
- enif_make_uint(env, event.button.windowID), &map);
- enif_make_map_put(env, map, atom_which,
- (event.button.which == SDL_TOUCH_MOUSEID)
- ? atom_touch
- : enif_make_uint(env, event.button.which),
- &map);
- enif_make_map_put(env, map, atom_button,
- (event.button.button <= SDL_BUTTON_X2)
- ? button_to_atom(event.button.button)
- : enif_make_uint(env, event.button.button),
- &map);
- // We don't pass the state as this information is redundant with the type.
- enif_make_map_put(env, map, atom_clicks,
- enif_make_uint(env, event.button.clicks), &map);
- enif_make_map_put(env, map, atom_x,
- enif_make_int(env, event.button.x), &map);
- enif_make_map_put(env, map, atom_y,
- enif_make_int(env, event.button.y), &map);
- } else if (event.type == SDL_MOUSEWHEEL) {
- enif_make_map_put(env, map, atom_window_id,
- enif_make_uint(env, event.wheel.windowID), &map);
- enif_make_map_put(env, map, atom_which,
- (event.wheel.which == SDL_TOUCH_MOUSEID)
- ? atom_touch
- : enif_make_uint(env, event.wheel.which),
- &map);
- enif_make_map_put(env, map, atom_x,
- enif_make_int(env, event.wheel.x), &map);
- enif_make_map_put(env, map, atom_y,
- enif_make_int(env, event.wheel.y), &map);
- enif_make_map_put(env, map, atom_direction,
- mousewheel_direction_to_atom(event.wheel.direction), &map);
- }
+ enif_make_uint(env, event->common.timestamp), &map);
+
+ // The following event types have no additional fields:
+ //
+ // - SDL_QUIT
+ // - SDL_APP_TERMINATING
+ // - SDL_APP_LOWMEMORY
+ // - SDL_APP_WILLENTERBACKGROUND
+ // - SDL_APP_DIDENTERBACKGROUND
+ // - SDL_APP_WILLENTERFOREGROUND
+ // - SDL_APP_DIDENTERFOREGROUND
+ // - SDL_KEYMAPCHANGED
+ // - SDL_CLIPBOARDUPDATE
+ // - SDL_RENDER_TARGETS_RESET
+ // - SDL_RENDER_DEVICE_RESET
+
+ switch (event->type) {
+ case SDL_WINDOWEVENT:
+ return window_event_to_map(env, event, map);
+
+ // @todo SDL_SYSWMEVENT
+
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ return keyboard_event_to_map(env, event, map);
+
+ // @todo SDL_TEXTEDITING
+ // @todo SDL_TEXTINPUT
+
+ case SDL_MOUSEMOTION:
+ return mouse_motion_event_to_map(env, event, map);
+
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ return mouse_button_event_to_map(env, event, map);
+
+ case SDL_MOUSEWHEEL:
+ return mouse_wheel_event_to_map(env, event, map);
+
+ // @todo SDL_JOYAXISMOTION
+ // @todo SDL_JOYBALLMOTION
+ // @todo SDL_JOYHATMOTION
+ // @todo SDL_JOYBUTTONDOWN
+ // @todo SDL_JOYBUTTONUP
+ // @todo SDL_JOYDEVICEADDED
+ // @todo SDL_JOYDEVICEREMOVED
+
+ // @todo SDL_CONTROLLERAXISMOTION
+ // @todo SDL_CONTROLLERBUTTONDOWN
+ // @todo SDL_CONTROLLERBUTTONUP
+ // @todo SDL_CONTROLLERDEVICEADDED
+ // @todo SDL_CONTROLLERDEVICEREMOVED
+ // @todo SDL_CONTROLLERDEVICEREMAPPED
+
+ // @todo SDL_FINGERDOWN
+ // @todo SDL_FINGERUP
+ // @todo SDL_FINGERMOTION
+
+ // @todo SDL_DOLLARGESTURE
+ // @todo SDL_DOLLARRECORD
+ // @todo SDL_MULTIGESTURE
- // @todo SDL_TextEditingEvent
- // @todo SDL_TextInputEvent
- // @todo SDL_JoyAxisEvent
- // @todo SDL_JoyBallEvent
- // @todo SDL_JoyHatEvent
- // @todo SDL_JoyButtonEvent
- // @todo SDL_JoyDeviceEvent
- // @todo SDL_ControllerAxisEvent
- // @todo SDL_ControllerButtonEvent
- // @todo SDL_ControllerDeviceEvent
- // @todo SDL_UserEvent
- // @todo SDL_SysWMEvent
- // @todo SDL_TouchFingerEvent
- // @todo SDL_MultiGestureEvent
- // @todo SDL_DollarGestureEvent
- // @todo SDL_DropEvent
+ // @todo SDL_DROPFILE
+ // @todo SDL_DROPTEXT
+ // @todo SDL_DROPBEGIN
+ // @todo SDL_DROPCOMPLETE
+
+ // @todo SDL_AUDIODEVICEADDED
+ // @todo SDL_AUDIODEVICEREMOVED
+ }
return map;
}
+// flush_event
+
+NIF_CAST_HANDLER(thread_flush_event)
+{
+ SDL_FlushEvent((long)args[0]);
+}
+
+NIF_FUNCTION(flush_event)
+{
+ Uint32 type;
+
+ BADARG_IF(!atom_to_event_type(env, argv[0], &type));
+
+ return nif_thread_cast(env, thread_flush_event, 1, type);
+}
+
+// flush_events
+
+NIF_CAST_HANDLER(thread_flush_events)
+{
+ SDL_FlushEvents((long)args[0], (long)args[1]);
+}
+
+NIF_FUNCTION(flush_events)
+{
+ Uint32 minType, maxType;
+
+ BADARG_IF(!atom_to_event_type(env, argv[0], &minType));
+ BADARG_IF(!atom_to_event_type(env, argv[1], &maxType));
+
+ return nif_thread_cast(env, thread_flush_events, 2, minType, maxType);
+}
+
+// has_event
+
+NIF_CALL_HANDLER(thread_has_event)
+{
+ if (SDL_HasEvent((long)args[0]))
+ return atom_true;
+
+ return atom_false;
+}
+
+NIF_FUNCTION(has_event)
+{
+ Uint32 type;
+
+ BADARG_IF(!atom_to_event_type(env, argv[0], &type));
+
+ return nif_thread_call(env, thread_has_event, 1, type);
+}
+
+// has_events
+
+NIF_CALL_HANDLER(thread_has_events)
+{
+ if (SDL_HasEvents((long)args[0], (long)args[1]))
+ return atom_true;
+
+ return atom_false;
+}
+
+NIF_FUNCTION(has_events)
+{
+ Uint32 minType, maxType;
+
+ BADARG_IF(!atom_to_event_type(env, argv[0], &minType));
+ BADARG_IF(!atom_to_event_type(env, argv[1], &maxType));
+
+ return nif_thread_call(env, thread_has_events, 2, minType, maxType);
+}
+
+// peep_events
+//
+// @todo It is not currently possible to add events at the back of the queue.
+
+NIF_CALL_HANDLER(thread_peep_events)
+{
+ SDL_Event* events;
+ int i, numEvents;
+ ERL_NIF_TERM list;
+
+ events = malloc(sizeof(SDL_Event) * (long)args[1]);
+
+ numEvents = SDL_PeepEvents(events, (long)args[1],
+ (long)args[0], (long)args[2], (long)args[3]);
+
+ if (numEvents < 0)
+ return sdl_error_tuple(env);
+
+ list = enif_make_list(env, 0);
+
+ for (i = 0; i < numEvents; i++)
+ list = enif_make_list_cell(env, event_to_map(env, &events[i]), list);
+
+ free(events);
+
+ return enif_make_tuple2(env, atom_ok, list);
+}
+
+NIF_FUNCTION(peep_events)
+{
+ SDL_eventaction action;
+ int numEvents;
+ Uint32 minType, maxType;
+
+ BADARG_IF(enif_is_identical(atom_add, argv[0]));
+
+ BADARG_IF(!atom_to_event_action(env, argv[0], &action));
+ BADARG_IF(!enif_get_int(env, argv[1], &numEvents));
+ BADARG_IF(!atom_to_event_type(env, argv[2], &minType));
+ BADARG_IF(!atom_to_event_type(env, argv[3], &maxType));
+
+ return nif_thread_call(env, thread_peep_events, 4,
+ action, numEvents, minType, maxType);
+}
+
+// poll_event
+
+NIF_CALL_HANDLER(thread_poll_event)
+{
+ SDL_Event event;
+
+ if (SDL_PollEvent(&event) == 0)
+ return atom_false;
+
+ return event_to_map(env, &event);
+}
+
NIF_FUNCTION(poll_event)
{
return nif_thread_call(env, thread_poll_event, 0);
}
+
+// pump_events
+
+NIF_CAST_HANDLER(thread_pump_events)
+{
+ SDL_PumpEvents();
+}
+
+NIF_FUNCTION(pump_events)
+{
+ return nif_thread_cast(env, thread_pump_events, 0);
+}
diff --git a/c_src/sdl_keycode.c b/c_src/sdl_keycode.c
new file mode 100644
index 0000000..539accd
--- /dev/null
+++ b/c_src/sdl_keycode.c
@@ -0,0 +1,30 @@
+// Copyright (c) 2014-2017, Loïc Hoguin <[email protected]>
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#include "esdl2.h"
+
+#define KEYMOD_FLAGS(F) \
+ F(left_shift, KMOD_LSHIFT) \
+ F(right_shift, KMOD_RSHIFT) \
+ F(left_ctrl, KMOD_LCTRL) \
+ F(right_ctrl, KMOD_RCTRL) \
+ F(left_alt, KMOD_LALT) \
+ F(right_alt, KMOD_RALT) \
+ F(left_gui, KMOD_LGUI) \
+ F(right_gui, KMOD_RGUI) \
+ F(num, KMOD_NUM) \
+ F(caps, KMOD_CAPS) \
+ F(mode, KMOD_MODE)
+
+NIF_FLAGS_TO_LIST_FUNCTION(keymod_flags_to_list, Uint16, KEYMOD_FLAGS)
diff --git a/c_src/sdl_mouse.c b/c_src/sdl_mouse.c
index eb2af39..018b44c 100644
--- a/c_src/sdl_mouse.c
+++ b/c_src/sdl_mouse.c
@@ -20,7 +20,16 @@
NIF_ENUM_TO_ATOM_FUNCTION(mousewheel_direction_to_atom, Uint32, MOUSEWHEEL_DIRECTION_ENUM)
-static ERL_NIF_TERM get_mouse_state_common(ErlNifEnv* env, int x, int y, Uint32 state)
+#define BUTTON_ENUM(E) \
+ E(left, SDL_BUTTON_LEFT) \
+ E(middle, SDL_BUTTON_MIDDLE) \
+ E(right, SDL_BUTTON_RIGHT) \
+ E(x1, SDL_BUTTON_X1) \
+ E(x2, SDL_BUTTON_X2)
+
+NIF_ENUM_TO_ATOM_FUNCTION(button_to_atom, Uint8, BUTTON_ENUM)
+
+ERL_NIF_TERM mouse_state_to_list(ErlNifEnv* env, Uint32 state)
{
ERL_NIF_TERM list;
@@ -37,10 +46,15 @@ static ERL_NIF_TERM get_mouse_state_common(ErlNifEnv* env, int x, int y, Uint32
if (state & SDL_BUTTON_X2MASK)
list = enif_make_list_cell(env, atom_x2, list);
+ return list;
+}
+
+static ERL_NIF_TERM get_mouse_state_common(ErlNifEnv* env, int x, int y, Uint32 state)
+{
return enif_make_tuple3(env,
enif_make_int(env, x),
enif_make_int(env, y),
- list
+ mouse_state_to_list(env, state)
);
}
diff --git a/c_src/sdl_window.c b/c_src/sdl_window.c
index 4ac3604..36ddcc2 100644
--- a/c_src/sdl_window.c
+++ b/c_src/sdl_window.c
@@ -49,6 +49,26 @@ static NIF_FLAGS_TO_LIST_FUNCTION(window_flags_to_list, Uint32, WINDOW_FLAGS)
static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_window_pos, int, WINDOW_POS_ENUM)
+#define WINDOW_EVENT_ENUM(E) \
+ E(shown, SDL_WINDOWEVENT_SHOWN) \
+ E(hidden, SDL_WINDOWEVENT_HIDDEN) \
+ E(exposed, SDL_WINDOWEVENT_EXPOSED) \
+ E(moved, SDL_WINDOWEVENT_MOVED) \
+ E(resized, SDL_WINDOWEVENT_RESIZED) \
+ E(size_changed, SDL_WINDOWEVENT_SIZE_CHANGED) \
+ E(minimized, SDL_WINDOWEVENT_MINIMIZED) \
+ E(maximized, SDL_WINDOWEVENT_MAXIMIZED) \
+ E(restored, SDL_WINDOWEVENT_RESTORED) \
+ E(enter, SDL_WINDOWEVENT_ENTER) \
+ E(leave, SDL_WINDOWEVENT_LEAVE) \
+ E(focus_gained, SDL_WINDOWEVENT_FOCUS_GAINED) \
+ E(focus_lost, SDL_WINDOWEVENT_FOCUS_LOST) \
+ E(close, SDL_WINDOWEVENT_CLOSE) \
+ E(take_focus, SDL_WINDOWEVENT_TAKE_FOCUS) \
+ E(hit_test, SDL_WINDOWEVENT_HIT_TEST)
+
+NIF_ENUM_TO_ATOM_FUNCTION(window_event_to_atom, Uint8, WINDOW_EVENT_ENUM)
+
#define WINDOW_FULLSCREEN_ENUM(E) \
E(fullscreen, SDL_WINDOW_FULLSCREEN) \
E(fullscreen_desktop, SDL_WINDOW_FULLSCREEN_DESKTOP) \
diff --git a/ebin/esdl2.app b/ebin/esdl2.app
index ccb9664..3b48762 100644
--- a/ebin/esdl2.app
+++ b/ebin/esdl2.app
@@ -1,7 +1,7 @@
{application, 'esdl2', [
{description, "SDL2 Erlang NIF."},
{vsn, "0.1.0"},
- {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_blend_mode','sdl_clipboard','sdl_cpu_info','sdl_cursor','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_mouse','sdl_power','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_window']},
+ {modules, ['esdl2','esdl2_app','esdl2_callbacks','esdl2_sup','sdl','sdl_blend_mode','sdl_clipboard','sdl_cpu_info','sdl_cursor','sdl_events','sdl_filesystem','sdl_gl','sdl_hints','sdl_keyboard','sdl_keycode','sdl_mouse','sdl_power','sdl_renderer','sdl_surface','sdl_texture','sdl_version','sdl_window']},
{registered, [esdl2_sup]},
{applications, [kernel,stdlib]},
{mod, {esdl2_app, []}},
diff --git a/src/esdl2.erl b/src/esdl2.erl
index 1020849..5fa9a16 100644
--- a/src/esdl2.erl
+++ b/src/esdl2.erl
@@ -60,7 +60,13 @@
-export([show_cursor/1]).
%% sdl_events
+-export([flush_event/1]).
+-export([flush_events/2]).
+-export([has_event/1]).
+-export([has_events/2]).
+-export([peep_events/4]).
-export([poll_event/0]).
+-export([pump_events/0]).
%% sdl_filesystem
-export([get_base_path/0]).
@@ -293,9 +299,27 @@ show_cursor(_) ->
%% sdl_events
+flush_event(_) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+flush_events(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+has_event(_) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+has_events(_, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
+peep_events(_, _, _, _) ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
poll_event() ->
erlang:nif_error({not_loaded, ?MODULE}).
+pump_events() ->
+ erlang:nif_error({not_loaded, ?MODULE}).
+
%% sdl_filesystem
get_base_path() ->
diff --git a/src/sdl_events.erl b/src/sdl_events.erl
index 366edeb..034ca3d 100644
--- a/src/sdl_events.erl
+++ b/src/sdl_events.erl
@@ -14,40 +14,100 @@
-module(sdl_events).
+-export([flush/1]).
+-export([flush/2]).
+-export([get/3]).
+-export([has/1]).
+-export([has/2]).
+-export([peek/3]).
-export([poll/0]).
+-export([pump/0]).
+
+-type event_type() :: first
+ | quit
+ | app_terminating | app_low_memory | app_will_enter_background
+ | app_did_enter_background | app_will_enter_foreground | app_did_enter_foreground
+ | window | syswm
+ | key_down | key_up | text_editing | text_input | keymap_changed
+ | mouse_motion | mouse_down | mouse_up | mouse_wheel
+ | joy_axis_motion | joy_ball_motion | joy_hat_motion
+ | joy_button_down | joy_button_up | joy_device_added | joy_device_removed
+ | controller_axis_motion | controller_button_down | controller_button_up
+ | controller_device_added | controller_device_removed | controller_device_remapped
+ | finger_down | finger_up | finger_motion
+ | dollar_gesture | dollar_record | multi_gesture
+ | clipboard_update
+ | drop_file | drop_text | drop_begin | drop_complete
+ | audio_device_added | audio_device_removed
+ | render_targets_reset | render_device_reset
+ | last.
--type window_event_type() :: shown | hidden | exposed | moved | resized
- | size_changed | minimized | maximized | restored | enter | leave
- | focus_gained | focus_lost | close.
-type window_event() :: #{type=>window, timestamp=>non_neg_integer(),
- window_id=>non_neg_integer(), event=>window_event_type(),
- data=>{integer(), integer()}}.
+ window_id=>non_neg_integer(), event=>sdl_window:window_event_type(),
+ data1=>integer(), data2=>integer()}.
--type keymod() :: left_shift | right_shift | left_ctrl | right_ctrl
- | left_alt | right_alt | left_gui | right_gui | num | caps | mode.
--type key_event() :: #{type=>key_down | key_up, timestamp=>non_neg_integer(),
- window_id=>non_neg_integer(), repeat=>boolean(), scancode=>non_neg_integer(),
- sym=>non_neg_integer(), mod=>[keymod()]}.
-
--type mouse_button() :: left | middle | right | x1 | x2 | non_neg_integer().
--type mouse_button_event() :: #{type=>mouse_down | mouse_up, timestamp=>non_neg_integer(),
- window_id=>non_neg_integer(), which=>touch | non_neg_integer(),
- button=>mouse_button(), clicks=>non_neg_integer(), x=>integer(), y=>integer()}.
+-type keyboard_event() :: #{type=>key_down | key_up, timestamp=>non_neg_integer(),
+ window_id=>non_neg_integer(), state=>released | pressed, repeat=>boolean(),
+ scancode=>non_neg_integer(), sym=>non_neg_integer(), mod=>[sdl_keycode:keymod()]}.
-type mouse_motion_event() :: #{type=>mouse_motion, timestamp=>non_neg_integer(),
window_id=>non_neg_integer(), which=>touch | non_neg_integer(),
x=>integer(), y=>integer(), xrel=>integer(), yrel=>integer()}.
+-type mouse_button_event() :: #{type=>mouse_down | mouse_up, timestamp=>non_neg_integer(),
+ window_id=>non_neg_integer(), which=>touch | non_neg_integer(),
+ button=>sdl_mouse:button(), state=>released | pressed,
+ clicks=>non_neg_integer(), x=>integer(), y=>integer()}.
+
-type mouse_wheel_event() :: #{type=>mouse_wheel, timestamp=>non_neg_integer(),
window_id=>non_neg_integer(), which=>touch | non_neg_integer(),
- x=>integer(), y=>integer()}.
+ x=>integer(), y=>integer(), direction=>sdl_mouse:wheel_direction()}.
+
+-type generic_event() :: #{
+ type=> quit | app_terminating | app_low_memory | app_will_enter_background
+ | app_did_enter_background | app_will_enter_foreground | app_did_enter_foreground
+ | keymap_changed | clipboard_update | render_targets_reset | render_device_reset,
+ timestamp=>non_neg_integer()}.
+
+-type event() :: window_event() | keyboard_event()
+ | mouse_motion_event() | mouse_button_event() | mouse_wheel_event()
+ | generic_event().
--type quit_event() :: #{type=>quit, timestamp=>non_neg_integer()}.
+-spec flush(event_type()) -> ok.
+flush(Type) ->
+ esdl2:flush_event(Type).
--type event() :: window_event() | key_event() | mouse_button_event()
- | mouse_motion_event() | mouse_wheel_event() | quit_event().
+-spec flush(event_type(), event_type()) -> ok.
+flush(MinType, MaxType) ->
+ esdl2:flush_events(MinType, MaxType).
+
+-spec get(non_neg_integer(), event_type(), event_type())
+ -> {ok, [event()]} | sdl:error().
+get(NumEvents, MinType, MaxType) ->
+ esdl2:peep_events(get, NumEvents, MinType, MaxType),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec has(event_type()) -> boolean().
+has(Type) ->
+ esdl2:has_event(Type),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec has(event_type(), event_type()) -> boolean().
+has(MinType, MaxType) ->
+ esdl2:has_events(MinType, MaxType),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec peek(non_neg_integer(), event_type(), event_type())
+ -> {ok, [event()]} | sdl:error().
+peek(NumEvents, MinType, MaxType) ->
+ esdl2:peep_events(peek, NumEvents, MinType, MaxType),
+ receive {'_nif_thread_ret_', Ret} -> Ret end.
-spec poll() -> event() | false.
poll() ->
esdl2:poll_event(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
+
+-spec pump() -> ok.
+pump() ->
+ esdl2:pump_events().
diff --git a/src/sdl_keycode.erl b/src/sdl_keycode.erl
new file mode 100644
index 0000000..6ab1cf4
--- /dev/null
+++ b/src/sdl_keycode.erl
@@ -0,0 +1,19 @@
+%% Copyright (c) 2014-2017, Loïc Hoguin <[email protected]>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(sdl_keycode).
+
+-type keymod() :: left_shift | right_shift | left_ctrl | right_ctrl
+ | left_alt | right_alt | left_gui | right_gui | num | caps | mode.
+-export_type([keymod/0]).
diff --git a/src/sdl_mouse.erl b/src/sdl_mouse.erl
index d6c3815..6d34b8d 100644
--- a/src/sdl_mouse.erl
+++ b/src/sdl_mouse.erl
@@ -24,6 +24,12 @@
-export([warp/2]).
-export([warp/3]).
+-type wheel_direction() :: normal | flipped.
+-export_type([wheel_direction/0]).
+
+-type button() :: left | middle | right | x1 | x2.
+-export_type([button/0]).
+
-spec capture(boolean()) -> ok | sdl:error().
capture(Bool) ->
esdl2:capture_mouse(Bool),
@@ -34,8 +40,7 @@ get_focused_window() ->
esdl2:get_mouse_focus(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
--spec get_global_state()
- -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+-spec get_global_state() -> {integer(), integer(), [button()]}.
get_global_state() ->
esdl2:get_global_mouse_state(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
@@ -45,14 +50,12 @@ get_relative_mode() ->
esdl2:get_relative_mouse_mode(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
--spec get_relative_state()
- -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+-spec get_relative_state() -> {integer(), integer(), [button()]}.
get_relative_state() ->
esdl2:get_relative_mouse_state(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
--spec get_state()
- -> {integer(), integer(), [left | middle | right | x1 | x2]}.
+-spec get_state() -> {integer(), integer(), [button()]}.
get_state() ->
esdl2:get_mouse_state(),
receive {'_nif_thread_ret_', Ret} -> Ret end.
diff --git a/src/sdl_window.erl b/src/sdl_window.erl
index 5d31392..ea757bf 100644
--- a/src/sdl_window.erl
+++ b/src/sdl_window.erl
@@ -51,6 +51,11 @@
| hidden | borderless | resizable | minimized | maximized
| input_grabbed | input_focus | mouse_focus | foreign | allow_high_dpi.
+-type window_event_type() :: shown | hidden | exposed | moved | resized
+ | size_changed | minimized | maximized | restored | enter | leave
+ | focus_gained | focus_lost | close | take_focus | hit_test.
+-export_type([window_event_type/0]).
+
-spec create(string(), window_pos(), window_pos(), integer(), integer(), [window_flag()])
-> {ok, window()} | sdl:error().
create(Title, X, Y, W, H, Flags) ->