Files
XCEngine/new_editor/app/Platform/Win32/InputModifierTracker.h

254 lines
8.2 KiB
C++

#pragma once
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEngine/UI/Types.h>
#include <windows.h>
#include <cstddef>
#include <cstdint>
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<std::uint32_t>(lParam) & 0x01000000u) != 0u;
}
static std::uint32_t ExtractScanCode(LPARAM lParam) {
return (static_cast<std::uint32_t>(lParam) >> 16u) & 0xffu;
}
static ModifierKey ResolveModifierKey(WPARAM wParam, LPARAM lParam) {
switch (static_cast<std::uint32_t>(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