feat(xcui): close scroll view validation loop

This commit is contained in:
2026-04-06 13:13:17 +08:00
parent b14a4fb7bb
commit 0804052d6f
11 changed files with 477 additions and 2 deletions

View File

@@ -1,10 +1,12 @@
add_subdirectory(keyboard_focus)
add_subdirectory(pointer_states)
add_subdirectory(scroll_view)
add_subdirectory(shortcut_scope)
add_custom_target(editor_ui_input_integration_tests
DEPENDS
editor_ui_input_keyboard_focus_validation
editor_ui_input_pointer_states_validation
editor_ui_input_scroll_view_validation
editor_ui_input_shortcut_scope_validation
)

View File

@@ -0,0 +1,35 @@
set(EDITOR_UI_INPUT_SCROLL_VIEW_RESOURCES
View.xcui
${CMAKE_SOURCE_DIR}/tests/UI/Editor/integration/shared/themes/editor_validation.xctheme
)
add_executable(editor_ui_input_scroll_view_validation WIN32
main.cpp
${EDITOR_UI_INPUT_SCROLL_VIEW_RESOURCES}
)
target_include_directories(editor_ui_input_scroll_view_validation PRIVATE
${CMAKE_SOURCE_DIR}/tests/UI/Editor/integration/shared/src
${CMAKE_SOURCE_DIR}/engine/include
)
target_compile_definitions(editor_ui_input_scroll_view_validation PRIVATE
UNICODE
_UNICODE
)
if(MSVC)
target_compile_options(editor_ui_input_scroll_view_validation PRIVATE /utf-8 /FS)
set_property(TARGET editor_ui_input_scroll_view_validation PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
target_link_libraries(editor_ui_input_scroll_view_validation PRIVATE
editor_ui_integration_host
)
set_target_properties(editor_ui_input_scroll_view_validation PROPERTIES
OUTPUT_NAME "XCUIEditorInputScrollViewValidation"
)
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES View.xcui)

View File

@@ -0,0 +1,61 @@
<View
name="EditorInputScrollView"
theme="../../shared/themes/editor_validation.xctheme">
<Column padding="20" gap="12">
<Card
title="功能ScrollView 滚动 / clip / overflow"
subtitle="只检查滚轮滚动、裁剪、overflow 与 target 路由,不检查业务面板"
tone="accent"
height="118">
<Column gap="6">
<Text text="1. 把鼠标放到下方日志区内滚动滚轮:内容应上下移动,右下角 Scroll target 应落到 validation-scroll。" />
<Text text="2. 连续向下滚到末尾再继续滚Offset 应被 clampResult 应显示 Scroll delta clamped to current offset。" />
<Text text="3. 把鼠标移到日志区外再滚动日志位置不应变化Result 应显示 No hovered ScrollView。" />
<Text text="4. 这个场景只验证 ScrollView 基础能力,不验证 editor 业务面板。" />
</Column>
</Card>
<Card
title="Scrollable Log"
subtitle="wheel inside this viewport"
height="fill">
<ScrollView id="validation-scroll" height="fill">
<Column gap="8">
<Text text="Line 01 - Scroll validation log" />
<Text text="Line 02 - Scroll validation log" />
<Text text="Line 03 - Scroll validation log" />
<Text text="Line 04 - Scroll validation log" />
<Text text="Line 05 - Scroll validation log" />
<Text text="Line 06 - Scroll validation log" />
<Text text="Line 07 - Scroll validation log" />
<Text text="Line 08 - Scroll validation log" />
<Text text="Line 09 - Scroll validation log" />
<Text text="Line 10 - Scroll validation log" />
<Text text="Line 11 - Scroll validation log" />
<Text text="Line 12 - Scroll validation log" />
<Text text="Line 13 - Scroll validation log" />
<Text text="Line 14 - Scroll validation log" />
<Text text="Line 15 - Scroll validation log" />
<Text text="Line 16 - Scroll validation log" />
<Text text="Line 17 - Scroll validation log" />
<Text text="Line 18 - Scroll validation log" />
<Text text="Line 19 - Scroll validation log" />
<Text text="Line 20 - Scroll validation log" />
<Text text="Line 21 - Scroll validation log" />
<Text text="Line 22 - Scroll validation log" />
<Text text="Line 23 - Scroll validation log" />
<Text text="Line 24 - Scroll validation log" />
</Column>
</ScrollView>
</Card>
<Card
title="Outside Area"
subtitle="wheel here should not move the log"
height="84">
<Column gap="8">
<Text text="把鼠标移到这个区域再滚动,用来检查 No hovered ScrollView。" />
</Column>
</Card>
</Column>
</View>

View File

@@ -0,0 +1,8 @@
#include "Application.h"
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow) {
return XCEngine::Tests::EditorUI::RunEditorUIValidationApp(
hInstance,
nCmdShow,
"editor.input.scroll_view");
}

View File

@@ -530,6 +530,7 @@ void Application::AppendRuntimeOverlay(UIDrawData& drawData, float width, float
if (authoredMode) {
const auto& inputDebug = m_documentHost.GetInputDebugSnapshot();
const auto& scrollDebug = m_documentHost.GetScrollDebugSnapshot();
detailLines.push_back(
"Hover | Focus: " +
ExtractStateKeyTail(inputDebug.hoveredStateKey) +
@@ -601,6 +602,25 @@ void Application::AppendRuntimeOverlay(UIDrawData& drawData, float width, float
"Last event result: " +
(inputDebug.lastResult.empty() ? std::string("n/a") : inputDebug.lastResult));
}
detailLines.push_back(
"Scroll target | Primary: " +
ExtractStateKeyTail(scrollDebug.lastTargetStateKey) +
" | " +
ExtractStateKeyTail(scrollDebug.primaryTargetStateKey));
detailLines.push_back(
"Scroll offset B/A: " +
FormatFloat(scrollDebug.lastOffsetBefore) +
" -> " +
FormatFloat(scrollDebug.lastOffsetAfter) +
" | overflow " +
FormatFloat(scrollDebug.lastOverflow));
detailLines.push_back(
"Scroll H/T: " +
std::to_string(scrollDebug.handledWheelEventCount) +
"/" +
std::to_string(scrollDebug.totalWheelEventCount) +
" | " +
(scrollDebug.lastResult.empty() ? std::string("n/a") : scrollDebug.lastResult));
}
if (m_autoScreenshot.HasPendingCapture()) {

View File

@@ -24,8 +24,8 @@ fs::path RepoRelative(const char* relativePath) {
return (RepoRootPath() / relativePath).lexically_normal();
}
const std::array<EditorValidationScenario, 6>& GetEditorValidationScenarios() {
static const std::array<EditorValidationScenario, 6> scenarios = { {
const std::array<EditorValidationScenario, 7>& GetEditorValidationScenarios() {
static const std::array<EditorValidationScenario, 7> scenarios = { {
{
"editor.input.keyboard_focus",
UIValidationDomain::Editor,
@@ -44,6 +44,15 @@ const std::array<EditorValidationScenario, 6>& GetEditorValidationScenarios() {
RepoRelative("tests/UI/Editor/integration/shared/themes/editor_validation.xctheme"),
RepoRelative("tests/UI/Editor/integration/input/pointer_states/captures")
},
{
"editor.input.scroll_view",
UIValidationDomain::Editor,
"input",
"Editor Input | Scroll View",
RepoRelative("tests/UI/Editor/integration/input/scroll_view/View.xcui"),
RepoRelative("tests/UI/Editor/integration/shared/themes/editor_validation.xctheme"),
RepoRelative("tests/UI/Editor/integration/input/scroll_view/captures")
},
{
"editor.input.shortcut_scope",
UIValidationDomain::Editor,