Files
XCEngine/tests/NewEditor/test_xcui_input_bridge.cpp

147 lines
6.3 KiB
C++

#include <gtest/gtest.h>
#include "XCUIBackend/XCUIInputBridge.h"
#include <XCEngine/Input/InputTypes.h>
namespace {
using XCEngine::Editor::XCUIBackend::XCUIInputBridge;
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeCaptureOptions;
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta;
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameSnapshot;
using XCEngine::Editor::XCUIBackend::XCUIInputBridgeKeyState;
using XCEngine::Editor::XCUIBackend::XCUIWin32InputSource;
using XCEngine::Input::KeyCode;
using XCEngine::UI::UIInputEventType;
using XCEngine::UI::UIPoint;
XCUIInputBridgeKeyState MakeKeyState(KeyCode keyCode, bool down, bool repeat = false) {
XCUIInputBridgeKeyState state = {};
state.keyCode = static_cast<std::int32_t>(keyCode);
state.down = down;
state.repeat = repeat;
return state;
}
} // namespace
TEST(XCUIInputBridgeTest, TranslateBuildsPointerKeyboardAndCharacterEventsFromSnapshots) {
XCUIInputBridgeFrameSnapshot previous = {};
XCUIInputBridgeFrameSnapshot current = {};
current.pointerInside = true;
current.pointerPosition = UIPoint(32.0f, 48.0f);
current.pointerButtonsDown[0] = true;
current.windowFocused = true;
current.keys.push_back(MakeKeyState(KeyCode::P, true));
current.characters.push_back(static_cast<std::uint32_t>('p'));
const XCUIInputBridgeFrameDelta delta = XCUIInputBridge::Translate(previous, current);
EXPECT_TRUE(delta.focusGained);
EXPECT_TRUE(delta.pointer.entered);
EXPECT_TRUE(delta.pointer.moved);
EXPECT_TRUE(delta.pointer.pressed[0]);
ASSERT_EQ(delta.keyboard.pressedKeys.size(), 1u);
EXPECT_EQ(delta.keyboard.pressedKeys[0], static_cast<std::int32_t>(KeyCode::P));
ASSERT_EQ(delta.keyboard.characters.size(), 1u);
EXPECT_EQ(delta.keyboard.characters[0], static_cast<std::uint32_t>('p'));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::FocusGained));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::PointerEnter));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::PointerMove));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::PointerButtonDown));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::KeyDown));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::Character));
}
TEST(XCUIInputBridgeTest, PrimeSuppressesSyntheticFirstFrameTransitions) {
XCUIInputBridge bridge = {};
XCUIInputBridgeFrameSnapshot baseline = {};
baseline.pointerInside = true;
baseline.pointerPosition = UIPoint(24.0f, 12.0f);
baseline.pointerButtonsDown[0] = true;
baseline.windowFocused = true;
baseline.keys.push_back(MakeKeyState(KeyCode::P, true));
bridge.Prime(baseline);
const XCUIInputBridgeFrameDelta firstDelta = bridge.Translate(baseline);
EXPECT_FALSE(firstDelta.HasEvents());
XCUIInputBridgeFrameSnapshot released = baseline;
released.pointerButtonsDown[0] = false;
released.keys.clear();
const XCUIInputBridgeFrameDelta secondDelta = bridge.Translate(released);
EXPECT_TRUE(secondDelta.pointer.released[0]);
ASSERT_EQ(secondDelta.keyboard.releasedKeys.size(), 1u);
EXPECT_EQ(secondDelta.keyboard.releasedKeys[0], static_cast<std::int32_t>(KeyCode::P));
EXPECT_TRUE(secondDelta.HasEventType(UIInputEventType::PointerButtonUp));
EXPECT_TRUE(secondDelta.HasEventType(UIInputEventType::KeyUp));
}
TEST(XCUIInputBridgeTest, Win32InputSourceCapturesPointerWheelKeyRepeatAndCharacters) {
XCUIWin32InputSource inputSource = {};
inputSource.HandleWindowMessage(nullptr, WM_SETFOCUS, 0, 0);
inputSource.HandleWindowMessage(nullptr, WM_MOUSEMOVE, 0, MAKELPARAM(64, 96));
inputSource.HandleWindowMessage(nullptr, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(64, 96));
inputSource.HandleWindowMessage(nullptr, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0);
inputSource.HandleWindowMessage(nullptr, WM_KEYDOWN, 'P', 0);
inputSource.HandleWindowMessage(nullptr, WM_KEYDOWN, 'P', 1u << 30u);
inputSource.HandleWindowMessage(nullptr, WM_CHAR, 'p', 0);
XCUIInputBridgeCaptureOptions options = {};
options.windowFocused = true;
const XCUIInputBridgeFrameSnapshot snapshot = inputSource.CaptureSnapshot(options);
EXPECT_TRUE(snapshot.windowFocused);
EXPECT_TRUE(snapshot.pointerInside);
EXPECT_EQ(snapshot.pointerPosition.x, 64.0f);
EXPECT_EQ(snapshot.pointerPosition.y, 96.0f);
EXPECT_TRUE(snapshot.pointerButtonsDown[0]);
EXPECT_FLOAT_EQ(snapshot.wheelDelta.y, 1.0f);
EXPECT_TRUE(snapshot.IsKeyDown(static_cast<std::int32_t>(KeyCode::P)));
ASSERT_EQ(snapshot.characters.size(), 1u);
EXPECT_EQ(snapshot.characters[0], static_cast<std::uint32_t>('p'));
const XCUIInputBridgeFrameDelta delta = XCUIInputBridge::Translate(XCUIInputBridgeFrameSnapshot(), snapshot);
EXPECT_TRUE(delta.pointer.pressed[0]);
ASSERT_EQ(delta.keyboard.pressedKeys.size(), 1u);
EXPECT_EQ(delta.keyboard.pressedKeys[0], static_cast<std::int32_t>(KeyCode::P));
EXPECT_TRUE(delta.HasEventType(UIInputEventType::Character));
inputSource.ClearFrameTransients();
const XCUIInputBridgeFrameSnapshot afterClear = inputSource.CaptureSnapshot(options);
EXPECT_FLOAT_EQ(afterClear.wheelDelta.x, 0.0f);
EXPECT_FLOAT_EQ(afterClear.wheelDelta.y, 0.0f);
EXPECT_TRUE(afterClear.characters.empty());
const XCUIInputBridgeKeyState* repeatedKey =
afterClear.FindKeyState(static_cast<std::int32_t>(KeyCode::P));
ASSERT_NE(repeatedKey, nullptr);
EXPECT_FALSE(repeatedKey->repeat);
}
TEST(XCUIInputBridgeTest, Win32InputSourceClearsPressedStateOnFocusLoss) {
XCUIWin32InputSource inputSource = {};
inputSource.HandleWindowMessage(nullptr, WM_SETFOCUS, 0, 0);
inputSource.HandleWindowMessage(nullptr, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(20, 24));
inputSource.HandleWindowMessage(nullptr, WM_KEYDOWN, 'P', 0);
XCUIInputBridgeCaptureOptions options = {};
options.windowFocused = true;
XCUIInputBridgeFrameSnapshot focused = inputSource.CaptureSnapshot(options);
EXPECT_TRUE(focused.pointerButtonsDown[0]);
EXPECT_TRUE(focused.IsKeyDown(static_cast<std::int32_t>(KeyCode::P)));
inputSource.HandleWindowMessage(nullptr, WM_KILLFOCUS, 0, 0);
XCUIInputBridgeFrameSnapshot blurred = inputSource.CaptureSnapshot(options);
EXPECT_FALSE(blurred.windowFocused);
EXPECT_FALSE(blurred.pointerButtonsDown[0]);
EXPECT_FALSE(blurred.IsKeyDown(static_cast<std::int32_t>(KeyCode::P)));
}