#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include #include #include #include namespace XCEngine::UI::Editor::Host { class InputModifierTracker { public: void Reset() { m_leftShift = false; m_rightShift = false; m_leftControl = false; m_rightControl = false; m_leftAlt = false; m_rightAlt = false; m_leftSuper = false; m_rightSuper = false; m_leftMouse = false; m_rightMouse = false; m_middleMouse = false; m_x1Mouse = false; m_x2Mouse = false; } void SyncFromSystemState() { m_leftShift = (GetKeyState(VK_LSHIFT) & 0x8000) != 0; m_rightShift = (GetKeyState(VK_RSHIFT) & 0x8000) != 0; m_leftControl = (GetKeyState(VK_LCONTROL) & 0x8000) != 0; m_rightControl = (GetKeyState(VK_RCONTROL) & 0x8000) != 0; m_leftAlt = (GetKeyState(VK_LMENU) & 0x8000) != 0; m_rightAlt = (GetKeyState(VK_RMENU) & 0x8000) != 0; m_leftSuper = (GetKeyState(VK_LWIN) & 0x8000) != 0; m_rightSuper = (GetKeyState(VK_RWIN) & 0x8000) != 0; m_leftMouse = (GetKeyState(VK_LBUTTON) & 0x8000) != 0; m_rightMouse = (GetKeyState(VK_RBUTTON) & 0x8000) != 0; m_middleMouse = (GetKeyState(VK_MBUTTON) & 0x8000) != 0; m_x1Mouse = (GetKeyState(VK_XBUTTON1) & 0x8000) != 0; m_x2Mouse = (GetKeyState(VK_XBUTTON2) & 0x8000) != 0; } ::XCEngine::UI::UIInputModifiers GetCurrentModifiers() const { return BuildModifiers(); } ::XCEngine::UI::UIInputModifiers BuildPointerModifiers(std::size_t wParam) const { ::XCEngine::UI::UIInputModifiers modifiers = BuildModifiers(); ApplyPointerWParam(modifiers, wParam); return modifiers; } ::XCEngine::UI::UIInputModifiers ApplyPointerMessage( ::XCEngine::UI::UIInputEventType type, ::XCEngine::UI::UIPointerButton button, std::size_t wParam) { ::XCEngine::UI::UIInputModifiers modifiers = BuildPointerModifiers(wParam); if (type == ::XCEngine::UI::UIInputEventType::PointerButtonDown) { SetPointerButton(modifiers, button, true); } else if (type == ::XCEngine::UI::UIInputEventType::PointerButtonUp) { SetPointerButton(modifiers, button, false); } ApplyPointerState(modifiers); return BuildModifiers(); } ::XCEngine::UI::UIInputModifiers ApplyKeyMessage( ::XCEngine::UI::UIInputEventType type, WPARAM wParam, LPARAM lParam) { if (type == ::XCEngine::UI::UIInputEventType::KeyDown) { SetModifierState(ResolveModifierKey(wParam, lParam), true); } else if (type == ::XCEngine::UI::UIInputEventType::KeyUp) { SetModifierState(ResolveModifierKey(wParam, lParam), false); } return BuildModifiers(); } private: enum class ModifierKey : std::uint8_t { None = 0, LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt, LeftSuper, RightSuper }; static bool IsExtendedKey(LPARAM lParam) { return (static_cast(lParam) & 0x01000000u) != 0u; } static std::uint32_t ExtractScanCode(LPARAM lParam) { return (static_cast(lParam) >> 16u) & 0xffu; } static ModifierKey ResolveModifierKey(WPARAM wParam, LPARAM lParam) { switch (static_cast(wParam)) { case VK_SHIFT: { const UINT shiftVirtualKey = MapVirtualKeyW(ExtractScanCode(lParam), MAPVK_VSC_TO_VK_EX); return shiftVirtualKey == VK_RSHIFT ? ModifierKey::RightShift : ModifierKey::LeftShift; } case VK_LSHIFT: return ModifierKey::LeftShift; case VK_RSHIFT: return ModifierKey::RightShift; case VK_CONTROL: return IsExtendedKey(lParam) ? ModifierKey::RightControl : ModifierKey::LeftControl; case VK_LCONTROL: return ModifierKey::LeftControl; case VK_RCONTROL: return ModifierKey::RightControl; case VK_MENU: return IsExtendedKey(lParam) ? ModifierKey::RightAlt : ModifierKey::LeftAlt; case VK_LMENU: return ModifierKey::LeftAlt; case VK_RMENU: return ModifierKey::RightAlt; case VK_LWIN: return ModifierKey::LeftSuper; case VK_RWIN: return ModifierKey::RightSuper; default: return ModifierKey::None; } } static void ApplyPointerWParam( ::XCEngine::UI::UIInputModifiers& modifiers, std::size_t wParam) { modifiers.shift = modifiers.shift || (wParam & MK_SHIFT) != 0; modifiers.control = modifiers.control || (wParam & MK_CONTROL) != 0; modifiers.leftMouse = (wParam & MK_LBUTTON) != 0; modifiers.rightMouse = (wParam & MK_RBUTTON) != 0; modifiers.middleMouse = (wParam & MK_MBUTTON) != 0; modifiers.x1Mouse = (wParam & MK_XBUTTON1) != 0; modifiers.x2Mouse = (wParam & MK_XBUTTON2) != 0; } static void SetPointerButton( ::XCEngine::UI::UIInputModifiers& modifiers, ::XCEngine::UI::UIPointerButton button, bool pressed) { switch (button) { case ::XCEngine::UI::UIPointerButton::Left: modifiers.leftMouse = pressed; break; case ::XCEngine::UI::UIPointerButton::Right: modifiers.rightMouse = pressed; break; case ::XCEngine::UI::UIPointerButton::Middle: modifiers.middleMouse = pressed; break; case ::XCEngine::UI::UIPointerButton::X1: modifiers.x1Mouse = pressed; break; case ::XCEngine::UI::UIPointerButton::X2: modifiers.x2Mouse = pressed; break; case ::XCEngine::UI::UIPointerButton::None: default: break; } } void ApplyPointerState(const ::XCEngine::UI::UIInputModifiers& modifiers) { m_leftMouse = modifiers.leftMouse; m_rightMouse = modifiers.rightMouse; m_middleMouse = modifiers.middleMouse; m_x1Mouse = modifiers.x1Mouse; m_x2Mouse = modifiers.x2Mouse; } void SetModifierState(ModifierKey key, bool pressed) { switch (key) { case ModifierKey::LeftShift: m_leftShift = pressed; break; case ModifierKey::RightShift: m_rightShift = pressed; break; case ModifierKey::LeftControl: m_leftControl = pressed; break; case ModifierKey::RightControl: m_rightControl = pressed; break; case ModifierKey::LeftAlt: m_leftAlt = pressed; break; case ModifierKey::RightAlt: m_rightAlt = pressed; break; case ModifierKey::LeftSuper: m_leftSuper = pressed; break; case ModifierKey::RightSuper: m_rightSuper = pressed; break; case ModifierKey::None: default: break; } } ::XCEngine::UI::UIInputModifiers BuildModifiers() const { ::XCEngine::UI::UIInputModifiers modifiers = {}; modifiers.shift = m_leftShift || m_rightShift; modifiers.control = m_leftControl || m_rightControl; modifiers.alt = m_leftAlt || m_rightAlt; modifiers.super = m_leftSuper || m_rightSuper; modifiers.leftMouse = m_leftMouse; modifiers.rightMouse = m_rightMouse; modifiers.middleMouse = m_middleMouse; modifiers.x1Mouse = m_x1Mouse; modifiers.x2Mouse = m_x2Mouse; return modifiers; } bool m_leftShift = false; bool m_rightShift = false; bool m_leftControl = false; bool m_rightControl = false; bool m_leftAlt = false; bool m_rightAlt = false; bool m_leftSuper = false; bool m_rightSuper = false; bool m_leftMouse = false; bool m_rightMouse = false; bool m_middleMouse = false; bool m_x1Mouse = false; bool m_x2Mouse = false; }; } // namespace XCEngine::UI::Editor::Host