aboutsummaryrefslogtreecommitdiffstats
path: root/c_src/sdl_cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/sdl_cursor.c')
-rw-r--r--c_src/sdl_cursor.c262
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);
+}