aboutsummaryrefslogblamecommitdiffstats
path: root/c_src/sdl_cursor.c
blob: 432e1bac32a4da88cfc1036e0349e33c99eb3396 (plain) (tree)
1
                                                             




































































































































































































































































                                                                                
// Copyright (c) 2017-2018, 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);
}