|
|
|
|
/**
|
|
|
|
|
* @file hwcursor.hpp
|
|
|
|
|
*
|
|
|
|
|
* Hardware cursor (SDL2 only).
|
|
|
|
|
*/
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
#include <SDL_version.h>
|
|
|
|
|
|
|
|
|
|
#include "options.h"
|
|
|
|
|
#include "utils/log.hpp"
|
|
|
|
|
|
|
|
|
|
// Set this to 1 to log the hardware cursor state changes.
|
|
|
|
|
#define LOG_HWCURSOR 0
|
|
|
|
|
|
|
|
|
|
namespace devilution {
|
|
|
|
|
|
|
|
|
|
// Whether the hardware cursor is enabled in settings.
|
|
|
|
|
inline bool IsHardwareCursorEnabled()
|
|
|
|
|
{
|
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
|
return *sgOptions.Graphics.hardwareCursor && HardwareCursorSupported();
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum class CursorType : uint8_t {
|
|
|
|
|
Unknown,
|
|
|
|
|
UserInterface,
|
|
|
|
|
Game,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CursorInfo {
|
|
|
|
|
public:
|
|
|
|
|
CursorInfo() = default;
|
|
|
|
|
|
|
|
|
|
static CursorInfo UserInterfaceCursor()
|
|
|
|
|
{
|
|
|
|
|
return CursorInfo { CursorType::UserInterface };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CursorInfo GameCursor(int gameSpriteId)
|
|
|
|
|
{
|
|
|
|
|
return CursorInfo { CursorType::Game, gameSpriteId };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CursorInfo UnknownCursor()
|
|
|
|
|
{
|
|
|
|
|
return CursorInfo { CursorType::Unknown };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] CursorType type() const
|
|
|
|
|
{
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] int id() const
|
|
|
|
|
{
|
|
|
|
|
return id_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] bool Enabled() const
|
|
|
|
|
{
|
|
|
|
|
return enabled_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetEnabled(bool value)
|
|
|
|
|
{
|
|
|
|
|
#if LOG_HWCURSOR
|
|
|
|
|
if (enabled_ != value) {
|
|
|
|
|
Log("hwcursor: SetEnabled {}", value);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
enabled_ = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[[nodiscard]] bool needsReinitialization()
|
|
|
|
|
{
|
|
|
|
|
return needs_reinitialization_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setNeedsReinitialization(bool value)
|
|
|
|
|
{
|
|
|
|
|
#if LOG_HWCURSOR
|
|
|
|
|
if (needs_reinitialization_ != value) {
|
|
|
|
|
Log("hwcursor: setNeedsReinitialization {}", value);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
needs_reinitialization_ = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool operator==(const CursorInfo &other) const
|
|
|
|
|
{
|
|
|
|
|
return type_ == other.type_ && (type_ != CursorType::Game || id_ == other.id_);
|
|
|
|
|
}
|
|
|
|
|
bool operator!=(const CursorInfo &other) const
|
|
|
|
|
{
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
explicit CursorInfo(CursorType type, int id = 0)
|
|
|
|
|
: type_(type)
|
|
|
|
|
, id_(id)
|
|
|
|
|
, enabled_(false)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CursorType type_ = CursorType::Unknown;
|
|
|
|
|
|
|
|
|
|
// ID for CursorType::Game
|
|
|
|
|
int id_;
|
|
|
|
|
|
|
|
|
|
bool enabled_ = false;
|
|
|
|
|
|
|
|
|
|
bool needs_reinitialization_ = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CursorInfo &GetCurrentCursorInfo();
|
|
|
|
|
|
|
|
|
|
// Whether the current cursor is a hardware cursor.
|
|
|
|
|
inline bool IsHardwareCursor()
|
|
|
|
|
{
|
|
|
|
|
return GetCurrentCursorInfo().Enabled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetHardwareCursor(CursorInfo cursorInfo);
|
|
|
|
|
|
|
|
|
|
inline void DoReinitializeHardwareCursor()
|
|
|
|
|
{
|
|
|
|
|
#if LOG_HWCURSOR
|
|
|
|
|
Log("hwcursor: DoReinitializeHardwareCursor");
|
|
|
|
|
#endif
|
|
|
|
|
SetHardwareCursor(GetCurrentCursorInfo());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool IsHardwareCursorVisible()
|
|
|
|
|
{
|
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
|
return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE;
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void SetHardwareCursorVisible(bool visible)
|
|
|
|
|
{
|
|
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
|
|
|
if (IsHardwareCursorVisible() == visible)
|
|
|
|
|
return;
|
|
|
|
|
if (visible && GetCurrentCursorInfo().needsReinitialization()) {
|
|
|
|
|
DoReinitializeHardwareCursor();
|
|
|
|
|
}
|
|
|
|
|
#if LOG_HWCURSOR
|
|
|
|
|
Log("hwcursor: SetHardwareCursorVisible {}", visible);
|
|
|
|
|
#endif
|
|
|
|
|
if (SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE) < 0) {
|
|
|
|
|
LogError("{}", SDL_GetError());
|
|
|
|
|
SDL_ClearError();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline void ReinitializeHardwareCursor()
|
|
|
|
|
{
|
|
|
|
|
if (IsHardwareCursorVisible()) {
|
|
|
|
|
DoReinitializeHardwareCursor();
|
|
|
|
|
} else {
|
|
|
|
|
GetCurrentCursorInfo().setNeedsReinitialization(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace devilution
|