engine: sync editor rendering and ui changes

This commit is contained in:
2026-04-08 16:09:15 +08:00
parent 31756847ab
commit 162f1cc12e
153 changed files with 4454 additions and 2990 deletions

View File

@@ -1,5 +1,6 @@
#include <gtest/gtest.h>
#include <XCEngine/Input/InputTypes.h>
#include <XCEngine/UI/Runtime/UIScreenDocumentHost.h>
#include <XCEngine/UI/Runtime/UIScreenPlayer.h>
#include <XCEngine/UI/Runtime/UISceneRuntimeContext.h>
@@ -22,6 +23,7 @@ using XCEngine::UI::Runtime::UISceneRuntimeContext;
using XCEngine::UI::Runtime::UIDocumentScreenHost;
using XCEngine::UI::Runtime::UIScreenStackController;
using XCEngine::UI::Runtime::UISystem;
using XCEngine::Input::KeyCode;
namespace fs = std::filesystem;
@@ -515,6 +517,79 @@ TEST(UIRuntimeTest, DocumentHostTracksHoverFocusAndPointerCaptureAcrossFrames) {
EXPECT_NE(afterRelease.hoveredStateKey.find("/input-route"), std::string::npos);
}
TEST(UIRuntimeTest, DocumentHostTraversesKeyboardFocusAndKeyboardActivationAcrossFrames) {
TempFileScope viewFile(
"xcui_runtime_keyboard_focus",
".xcui",
"<View name=\"Keyboard Focus Test\">\n"
" <Column padding=\"18\" gap=\"10\">\n"
" <Button id=\"focus-first\" text=\"First Focus\" />\n"
" <Button id=\"focus-second\" text=\"Second Focus\" />\n"
" <Button id=\"focus-third\" text=\"Third Focus\" />\n"
" </Column>\n"
"</View>\n");
UIDocumentScreenHost host = {};
UIScreenPlayer player(host);
ASSERT_TRUE(player.Load(BuildScreenAsset(viewFile.Path(), "runtime.keyboard.focus")));
UIScreenFrameInput firstInput = BuildInputState(1u);
firstInput.viewportRect = XCEngine::UI::UIRect(0.0f, 0.0f, 520.0f, 260.0f);
player.Update(firstInput);
const auto& initialSnapshot = host.GetInputDebugSnapshot();
EXPECT_TRUE(initialSnapshot.focusedStateKey.empty());
UIScreenFrameInput tabInput = BuildInputState(2u);
tabInput.viewportRect = firstInput.viewportRect;
XCEngine::UI::UIInputEvent tabEvent = {};
tabEvent.type = XCEngine::UI::UIInputEventType::KeyDown;
tabEvent.keyCode = static_cast<std::int32_t>(KeyCode::Tab);
tabInput.events.push_back(tabEvent);
player.Update(tabInput);
const auto& afterFirstTab = host.GetInputDebugSnapshot();
EXPECT_NE(afterFirstTab.focusedStateKey.find("/focus-first"), std::string::npos);
EXPECT_EQ(afterFirstTab.lastResult, "Focus traversed");
UIScreenFrameInput secondTabInput = BuildInputState(3u);
secondTabInput.viewportRect = firstInput.viewportRect;
secondTabInput.events.push_back(tabEvent);
player.Update(secondTabInput);
const auto& afterSecondTab = host.GetInputDebugSnapshot();
EXPECT_NE(afterSecondTab.focusedStateKey.find("/focus-second"), std::string::npos);
UIScreenFrameInput reverseTabInput = BuildInputState(4u);
reverseTabInput.viewportRect = firstInput.viewportRect;
XCEngine::UI::UIInputEvent reverseTabEvent = tabEvent;
reverseTabEvent.modifiers.shift = true;
reverseTabInput.events.push_back(reverseTabEvent);
player.Update(reverseTabInput);
const auto& afterReverseTab = host.GetInputDebugSnapshot();
EXPECT_NE(afterReverseTab.focusedStateKey.find("/focus-first"), std::string::npos);
UIScreenFrameInput enterDownInput = BuildInputState(5u);
enterDownInput.viewportRect = firstInput.viewportRect;
XCEngine::UI::UIInputEvent enterDownEvent = {};
enterDownEvent.type = XCEngine::UI::UIInputEventType::KeyDown;
enterDownEvent.keyCode = static_cast<std::int32_t>(KeyCode::Enter);
enterDownInput.events.push_back(enterDownEvent);
player.Update(enterDownInput);
const auto& afterEnterDown = host.GetInputDebugSnapshot();
EXPECT_NE(afterEnterDown.focusedStateKey.find("/focus-first"), std::string::npos);
EXPECT_NE(afterEnterDown.activeStateKey.find("/focus-first"), std::string::npos);
EXPECT_EQ(afterEnterDown.lastTargetKind, "Focused");
UIScreenFrameInput enterUpInput = BuildInputState(6u);
enterUpInput.viewportRect = firstInput.viewportRect;
XCEngine::UI::UIInputEvent enterUpEvent = {};
enterUpEvent.type = XCEngine::UI::UIInputEventType::KeyUp;
enterUpEvent.keyCode = static_cast<std::int32_t>(KeyCode::Enter);
enterUpInput.events.push_back(enterUpEvent);
player.Update(enterUpInput);
const auto& afterEnterUp = host.GetInputDebugSnapshot();
EXPECT_NE(afterEnterUp.focusedStateKey.find("/focus-first"), std::string::npos);
EXPECT_TRUE(afterEnterUp.activeStateKey.empty());
}
TEST(UIRuntimeTest, ScreenPlayerConsumeLastFrameReturnsDetachedPacketAndClearsBorrowedState) {
TempFileScope viewFile("xcui_runtime_consume_player", ".xcui", BuildViewMarkup("Runtime Consume"));
UIDocumentScreenHost host = {};