Route app input dispatch through app core

This commit is contained in:
2026-06-05 06:38:48 +02:00
parent 1df93c23f7
commit b825d920d2
11 changed files with 695 additions and 46 deletions

View File

@@ -565,6 +565,16 @@ add_test(NAME pp_app_core_app_frame_tests COMMAND pp_app_core_app_frame_tests)
set_tests_properties(pp_app_core_app_frame_tests PROPERTIES
LABELS "app;desktop-fast;fuzz")
add_executable(pp_app_core_app_input_tests
app_core/app_input_tests.cpp)
target_link_libraries(pp_app_core_app_input_tests PRIVATE
pp_app_core
pp_test_harness)
add_test(NAME pp_app_core_app_input_tests COMMAND pp_app_core_app_input_tests)
set_tests_properties(pp_app_core_app_input_tests PROPERTIES
LABELS "app;desktop-fast;fuzz")
add_executable(pp_app_core_app_shutdown_tests
app_core/app_shutdown_tests.cpp)
target_link_libraries(pp_app_core_app_shutdown_tests PRIVATE
@@ -1002,6 +1012,31 @@ if(TARGET pano_cli)
WILL_FAIL TRUE
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-frame\".*\"message\":\"resize dimensions")
add_test(NAME pano_cli_plan_app_input_pointer_smoke
COMMAND pano_cli plan-app-input --kind pointer --x 100 --y 50 --zoom 2)
set_tests_properties(pano_cli_plan_app_input_pointer_smoke PROPERTIES
LABELS "app;integration;desktop-fast"
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-input\".*\"kind\":\"pointer\".*\"dispatchDesignerFirst\":true.*\"dispatchMainIfNotConsumed\":true.*\"normalizedX\":50.*\"normalizedY\":25")
add_test(NAME pano_cli_plan_app_input_gesture_smoke
COMMAND pano_cli plan-app-input --kind gesture --x 0 --y 0 --x1 6 --y1 8 --prev-x 0 --prev-y 0 --prev-x1 3 --prev-y1 4 --zoom 2)
set_tests_properties(pano_cli_plan_app_input_gesture_smoke PROPERTIES
LABELS "app;integration;desktop-fast"
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-input\".*\"kind\":\"gesture\".*\"dispatchMain\":true.*\"normalizedX\":1.5.*\"normalizedY\":2.*\"distance\":10.*\"distanceDelta\":5")
add_test(NAME pano_cli_plan_app_input_key_vr_smoke
COMMAND pano_cli plan-app-input --kind key --spacebar --vr-active)
set_tests_properties(pano_cli_plan_app_input_key_vr_smoke PROPERTIES
LABELS "app;integration;desktop-fast"
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-input\".*\"kind\":\"key\".*\"dispatchMain\":true.*\"setKeyDown\":true.*\"syncVrCameraRotation\":true")
add_test(NAME pano_cli_plan_app_input_rejects_bad_float
COMMAND pano_cli plan-app-input --kind pointer --bad-float)
set_tests_properties(pano_cli_plan_app_input_rejects_bad_float PROPERTIES
LABELS "app;integration;desktop-fast;fuzz"
WILL_FAIL TRUE
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-input\".*\"message\":\"input zoom must be finite and positive\"")
add_test(NAME pano_cli_plan_app_shutdown_smoke
COMMAND pano_cli plan-app-shutdown)
set_tests_properties(pano_cli_plan_app_shutdown_smoke PROPERTIES

View File

@@ -0,0 +1,118 @@
#include "app_core/app_input.h"
#include "test_harness.h"
#include <cmath>
namespace {
void pointer_plan_normalizes_coordinates_and_routes_designer_first(pp::tests::Harness& harness)
{
const auto plan = pp::app::plan_app_pointer_dispatch(100.0F, 50.0F, 2.0F, true, true);
PP_EXPECT(harness, plan);
PP_EXPECT(harness, plan.value().request_redraw);
PP_EXPECT(harness, plan.value().dispatch_designer_first);
PP_EXPECT(harness, plan.value().dispatch_main_if_not_consumed);
PP_EXPECT(harness, plan.value().normalized_x == 50.0F);
PP_EXPECT(harness, plan.value().normalized_y == 25.0F);
}
void pointer_plan_rejects_invalid_zoom_or_coordinates(pp::tests::Harness& harness)
{
PP_EXPECT(harness, !pp::app::plan_app_pointer_dispatch(100.0F, 50.0F, 0.0F, true, true));
PP_EXPECT(harness, !pp::app::plan_app_pointer_dispatch(std::nanf(""), 50.0F, 1.0F, true, true));
}
void mouse_cancel_preserves_designer_first_routing(pp::tests::Harness& harness)
{
const auto designer = pp::app::plan_app_mouse_cancel_dispatch(true, true);
const auto main = pp::app::plan_app_mouse_cancel_dispatch(false, true);
PP_EXPECT(harness, designer.request_redraw);
PP_EXPECT(harness, designer.dispatch_designer_first);
PP_EXPECT(harness, designer.dispatch_main_if_not_consumed);
PP_EXPECT(harness, !main.dispatch_designer_first);
PP_EXPECT(harness, main.dispatch_main_if_not_consumed);
}
void gesture_plan_computes_midpoint_distance_and_delta(pp::tests::Harness& harness)
{
const auto plan = pp::app::plan_app_gesture_dispatch(
0.0F,
0.0F,
6.0F,
8.0F,
0.0F,
0.0F,
3.0F,
4.0F,
2.0F,
true);
PP_EXPECT(harness, plan);
PP_EXPECT(harness, plan.value().dispatch_main);
PP_EXPECT(harness, plan.value().normalized_x == 1.5F);
PP_EXPECT(harness, plan.value().normalized_y == 2.0F);
PP_EXPECT(harness, plan.value().distance == 10.0F);
PP_EXPECT(harness, plan.value().distance_delta == 5.0F);
PP_EXPECT(harness, plan.value().position_delta_x == 1.5F);
PP_EXPECT(harness, plan.value().position_delta_y == 2.0F);
}
void gesture_plan_rejects_invalid_input(pp::tests::Harness& harness)
{
PP_EXPECT(
harness,
!pp::app::plan_app_gesture_dispatch(
0.0F,
0.0F,
1.0F,
1.0F,
0.0F,
0.0F,
1.0F,
1.0F,
-1.0F,
true));
}
void key_plan_tracks_state_and_vr_spacebar_sync(pp::tests::Harness& harness)
{
const auto down = pp::app::plan_app_key_down_dispatch(true, true, true);
const auto ordinary = pp::app::plan_app_key_down_dispatch(true, false, true);
const auto up = pp::app::plan_app_key_up_dispatch(true);
PP_EXPECT(harness, down.dispatch_main);
PP_EXPECT(harness, down.set_key_down);
PP_EXPECT(harness, down.sync_vr_camera_rotation);
PP_EXPECT(harness, ordinary.set_key_down);
PP_EXPECT(harness, !ordinary.sync_vr_camera_rotation);
PP_EXPECT(harness, up.dispatch_main);
PP_EXPECT(harness, !up.set_key_down);
}
void simple_input_plan_tracks_main_layout_availability(pp::tests::Harness& harness)
{
const auto available = pp::app::plan_app_main_input_dispatch(true);
const auto missing = pp::app::plan_app_main_input_dispatch(false);
PP_EXPECT(harness, available.request_redraw);
PP_EXPECT(harness, available.dispatch_main);
PP_EXPECT(harness, missing.request_redraw);
PP_EXPECT(harness, !missing.dispatch_main);
}
} // namespace
int main()
{
pp::tests::Harness harness;
harness.run("pointer plan normalizes coordinates and routes designer first", pointer_plan_normalizes_coordinates_and_routes_designer_first);
harness.run("pointer plan rejects invalid zoom or coordinates", pointer_plan_rejects_invalid_zoom_or_coordinates);
harness.run("mouse cancel preserves designer first routing", mouse_cancel_preserves_designer_first_routing);
harness.run("gesture plan computes midpoint distance and delta", gesture_plan_computes_midpoint_distance_and_delta);
harness.run("gesture plan rejects invalid input", gesture_plan_rejects_invalid_input);
harness.run("key plan tracks state and VR spacebar sync", key_plan_tracks_state_and_vr_spacebar_sync);
harness.run("simple input plan tracks main layout availability", simple_input_plan_tracks_main_layout_availability);
return harness.finish();
}