280 lines
11 KiB
C++
280 lines
11 KiB
C++
#include "Platform/Win32/EditorWindowInputController.h"
|
|
|
|
#include <XCEngine/Input/InputTypes.h>
|
|
|
|
namespace XCEngine::UI::Editor::App::Internal {
|
|
|
|
using ::XCEngine::UI::UIInputEvent;
|
|
using ::XCEngine::UI::UIInputEventType;
|
|
using ::XCEngine::UI::UIInputModifiers;
|
|
using ::XCEngine::UI::UIPointerButton;
|
|
|
|
bool EditorWindowInputController::IsTrackingMouseLeave() const {
|
|
return m_trackingMouseLeave;
|
|
}
|
|
|
|
void EditorWindowInputController::SetTrackingMouseLeave(bool trackingMouseLeave) {
|
|
m_trackingMouseLeave = trackingMouseLeave;
|
|
}
|
|
|
|
EditorWindowPointerCaptureOwner EditorWindowInputController::GetPointerCaptureOwner() const {
|
|
return m_pointerCaptureOwner;
|
|
}
|
|
|
|
bool EditorWindowInputController::OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const {
|
|
return m_pointerCaptureOwner == owner;
|
|
}
|
|
|
|
bool EditorWindowInputController::HasPointerCaptureOwner() const {
|
|
return m_pointerCaptureOwner != EditorWindowPointerCaptureOwner::None;
|
|
}
|
|
|
|
void EditorWindowInputController::AcquirePointerCapture(
|
|
HWND hwnd,
|
|
EditorWindowPointerCaptureOwner owner) {
|
|
if (owner == EditorWindowPointerCaptureOwner::None ||
|
|
hwnd == nullptr ||
|
|
!IsWindow(hwnd)) {
|
|
return;
|
|
}
|
|
|
|
m_pointerCaptureOwner = owner;
|
|
if (GetCapture() != hwnd) {
|
|
SetCapture(hwnd);
|
|
}
|
|
}
|
|
|
|
void EditorWindowInputController::ReleasePointerCapture(
|
|
HWND hwnd,
|
|
EditorWindowPointerCaptureOwner owner) {
|
|
if (m_pointerCaptureOwner != owner) {
|
|
return;
|
|
}
|
|
|
|
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
|
if (hwnd != nullptr && GetCapture() == hwnd) {
|
|
ReleaseCapture();
|
|
}
|
|
}
|
|
|
|
void EditorWindowInputController::ForceReleasePointerCapture(HWND hwnd) {
|
|
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
|
if (hwnd != nullptr && GetCapture() == hwnd) {
|
|
ReleaseCapture();
|
|
}
|
|
}
|
|
|
|
void EditorWindowInputController::ClearPointerCaptureOwner() {
|
|
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
|
}
|
|
|
|
void EditorWindowInputController::QueuePointerEvent(
|
|
UIInputEventType type,
|
|
UIPointerButton button,
|
|
const ::XCEngine::UI::UIPoint& position,
|
|
WPARAM wParam) {
|
|
UIInputEvent event = {};
|
|
event.type = type;
|
|
event.pointerButton = button;
|
|
event.position = position;
|
|
event.modifiers = m_modifierTracker.ApplyPointerMessage(
|
|
type,
|
|
button,
|
|
static_cast<std::size_t>(wParam));
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueueSyntheticPointerStateSyncEvent(
|
|
const ::XCEngine::UI::UIPoint& position,
|
|
const UIInputModifiers& modifiers) {
|
|
UIInputEvent event = {};
|
|
event.type = UIInputEventType::PointerMove;
|
|
event.position = position;
|
|
event.modifiers = modifiers;
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueuePointerLeaveEvent(
|
|
const ::XCEngine::UI::UIPoint& position) {
|
|
UIInputEvent event = {};
|
|
event.type = UIInputEventType::PointerLeave;
|
|
event.position = position;
|
|
event.modifiers = m_modifierTracker.GetCurrentModifiers();
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueuePointerWheelEvent(
|
|
const ::XCEngine::UI::UIPoint& position,
|
|
short wheelDelta,
|
|
WPARAM wParam) {
|
|
UIInputEvent event = {};
|
|
event.type = UIInputEventType::PointerWheel;
|
|
event.position = position;
|
|
event.wheelDelta = static_cast<float>(wheelDelta);
|
|
event.modifiers = m_modifierTracker.ApplyPointerMessage(
|
|
UIInputEventType::PointerWheel,
|
|
UIPointerButton::None,
|
|
static_cast<std::size_t>(wParam));
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueueKeyEvent(UIInputEventType type, WPARAM wParam, LPARAM lParam) {
|
|
UIInputEvent event = {};
|
|
event.type = type;
|
|
event.keyCode = MapVirtualKeyToUIKeyCode(wParam);
|
|
event.modifiers = m_modifierTracker.ApplyKeyMessage(type, wParam, lParam);
|
|
event.repeat = IsRepeatKeyMessage(lParam);
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueueCharacterEvent(WPARAM wParam) {
|
|
UIInputEvent event = {};
|
|
event.type = UIInputEventType::Character;
|
|
event.character = static_cast<std::uint32_t>(wParam);
|
|
event.modifiers = m_modifierTracker.GetCurrentModifiers();
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::QueueWindowFocusEvent(UIInputEventType type) {
|
|
UIInputEvent event = {};
|
|
event.type = type;
|
|
m_pendingEvents.push_back(event);
|
|
}
|
|
|
|
void EditorWindowInputController::SyncInputModifiersFromSystemState() {
|
|
m_modifierTracker.SyncFromSystemState();
|
|
}
|
|
|
|
void EditorWindowInputController::ResetInputModifiers() {
|
|
m_modifierTracker.Reset();
|
|
}
|
|
|
|
UIInputModifiers EditorWindowInputController::GetCurrentModifiers() const {
|
|
return m_modifierTracker.GetCurrentModifiers();
|
|
}
|
|
|
|
bool EditorWindowInputController::HasPendingPointerStateReconciliationEvent() const {
|
|
for (const UIInputEvent& event : m_pendingEvents) {
|
|
switch (event.type) {
|
|
case UIInputEventType::PointerMove:
|
|
case UIInputEventType::PointerEnter:
|
|
case UIInputEventType::PointerButtonDown:
|
|
case UIInputEventType::PointerButtonUp:
|
|
case UIInputEventType::PointerWheel:
|
|
case UIInputEventType::FocusLost:
|
|
return true;
|
|
case UIInputEventType::PointerLeave:
|
|
case UIInputEventType::KeyDown:
|
|
case UIInputEventType::KeyUp:
|
|
case UIInputEventType::Character:
|
|
case UIInputEventType::FocusGained:
|
|
case UIInputEventType::None:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::vector<UIInputEvent> EditorWindowInputController::TakePendingEvents() {
|
|
std::vector<UIInputEvent> events = std::move(m_pendingEvents);
|
|
m_pendingEvents.clear();
|
|
return events;
|
|
}
|
|
|
|
void EditorWindowInputController::ClearPendingEvents() {
|
|
m_pendingEvents.clear();
|
|
}
|
|
|
|
void EditorWindowInputController::ResetInteractionState() {
|
|
ForceReleasePointerCapture(nullptr);
|
|
ClearPendingEvents();
|
|
m_trackingMouseLeave = false;
|
|
m_modifierTracker.Reset();
|
|
}
|
|
|
|
void EditorWindowInputController::ResetWindowState() {
|
|
m_trackingMouseLeave = false;
|
|
m_pointerCaptureOwner = EditorWindowPointerCaptureOwner::None;
|
|
}
|
|
|
|
std::int32_t EditorWindowInputController::MapVirtualKeyToUIKeyCode(WPARAM wParam) {
|
|
using ::XCEngine::Input::KeyCode;
|
|
|
|
switch (wParam) {
|
|
case 'A': return static_cast<std::int32_t>(KeyCode::A);
|
|
case 'B': return static_cast<std::int32_t>(KeyCode::B);
|
|
case 'C': return static_cast<std::int32_t>(KeyCode::C);
|
|
case 'D': return static_cast<std::int32_t>(KeyCode::D);
|
|
case 'E': return static_cast<std::int32_t>(KeyCode::E);
|
|
case 'F': return static_cast<std::int32_t>(KeyCode::F);
|
|
case 'G': return static_cast<std::int32_t>(KeyCode::G);
|
|
case 'H': return static_cast<std::int32_t>(KeyCode::H);
|
|
case 'I': return static_cast<std::int32_t>(KeyCode::I);
|
|
case 'J': return static_cast<std::int32_t>(KeyCode::J);
|
|
case 'K': return static_cast<std::int32_t>(KeyCode::K);
|
|
case 'L': return static_cast<std::int32_t>(KeyCode::L);
|
|
case 'M': return static_cast<std::int32_t>(KeyCode::M);
|
|
case 'N': return static_cast<std::int32_t>(KeyCode::N);
|
|
case 'O': return static_cast<std::int32_t>(KeyCode::O);
|
|
case 'P': return static_cast<std::int32_t>(KeyCode::P);
|
|
case 'Q': return static_cast<std::int32_t>(KeyCode::Q);
|
|
case 'R': return static_cast<std::int32_t>(KeyCode::R);
|
|
case 'S': return static_cast<std::int32_t>(KeyCode::S);
|
|
case 'T': return static_cast<std::int32_t>(KeyCode::T);
|
|
case 'U': return static_cast<std::int32_t>(KeyCode::U);
|
|
case 'V': return static_cast<std::int32_t>(KeyCode::V);
|
|
case 'W': return static_cast<std::int32_t>(KeyCode::W);
|
|
case 'X': return static_cast<std::int32_t>(KeyCode::X);
|
|
case 'Y': return static_cast<std::int32_t>(KeyCode::Y);
|
|
case 'Z': return static_cast<std::int32_t>(KeyCode::Z);
|
|
case '0': return static_cast<std::int32_t>(KeyCode::Zero);
|
|
case '1': return static_cast<std::int32_t>(KeyCode::One);
|
|
case '2': return static_cast<std::int32_t>(KeyCode::Two);
|
|
case '3': return static_cast<std::int32_t>(KeyCode::Three);
|
|
case '4': return static_cast<std::int32_t>(KeyCode::Four);
|
|
case '5': return static_cast<std::int32_t>(KeyCode::Five);
|
|
case '6': return static_cast<std::int32_t>(KeyCode::Six);
|
|
case '7': return static_cast<std::int32_t>(KeyCode::Seven);
|
|
case '8': return static_cast<std::int32_t>(KeyCode::Eight);
|
|
case '9': return static_cast<std::int32_t>(KeyCode::Nine);
|
|
case VK_SPACE: return static_cast<std::int32_t>(KeyCode::Space);
|
|
case VK_TAB: return static_cast<std::int32_t>(KeyCode::Tab);
|
|
case VK_RETURN: return static_cast<std::int32_t>(KeyCode::Enter);
|
|
case VK_ESCAPE: return static_cast<std::int32_t>(KeyCode::Escape);
|
|
case VK_SHIFT: return static_cast<std::int32_t>(KeyCode::LeftShift);
|
|
case VK_CONTROL: return static_cast<std::int32_t>(KeyCode::LeftCtrl);
|
|
case VK_MENU: return static_cast<std::int32_t>(KeyCode::LeftAlt);
|
|
case VK_UP: return static_cast<std::int32_t>(KeyCode::Up);
|
|
case VK_DOWN: return static_cast<std::int32_t>(KeyCode::Down);
|
|
case VK_LEFT: return static_cast<std::int32_t>(KeyCode::Left);
|
|
case VK_RIGHT: return static_cast<std::int32_t>(KeyCode::Right);
|
|
case VK_HOME: return static_cast<std::int32_t>(KeyCode::Home);
|
|
case VK_END: return static_cast<std::int32_t>(KeyCode::End);
|
|
case VK_PRIOR: return static_cast<std::int32_t>(KeyCode::PageUp);
|
|
case VK_NEXT: return static_cast<std::int32_t>(KeyCode::PageDown);
|
|
case VK_DELETE: return static_cast<std::int32_t>(KeyCode::Delete);
|
|
case VK_BACK: return static_cast<std::int32_t>(KeyCode::Backspace);
|
|
case VK_F1: return static_cast<std::int32_t>(KeyCode::F1);
|
|
case VK_F2: return static_cast<std::int32_t>(KeyCode::F2);
|
|
case VK_F3: return static_cast<std::int32_t>(KeyCode::F3);
|
|
case VK_F4: return static_cast<std::int32_t>(KeyCode::F4);
|
|
case VK_F5: return static_cast<std::int32_t>(KeyCode::F5);
|
|
case VK_F6: return static_cast<std::int32_t>(KeyCode::F6);
|
|
case VK_F7: return static_cast<std::int32_t>(KeyCode::F7);
|
|
case VK_F8: return static_cast<std::int32_t>(KeyCode::F8);
|
|
case VK_F9: return static_cast<std::int32_t>(KeyCode::F9);
|
|
case VK_F10: return static_cast<std::int32_t>(KeyCode::F10);
|
|
case VK_F11: return static_cast<std::int32_t>(KeyCode::F11);
|
|
case VK_F12: return static_cast<std::int32_t>(KeyCode::F12);
|
|
default: return static_cast<std::int32_t>(KeyCode::None);
|
|
}
|
|
}
|
|
|
|
bool EditorWindowInputController::IsRepeatKeyMessage(LPARAM lParam) {
|
|
return (static_cast<unsigned long>(lParam) & (1ul << 30)) != 0ul;
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::App::Internal
|