#pragma once #include "../Devices/Screen.h" #include "../IPC/Event.h" #include #include #include #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 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 constexpr int get(); template constexpr bool pressed() const; template constexpr bool is_changed(); inline void clear_changed(uint32_t val = 0) { m_mask_changed_objects = val; } template 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(); } 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(); } else if constexpr (param == CursorManager::Params::OffsetX) { if (val != 0) { set(m_mouse_x + val); } else { m_mouse_offset_x = 0; } } else if constexpr (param == CursorManager::Params::OffsetY) { if (val != 0) { set(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(); } m_mouse_left_button_pressed = val; } else if constexpr (param == CursorManager::Params::RightButton) { if (m_mouse_right_button_pressed != val) { set_changed(); } m_mouse_right_button_pressed = val; } else if constexpr (param == CursorManager::Params::Wheel) { if (val != 0) { set_changed(); } m_wheel = val; } else { []() { static_assert(flag, "Could not call set() with such param!"); } (); } } template 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 { []() { static_assert(flag, "Could not set_changed() for the param!"); } (); } } void update_position(MouseEvent* mouse_event) { clear_changed(); set(mouse_event->packet().x_offset); set(-mouse_event->packet().y_offset); set((mouse_event->packet().button_states & 1)); set((mouse_event->packet().button_states & 2) >> 1); set(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 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 { []() { static_assert(flag, "Could call get() only for coords-like params!"); } (); } } template 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 { []() { static_assert(flag, "Could call pressed() only for buttons!"); } (); } } template 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 { []() { static_assert(flag, "Could not call is_changed() for the param!"); } (); } } } // namespace WinServer