147 lines
6.3 KiB
C++
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)));
|
||
|
|
}
|