Add XCUI command routing and widget state models

This commit is contained in:
2026-04-05 12:10:55 +08:00
parent 511e94fd30
commit 68c4c80b06
18 changed files with 1329 additions and 9 deletions

View File

@@ -242,6 +242,34 @@ TEST(XCUIHostedPreviewPresenterTest, QueuedNativePresenterFallsBackLogicalSizeTo
EXPECT_FLOAT_EQ(image.uvMax.y, 0.5f);
}
TEST(XCUIHostedPreviewPresenterTest, QueuedNativePresenterFallsBackWhenLogicalSizeIsPartiallySpecified) {
XCUIHostedPreviewQueue queue = {};
XCUIHostedPreviewSurfaceRegistry surfaceRegistry = {};
queue.BeginFrame();
std::unique_ptr<IXCUIHostedPreviewPresenter> presenter =
CreateQueuedNativeXCUIHostedPreviewPresenter(queue, surfaceRegistry);
ASSERT_NE(presenter, nullptr);
XCEngine::UI::UIDrawData drawData = {};
drawData.EmplaceDrawList("HostedPreviewPartialLogicalSize").AddFilledRect(
XCEngine::UI::UIRect(2.0f, 3.0f, 18.0f, 9.0f),
XCEngine::UI::UIColor(0.1f, 0.2f, 0.3f, 1.0f));
XCUIHostedPreviewFrame frame = {};
frame.drawData = &drawData;
frame.debugName = "XCUI Partial Logical Size";
frame.canvasRect = XCEngine::UI::UIRect(10.0f, 20.0f, 300.0f, 140.0f);
frame.logicalSize = XCEngine::UI::UISize(512.0f, 0.0f);
ASSERT_TRUE(presenter->Present(frame));
ASSERT_EQ(queue.GetQueuedFrames().size(), 1u);
const XCUIHostedPreviewQueuedFrame& queuedFrame = queue.GetQueuedFrames().front();
EXPECT_FLOAT_EQ(queuedFrame.logicalSize.width, 300.0f);
EXPECT_FLOAT_EQ(queuedFrame.logicalSize.height, 140.0f);
}
TEST(XCUIHostedPreviewPresenterTest, QueuedNativePresenterRejectsMissingDrawDataAndLeavesQueueUntouched) {
XCUIHostedPreviewQueue queue = {};
XCUIHostedPreviewSurfaceRegistry surfaceRegistry = {};
@@ -430,6 +458,61 @@ TEST(XCUIHostedPreviewPresenterTest, SurfaceRegistryTracksQueuedFrameMetadataAlo
EXPECT_TRUE(descriptor.image.IsValid());
}
TEST(XCUIHostedPreviewPresenterTest, SurfaceRegistryReusesDescriptorForRepeatedQueuedFrameKeys) {
XCUIHostedPreviewSurfaceRegistry surfaceRegistry = {};
surfaceRegistry.BeginFrame();
surfaceRegistry.UpdateSurface(
"XCUI Demo",
MakeHostedPreviewTextureHandle(31u, 400u, 200u),
XCEngine::UI::UIRect(0.0f, 0.0f, 200.0f, 100.0f));
XCUIHostedPreviewQueuedFrame firstQueuedFrame = {};
firstQueuedFrame.debugName = "XCUI Demo";
firstQueuedFrame.debugSource = "tests.hosted_preview.first";
firstQueuedFrame.canvasRect = XCEngine::UI::UIRect(8.0f, 12.0f, 320.0f, 180.0f);
firstQueuedFrame.logicalSize = XCEngine::UI::UISize(640.0f, 360.0f);
firstQueuedFrame.drawData.EmplaceDrawList("First").AddFilledRect(
XCEngine::UI::UIRect(0.0f, 0.0f, 16.0f, 16.0f),
XCEngine::UI::UIColor(1.0f, 0.0f, 0.0f, 1.0f));
XCUIHostedPreviewQueuedFrame secondQueuedFrame = {};
secondQueuedFrame.debugName = "XCUI Demo";
secondQueuedFrame.debugSource = "tests.hosted_preview.second";
secondQueuedFrame.canvasRect = XCEngine::UI::UIRect(20.0f, 24.0f, 256.0f, 144.0f);
secondQueuedFrame.logicalSize = XCEngine::UI::UISize(512.0f, 288.0f);
XCEngine::UI::UIDrawList& secondDrawList = secondQueuedFrame.drawData.EmplaceDrawList("Second");
secondDrawList.AddFilledRect(
XCEngine::UI::UIRect(1.0f, 2.0f, 20.0f, 10.0f),
XCEngine::UI::UIColor(0.0f, 1.0f, 0.0f, 1.0f));
secondDrawList.AddText(
XCEngine::UI::UIPoint(4.0f, 6.0f),
"second",
XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f),
12.0f);
surfaceRegistry.RecordQueuedFrame(firstQueuedFrame, 1u);
surfaceRegistry.RecordQueuedFrame(secondQueuedFrame, 7u);
ASSERT_EQ(surfaceRegistry.GetDescriptors().size(), 1u);
XCUIHostedPreviewSurfaceDescriptor descriptor = {};
ASSERT_TRUE(surfaceRegistry.TryGetSurfaceDescriptor("XCUI Demo", descriptor));
EXPECT_EQ(descriptor.debugSource, "tests.hosted_preview.second");
EXPECT_FLOAT_EQ(descriptor.canvasRect.x, 20.0f);
EXPECT_FLOAT_EQ(descriptor.canvasRect.y, 24.0f);
EXPECT_FLOAT_EQ(descriptor.canvasRect.width, 256.0f);
EXPECT_FLOAT_EQ(descriptor.canvasRect.height, 144.0f);
EXPECT_FLOAT_EQ(descriptor.logicalSize.width, 512.0f);
EXPECT_FLOAT_EQ(descriptor.logicalSize.height, 288.0f);
EXPECT_EQ(descriptor.queuedFrameIndex, 7u);
EXPECT_EQ(descriptor.submittedDrawListCount, 1u);
EXPECT_EQ(descriptor.submittedCommandCount, 2u);
EXPECT_TRUE(descriptor.queuedThisFrame);
EXPECT_TRUE(descriptor.image.IsValid());
EXPECT_EQ(descriptor.image.texture.nativeHandle, 31u);
}
TEST(XCUIHostedPreviewPresenterTest, SurfaceRegistryRejectsInvalidSurfaceUpdatesWithoutClobberingExistingImage) {
XCUIHostedPreviewSurfaceRegistry surfaceRegistry = {};
XCUIHostedPreviewSurfaceDescriptor descriptor = {};