99 lines
2.7 KiB
C++
99 lines
2.7 KiB
C++
#include <psemek/sdl2/cursor.hpp>
|
|
#include <psemek/sdl2/init.hpp>
|
|
#include <psemek/log/log.hpp>
|
|
#include <psemek/util/enum.hpp>
|
|
|
|
#include <SDL2/SDL_mouse.h>
|
|
|
|
#include <memory>
|
|
|
|
namespace psemek::sdl2
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
struct sdl_surface_deleter
|
|
{
|
|
void operator() (SDL_Surface * s) const
|
|
{
|
|
SDL_FreeSurface(s);
|
|
}
|
|
};
|
|
|
|
struct sdl_cursor_deleter
|
|
{
|
|
void operator() (SDL_Cursor * c) const
|
|
{
|
|
SDL_FreeCursor(c);
|
|
}
|
|
};
|
|
|
|
using sdl_surface_ptr = std::unique_ptr<SDL_Surface, sdl_surface_deleter>;
|
|
using sdl_cursor_ptr = std::unique_ptr<SDL_Cursor, sdl_cursor_deleter>;
|
|
|
|
SDL_SystemCursor to_sdl(default_cursor_type type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case default_cursor_type::arrow: return SDL_SYSTEM_CURSOR_ARROW;
|
|
case default_cursor_type::beam: return SDL_SYSTEM_CURSOR_IBEAM;
|
|
case default_cursor_type::wait: return SDL_SYSTEM_CURSOR_WAIT;
|
|
case default_cursor_type::crosshair: return SDL_SYSTEM_CURSOR_CROSSHAIR;
|
|
case default_cursor_type::waitarrow: return SDL_SYSTEM_CURSOR_WAITARROW;
|
|
case default_cursor_type::sizenwse: return SDL_SYSTEM_CURSOR_SIZENWSE;
|
|
case default_cursor_type::sizenesw: return SDL_SYSTEM_CURSOR_SIZENESW;
|
|
case default_cursor_type::sizewe: return SDL_SYSTEM_CURSOR_SIZEWE;
|
|
case default_cursor_type::sizens: return SDL_SYSTEM_CURSOR_SIZENS;
|
|
case default_cursor_type::sizeall: return SDL_SYSTEM_CURSOR_SIZEALL;
|
|
case default_cursor_type::no: return SDL_SYSTEM_CURSOR_NO;
|
|
case default_cursor_type::hand: return SDL_SYSTEM_CURSOR_HAND;
|
|
}
|
|
|
|
return SDL_SYSTEM_CURSOR_ARROW;
|
|
}
|
|
|
|
}
|
|
|
|
struct cursor
|
|
{
|
|
sdl_cursor_ptr cursor_ptr;
|
|
};
|
|
|
|
std::shared_ptr<cursor> get_default_cursor(default_cursor_type type)
|
|
{
|
|
sdl_cursor_ptr cursor_ptr{SDL_CreateSystemCursor(to_sdl(type))};
|
|
if (!cursor_ptr)
|
|
{
|
|
log::warning() << "Failed to create system cursor: " << SDL_GetError();
|
|
return nullptr;
|
|
}
|
|
return std::make_shared<cursor>(std::move(cursor_ptr));
|
|
}
|
|
|
|
std::shared_ptr<cursor> make_cursor(gfx::pixmap_rgba const & image, geom::point<int, 2> const & pivot)
|
|
{
|
|
sdl_surface_ptr surface_ptr{SDL_CreateRGBSurfaceFrom((void *)image.data(), image.width(), image.height(), 32, 4 * image.width(), 0x000000ffu, 0x0000ff00u, 0x00ff0000u, 0xff000000u)};
|
|
if (!surface_ptr)
|
|
{
|
|
log::warning() << "Failed to create cursor SDL surface: " << SDL_GetError();
|
|
return nullptr;
|
|
}
|
|
|
|
sdl_cursor_ptr cursor_ptr{SDL_CreateColorCursor(surface_ptr.get(), pivot[0], pivot[1])};
|
|
if (!cursor_ptr)
|
|
{
|
|
log::warning() << "Failed to create cursor from SDL surface: " << SDL_GetError();
|
|
return nullptr;
|
|
}
|
|
|
|
return std::make_shared<cursor>(std::move(cursor_ptr));
|
|
}
|
|
|
|
void set_cursor(cursor const & cursor)
|
|
{
|
|
SDL_SetCursor(cursor.cursor_ptr.get());
|
|
}
|
|
|
|
|
|
}
|