2026-04-06 03:17:53 +08:00
|
|
|
#ifndef NOMINMAX
|
|
|
|
|
#define NOMINMAX
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
2026-04-19 15:52:28 +08:00
|
|
|
#include "app/Platform/Win32/InputModifierTracker.h"
|
2026-04-06 03:17:53 +08:00
|
|
|
|
|
|
|
|
#include <XCEngine/UI/Types.h>
|
|
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2026-04-06 20:02:34 +08:00
|
|
|
using XCEngine::UI::Editor::Host::InputModifierTracker;
|
2026-04-06 03:17:53 +08:00
|
|
|
using XCEngine::UI::UIInputEventType;
|
2026-04-19 00:03:25 +08:00
|
|
|
using XCEngine::UI::UIPointerButton;
|
2026-04-06 03:17:53 +08:00
|
|
|
|
|
|
|
|
TEST(InputModifierTrackerTest, ControlStatePersistsAcrossChordKeyDownAndClearsOnKeyUp) {
|
|
|
|
|
InputModifierTracker tracker = {};
|
|
|
|
|
|
|
|
|
|
const auto ctrlDown = tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
0x001D0001);
|
|
|
|
|
EXPECT_TRUE(ctrlDown.control);
|
|
|
|
|
EXPECT_FALSE(ctrlDown.shift);
|
|
|
|
|
EXPECT_FALSE(ctrlDown.alt);
|
|
|
|
|
|
|
|
|
|
const auto chordKeyDown = tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
'P',
|
|
|
|
|
0x00190001);
|
|
|
|
|
EXPECT_TRUE(chordKeyDown.control);
|
|
|
|
|
|
|
|
|
|
const auto ctrlUp = tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyUp,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
static_cast<LPARAM>(0xC01D0001u));
|
|
|
|
|
EXPECT_FALSE(ctrlUp.control);
|
|
|
|
|
|
|
|
|
|
const auto nextKeyDown = tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
'P',
|
|
|
|
|
0x00190001);
|
|
|
|
|
EXPECT_FALSE(nextKeyDown.control);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(InputModifierTrackerTest, PointerModifiersMergeMouseFlagsWithTrackedKeyboardState) {
|
|
|
|
|
InputModifierTracker tracker = {};
|
|
|
|
|
tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
VK_MENU,
|
|
|
|
|
0x00380001);
|
|
|
|
|
|
2026-04-19 00:03:25 +08:00
|
|
|
const auto modifiers = tracker.BuildPointerModifiers(MK_SHIFT | MK_RBUTTON);
|
2026-04-06 03:17:53 +08:00
|
|
|
EXPECT_TRUE(modifiers.shift);
|
|
|
|
|
EXPECT_TRUE(modifiers.alt);
|
|
|
|
|
EXPECT_FALSE(modifiers.control);
|
|
|
|
|
EXPECT_FALSE(modifiers.super);
|
2026-04-19 00:03:25 +08:00
|
|
|
EXPECT_FALSE(modifiers.leftMouse);
|
|
|
|
|
EXPECT_TRUE(modifiers.rightMouse);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(InputModifierTrackerTest, PointerMessagesUpdateTrackedMouseButtonState) {
|
|
|
|
|
InputModifierTracker tracker = {};
|
|
|
|
|
|
|
|
|
|
const auto leftDown = tracker.ApplyPointerMessage(
|
|
|
|
|
UIInputEventType::PointerButtonDown,
|
|
|
|
|
UIPointerButton::Left,
|
|
|
|
|
0u);
|
|
|
|
|
EXPECT_TRUE(leftDown.leftMouse);
|
|
|
|
|
EXPECT_TRUE(tracker.GetCurrentModifiers().leftMouse);
|
|
|
|
|
|
|
|
|
|
const auto leftUp = tracker.ApplyPointerMessage(
|
|
|
|
|
UIInputEventType::PointerButtonUp,
|
|
|
|
|
UIPointerButton::Left,
|
|
|
|
|
0u);
|
|
|
|
|
EXPECT_FALSE(leftUp.leftMouse);
|
|
|
|
|
EXPECT_FALSE(tracker.GetCurrentModifiers().leftMouse);
|
2026-04-06 03:17:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST(InputModifierTrackerTest, RightControlIsTrackedIndependentlyFromLeftControl) {
|
|
|
|
|
InputModifierTracker tracker = {};
|
|
|
|
|
|
|
|
|
|
tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
static_cast<LPARAM>(0x011D0001u));
|
|
|
|
|
EXPECT_TRUE(tracker.GetCurrentModifiers().control);
|
|
|
|
|
|
|
|
|
|
tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyDown,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
0x001D0001);
|
|
|
|
|
EXPECT_TRUE(tracker.GetCurrentModifiers().control);
|
|
|
|
|
|
|
|
|
|
tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyUp,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
static_cast<LPARAM>(0xC11D0001u));
|
|
|
|
|
EXPECT_TRUE(tracker.GetCurrentModifiers().control);
|
|
|
|
|
|
|
|
|
|
tracker.ApplyKeyMessage(
|
|
|
|
|
UIInputEventType::KeyUp,
|
|
|
|
|
VK_CONTROL,
|
|
|
|
|
static_cast<LPARAM>(0xC01D0001u));
|
|
|
|
|
EXPECT_FALSE(tracker.GetCurrentModifiers().control);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|