#include #include #include #include #include #include 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; using sdl_cursor_ptr = std::unique_ptr; 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 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(std::move(cursor_ptr)); } std::shared_ptr make_cursor(gfx::pixmap_rgba const & image, geom::point 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(std::move(cursor_ptr)); } void set_cursor(cursor const & cursor) { SDL_SetCursor(cursor.cursor_ptr.get()); } }