Files
Custom-Operating-System/userland/servers/window_server/src/Managers/CursorManager.h

214 lines
7.6 KiB
C++

#pragma once
#include "../Devices/Screen.h"
#include "../IPC/Event.h"
#include <algorithm>
#include <libg/PixelBitmap.h>
#include <libg/Point.h>
#ifdef TARGET_DESKTOP
#define CURSOR_OFFSET (2)
#elif TARGET_MOBILE
#define CURSOR_OFFSET (6)
#endif
namespace WinServer {
class CursorManager {
public:
enum class Params {
X,
Y,
LeftButton,
RightButton,
OffsetX,
OffsetY,
Wheel,
// Only for getters of conditions changes.
Coords,
Buttons,
};
inline static CursorManager& the()
{
extern CursorManager* s_WinServer_CursorManager_the;
return *s_WinServer_CursorManager_the;
}
CursorManager();
~CursorManager() = default;
inline const LG::PixelBitmap& current_cursor() const { return std_cursor(); }
inline const LG::PixelBitmap& std_cursor() const { return m_std_cursor; }
inline LG::Point<int> draw_position() { return { m_mouse_x - CURSOR_OFFSET, m_mouse_y - CURSOR_OFFSET }; }
inline int x() const
{
return m_mouse_x;
}
inline int y() const { return m_mouse_y; }
template <Params param>
constexpr int get();
template <Params param>
constexpr bool pressed() const;
template <Params param>
constexpr bool is_changed();
inline void clear_changed(uint32_t val = 0) { m_mask_changed_objects = val; }
template <Params param, typename Value>
inline constexpr void set(Value val)
{
if constexpr (param == CursorManager::Params::X) {
val = std::max(std::min(val, (int)m_screen.width() - 1), 0);
m_mouse_offset_x = val - m_mouse_x;
m_mouse_x = val;
set_changed<CursorManager::Params::X>();
} else if constexpr (param == CursorManager::Params::Y) {
val = std::max(std::min(val, (int)m_screen.height() - 1), 0);
m_mouse_offset_y = val - m_mouse_y;
m_mouse_y = val;
set_changed<CursorManager::Params::Y>();
} else if constexpr (param == CursorManager::Params::OffsetX) {
if (val != 0) {
set<CursorManager::Params::X>(m_mouse_x + val);
} else {
m_mouse_offset_x = 0;
}
} else if constexpr (param == CursorManager::Params::OffsetY) {
if (val != 0) {
set<CursorManager::Params::Y>(m_mouse_y + val);
} else {
m_mouse_offset_y = 0;
}
} else if constexpr (param == CursorManager::Params::LeftButton) {
if (m_mouse_left_button_pressed != val) {
set_changed<CursorManager::Params::LeftButton>();
}
m_mouse_left_button_pressed = val;
} else if constexpr (param == CursorManager::Params::RightButton) {
if (m_mouse_right_button_pressed != val) {
set_changed<CursorManager::Params::RightButton>();
}
m_mouse_right_button_pressed = val;
} else if constexpr (param == CursorManager::Params::Wheel) {
if (val != 0) {
set_changed<CursorManager::Params::Wheel>();
}
m_wheel = val;
} else {
[]<bool flag = false>() { static_assert(flag, "Could not call set() with such param!"); }
();
}
}
template <Params param>
inline constexpr void set_changed()
{
if constexpr (param == CursorManager::Params::X) {
m_mask_changed_objects |= CursorManager::ChangedValues::MouseCoords;
} else if constexpr (param == CursorManager::Params::Y) {
m_mask_changed_objects |= CursorManager::ChangedValues::MouseCoords;
} else if constexpr (param == CursorManager::Params::LeftButton) {
m_mask_changed_objects |= CursorManager::ChangedValues::LeftButton;
} else if constexpr (param == CursorManager::Params::RightButton) {
m_mask_changed_objects |= CursorManager::ChangedValues::RightButton;
} else if constexpr (param == CursorManager::Params::Wheel) {
m_mask_changed_objects |= CursorManager::ChangedValues::Wheel;
} else {
[]<bool flag = false>() { static_assert(flag, "Could not set_changed() for the param!"); }
();
}
}
void update_position(MouseEvent* mouse_event)
{
clear_changed();
set<Params::OffsetX>(mouse_event->packet().x_offset);
set<Params::OffsetY>(-mouse_event->packet().y_offset);
set<Params::LeftButton>((mouse_event->packet().button_states & 1));
set<Params::RightButton>((mouse_event->packet().button_states & 2) >> 1);
set<Params::Wheel>(mouse_event->packet().wheel_data);
}
private:
enum ChangedValues {
MouseCoords = 0x1,
LeftButton = 0x2,
RightButton = 0x4,
Wheel = 0x8,
};
int m_mouse_x { 0 };
int m_mouse_y { 0 };
int m_mouse_offset_x { 0 };
int m_mouse_offset_y { 0 };
int m_wheel { 0 };
bool m_mouse_left_button_pressed { false };
bool m_mouse_right_button_pressed { false };
uint32_t m_mask_changed_objects { 0 };
bool m_mouse_changed_button_status { false };
Screen& m_screen;
LG::PixelBitmap m_std_cursor;
};
template <CursorManager::Params param>
inline constexpr int CursorManager::get()
{
if constexpr (param == CursorManager::Params::X) {
return m_mouse_x;
} else if constexpr (param == CursorManager::Params::Y) {
return m_mouse_y;
} else if constexpr (param == CursorManager::Params::OffsetX) {
return m_mouse_offset_x;
} else if constexpr (param == CursorManager::Params::OffsetY) {
return m_mouse_offset_y;
} else if constexpr (param == CursorManager::Params::Wheel) {
return m_wheel;
} else {
[]<bool flag = false>() { static_assert(flag, "Could call get() only for coords-like params!"); }
();
}
}
template <CursorManager::Params param>
inline constexpr bool CursorManager::pressed() const
{
if constexpr (param == CursorManager::Params::LeftButton) {
return m_mouse_left_button_pressed;
} else if constexpr (param == CursorManager::Params::RightButton) {
return m_mouse_right_button_pressed;
} else {
[]<bool flag = false>() { static_assert(flag, "Could call pressed() only for buttons!"); }
();
}
}
template <CursorManager::Params param>
inline constexpr bool CursorManager::is_changed()
{
if constexpr (param == CursorManager::Params::X) {
return (m_mask_changed_objects & CursorManager::ChangedValues::MouseCoords);
} else if constexpr (param == CursorManager::Params::Y) {
return (m_mask_changed_objects & CursorManager::ChangedValues::MouseCoords);
} else if constexpr (param == CursorManager::Params::LeftButton) {
return (m_mask_changed_objects & CursorManager::ChangedValues::LeftButton);
} else if constexpr (param == CursorManager::Params::RightButton) {
return (m_mask_changed_objects & CursorManager::ChangedValues::RightButton);
} else if constexpr (param == CursorManager::Params::Coords) {
return (m_mask_changed_objects & CursorManager::ChangedValues::MouseCoords);
} else if constexpr (param == CursorManager::Params::Buttons) {
return (m_mask_changed_objects & CursorManager::ChangedValues::LeftButton) | (m_mask_changed_objects & CursorManager::ChangedValues::RightButton);
} else if constexpr (param == CursorManager::Params::Wheel) {
return (m_mask_changed_objects & CursorManager::ChangedValues::Wheel);
} else {
[]<bool flag = false>() { static_assert(flag, "Could not call is_changed() for the param!"); }
();
}
}
} // namespace WinServer