#include #include #include #include #include namespace psemek::sdl2 { namespace { struct cursor_deleter { void operator() (SDL_Cursor * c) const { SDL_FreeCursor(c); } }; using cursor_ptr = std::unique_ptr; } struct cursor { std::unique_ptr cursor; }; namespace { SDL_Cursor * create_system_cursor(SDL_SystemCursor id) { auto cursor = SDL_CreateSystemCursor(id); if (!cursor) log::warning() << "Failed to create system cursor: " << SDL_GetError(); return cursor; } struct system_cursor_provider_impl : cursor_provider { system_cursor_provider_impl() { arrow_.cursor.reset(create_system_cursor(SDL_SYSTEM_CURSOR_ARROW)); beam_.cursor.reset(create_system_cursor(SDL_SYSTEM_CURSOR_IBEAM)); hand_.cursor.reset(create_system_cursor(SDL_SYSTEM_CURSOR_HAND)); } cursor const & get(cursor_type type) const override { switch (type) { case cursor_type::arrow: return arrow_; case cursor_type::beam: return beam_; case cursor_type::hand: return hand_; } throw util::unknown_enum_value_exception(type); } private: cursor arrow_; cursor beam_; cursor hand_; }; } std::unique_ptr system_cursor_provider() { return std::make_unique(); } static std::unique_ptr current_provider; std::unique_ptr set_cursor_provider(std::unique_ptr new_provider) { std::swap(current_provider, new_provider); return new_provider; } cursor_provider const * get_cursor_provider() { static std::unique_ptr fallback; if (current_provider) return current_provider.get(); if (!fallback) fallback = system_cursor_provider(); return fallback.get(); } void set_cursor(cursor_type type) { SDL_SetCursor(get_cursor_provider()->get(type).cursor.get()); } }