Add SDL2 cursor capabilities

This commit is contained in:
Nikita Lisitsa 2022-04-06 17:24:09 +03:00
parent f7568535b6
commit 80315e839a
2 changed files with 117 additions and 0 deletions

View file

@ -0,0 +1,26 @@
#pragma once
#include <memory>
namespace psemek::sdl2
{
struct cursor;
struct cursor_provider
{
virtual cursor const & arrow() const = 0;
virtual cursor const & beam() const = 0;
virtual cursor const & hand() const = 0;
virtual ~cursor_provider() {}
};
std::unique_ptr<cursor_provider> system_cursor_provider();
std::unique_ptr<cursor_provider> set_cursor_provider(std::unique_ptr<cursor_provider> new_provider);
cursor_provider const * get_cursor_provider();
void set_cursor(cursor const & c);
}

View file

@ -0,0 +1,91 @@
#include <psemek/sdl2/cursor.hpp>
#include <psemek/log/log.hpp>
#include <SDL2/SDL_mouse.h>
#include <memory>
namespace psemek::sdl2
{
namespace
{
struct cursor_deleter
{
void operator() (SDL_Cursor * c) const
{
SDL_FreeCursor(c);
}
};
using cursor_ptr = std::unique_ptr<SDL_Cursor, cursor_deleter>;
}
struct cursor
{
cursor_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 & arrow() const override { return arrow_; }
cursor const & beam() const override { return beam_; }
cursor const & hand() const override { return hand_; }
private:
cursor arrow_;
cursor beam_;
cursor hand_;
};
}
std::unique_ptr<cursor_provider> system_cursor_provider()
{
return std::make_unique<system_cursor_provider_impl>();
}
static std::unique_ptr<cursor_provider> current_provider;
std::unique_ptr<cursor_provider> set_cursor_provider(std::unique_ptr<cursor_provider> new_provider)
{
std::swap(current_provider, new_provider);
return new_provider;
}
cursor_provider const * get_cursor_provider()
{
static system_cursor_provider_impl const fallback;
if (!current_provider)
return &fallback;
return current_provider.get();
}
void set_cursor(cursor const & c)
{
SDL_SetCursor(c.cursor.get());
}
}