diff options
Diffstat (limited to 'c_src/sdl_cursor.c')
-rw-r--r-- | c_src/sdl_cursor.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/c_src/sdl_cursor.c b/c_src/sdl_cursor.c new file mode 100644 index 0000000..59ad923 --- /dev/null +++ b/c_src/sdl_cursor.c @@ -0,0 +1,262 @@ +// Copyright (c) 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 SYSTEM_CURSOR_ENUM(E) \ + E(arrow, SDL_SYSTEM_CURSOR_ARROW) \ + E(ibeam, SDL_SYSTEM_CURSOR_IBEAM) \ + E(wait, SDL_SYSTEM_CURSOR_WAIT) \ + E(crosshair, SDL_SYSTEM_CURSOR_CROSSHAIR) \ + E(wait_arrow, SDL_SYSTEM_CURSOR_WAITARROW) \ + E(size_nwse, SDL_SYSTEM_CURSOR_SIZENWSE) \ + E(size_nesw, SDL_SYSTEM_CURSOR_SIZENESW) \ + E(size_we, SDL_SYSTEM_CURSOR_SIZEWE) \ + E(size_ns, SDL_SYSTEM_CURSOR_SIZENS) \ + E(size_all, SDL_SYSTEM_CURSOR_SIZEALL) \ + E(no, SDL_SYSTEM_CURSOR_NO) \ + E(hand, SDL_SYSTEM_CURSOR_HAND) + +static NIF_ATOM_TO_ENUM_FUNCTION(atom_to_system_cursor, int, SYSTEM_CURSOR_ENUM) + +void dtor_Cursor(ErlNifEnv* env, void* obj) +{ + SDL_Cursor* cursor = NIF_RES_GET(Cursor, obj); + + SDL_FreeCursor(cursor); + esdl2_cursors_remove(cursor); +} + +// create_cursor + +NIF_CALL_HANDLER(thread_create_cursor) +{ + SDL_Cursor* cursor; + obj_Cursor* res; + ERL_NIF_TERM term; + ErlNifBinary data, mask; + + enif_inspect_binary(args[0], (long)args[1], &data); + enif_inspect_binary(args[0], (long)args[2], &mask); + + cursor = SDL_CreateCursor(data.data, mask.data, + (long)args[3], (long)args[4], (long)args[5], (long)args[6]); + + enif_free_env(args[0]); + + if (!cursor) + return sdl_error_tuple(env); + + NIF_RES_TO_PTR_AND_TERM(Cursor, cursor, res, term); + + esdl2_cursors_insert(cursor, res); + + return enif_make_tuple2(env, + atom_ok, + term + ); +} + +NIF_FUNCTION(create_cursor) +{ + ErlNifEnv* bin_env; + ERL_NIF_TERM data, mask; + int w, h, hot_x, hot_y; + + BADARG_IF(!enif_is_binary(env, argv[0])); + BADARG_IF(!enif_is_binary(env, argv[1])); + BADARG_IF(!enif_get_int(env, argv[2], &w)); + BADARG_IF(!enif_get_int(env, argv[3], &h)); + BADARG_IF(!enif_get_int(env, argv[4], &hot_x)); + BADARG_IF(!enif_get_int(env, argv[5], &hot_y)); + + // We copy the binaries to avoid copying their content. + bin_env = enif_alloc_env(); + data = enif_make_copy(bin_env, argv[0]); + mask = enif_make_copy(bin_env, argv[1]); + + return nif_thread_call(env, thread_create_cursor, 7, + bin_env, data, mask, w, h, hot_x, hot_y); +} + +// create_color_cursor + +NIF_CALL_HANDLER(thread_create_color_cursor) +{ + SDL_Cursor* cursor; + obj_Cursor* res; + ERL_NIF_TERM term; + + cursor = SDL_CreateColorCursor(args[0], (long)args[1], (long)args[2]); + + if (!cursor) + return sdl_error_tuple(env); + + NIF_RES_TO_PTR_AND_TERM(Cursor, cursor, res, term); + + esdl2_cursors_insert(cursor, res); + + return enif_make_tuple2(env, + atom_ok, + term + ); +} + +NIF_FUNCTION(create_color_cursor) +{ + void* surface_res; + int hot_x, hot_y; + + BADARG_IF(!enif_get_resource(env, argv[0], res_Surface, &surface_res)); + BADARG_IF(!enif_get_int(env, argv[1], &hot_x)); + BADARG_IF(!enif_get_int(env, argv[2], &hot_y)); + + return nif_thread_call(env, thread_create_color_cursor, 3, + NIF_RES_GET(Surface, surface_res), hot_x, hot_y); +} + +// create_system_cursor + +NIF_CALL_HANDLER(thread_create_system_cursor) +{ + SDL_Cursor* cursor; + obj_Cursor* res; + ERL_NIF_TERM term; + + cursor = SDL_CreateSystemCursor((long)args[0]); + + if (!cursor) + return sdl_error_tuple(env); + + NIF_RES_TO_PTR_AND_TERM(Cursor, cursor, res, term); + + esdl2_cursors_insert(cursor, res); + + return enif_make_tuple2(env, + atom_ok, + term + ); +} + +NIF_FUNCTION(create_system_cursor) +{ + int id; + + BADARG_IF(!atom_to_system_cursor(env, argv[0], &id)); + + return nif_thread_call(env, thread_create_system_cursor, 1, id); +} + +// get_cursor + +NIF_CALL_HANDLER(thread_get_cursor) +{ + SDL_Cursor* cursor; + obj_Cursor* res; + ERL_NIF_TERM term; + + cursor = SDL_GetCursor(); + + // There is no mouse. + if (!cursor) + return atom_undefined; + + term = esdl2_cursors_find(env, cursor); + + if (!enif_is_identical(term, atom_undefined)) + return term; + + // We don't know this cursor. It's probably a system cursor. + // We should insert it in the list to have the same reference + // for it while it's active. + + NIF_RES_TO_PTR_AND_TERM(Cursor, cursor, res, term); + + esdl2_cursors_insert(cursor, res); + + return term; +} + +NIF_FUNCTION(get_cursor) +{ + return nif_thread_call(env, thread_get_cursor, 0); +} + +// get_default_cursor + +NIF_CALL_HANDLER(thread_get_default_cursor) +{ + SDL_Cursor* cursor; + obj_Cursor* res; + ERL_NIF_TERM term; + + cursor = SDL_GetDefaultCursor(); + + // There is no mouse. + if (!cursor) + return atom_undefined; + + term = esdl2_cursors_find(env, cursor); + + if (!enif_is_identical(term, atom_undefined)) + return term; + + // We don't know this cursor. It's probably a system cursor. + // We should insert it in the list to have the same reference + // for it while it's active. + + NIF_RES_TO_PTR_AND_TERM(Cursor, cursor, res, term); + + esdl2_cursors_insert(cursor, res); + + return term; +} + +NIF_FUNCTION(get_default_cursor) +{ + return nif_thread_call(env, thread_get_default_cursor, 0); +} + +// set_cursor + +NIF_CAST_HANDLER(thread_set_cursor) +{ + SDL_SetCursor(args[0]); +} + +NIF_FUNCTION(set_cursor) +{ + void* cursor_res; + + BADARG_IF(!enif_get_resource(env, argv[0], res_Cursor, &cursor_res)); + + return nif_thread_cast(env, thread_set_cursor, 1, + NIF_RES_GET(Cursor, cursor_res)); +} + +// show_cursor + +NIF_CALL_HANDLER(thread_show_cursor) +{ + return enif_make_int(env, SDL_ShowCursor((long)args[0])); +} + +NIF_FUNCTION(show_cursor) +{ + int toggle; + + BADARG_IF(!enif_get_int(env, argv[0], &toggle)); + + return nif_thread_call(env, thread_show_cursor, 1, toggle); +} |