From b311afedd2399c4dc679958bbdea018265bda77f Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 17 Jun 2026 16:26:18 +0200 Subject: [PATCH] Own Win32 startup flow in runtime layer --- docs/modernization/debt.md | 6 + docs/modernization/roadmap.md | 11 ++ docs/modernization/tasks.md | 24 +++- src/platform_windows/windows_runtime_flow.cpp | 114 ++++++++++++++++++ src/platform_windows/windows_runtime_flow.h | 2 + .../windows_runtime_shell.cpp | 79 +----------- 6 files changed, 152 insertions(+), 84 deletions(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 7698f37b..2b74edfc 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,12 @@ agent or engineer to remove them without reconstructing context from chat. ## Reductions +- 2026-06-17: `DEBT-0003` was narrowed again. + `src/platform_windows/windows_runtime_flow.*` now owns the live Win32 + startup/session composition flow, including the bound app/session preflight + and the existing `convert` / `-vrmode` mode switch, so + `src/platform_windows/windows_runtime_shell.cpp` is down to a thin entry + wrapper and no longer repeats manual app/session teardown on each exit path. - 2026-06-17: `DEBT-0017` was narrowed again. The orphaned `src/platform_legacy/legacy_platform_services.*` shim and its `legacy_platform_fallback_behavior.h` helper were deleted after the root app, diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 3926892a..6c6803bc 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -70,6 +70,17 @@ What is already real: - `pp_app_core` Latest slice: +- `src/platform_windows/windows_runtime_flow.*` now owns the live Win32 + composition-edge startup flow instead of leaving that dense startup/session + body inside `src/platform_windows/windows_runtime_shell.cpp`. +- The new bound runtime-flow owner now binds the live `MainWindowSession`, + performs the Win32 startup preflight (`initLog`, DPI/shcore, stylus init, + runtime data dir, retained input setup, exception handler, WMI probe, and + `App::create()`), handles the existing `convert` / `-vrmode` mode switch, + and always tears down the bound app/session through one destructor path. +- `src/platform_windows/windows_runtime_shell.cpp` is down to a thin Windows + entry wrapper over `run_main_application_flow(...)`, so the composition edge + is smaller and the repeated bind/release exit paths are gone from the shell. - The orphaned `src/platform_legacy/legacy_platform_services.*` shim and its `src/platform_legacy/legacy_platform_fallback_behavior.h` helper are now deleted from the repo. diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 84708e7a..6bf22648 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -57,7 +57,8 @@ Completed, blocked, and superseded task history moved to now also binds directly from `src/platform_web/web_platform_services.*`, but the broader non-Windows fallback adapter still exists as generic fallback policy - - `platform_legacy` is still part of the live app shell + - the deleted `platform_legacy` shim is no longer in the root app graph, but + retained package/build compatibility edges still need cleanup - The app runtime boundary is not finished: - render/UI queues are static `App` state - app-facing detached launches are no longer the main issue; preview and @@ -66,12 +67,13 @@ Completed, blocked, and superseded task history moved to - canvas async import/export/save/open now run through an owned in-file worker, but their retained progress execution is still not a clean runtime service boundary - - the Win32 input path now binds the active `WacomTablet*` explicitly - through `windows_runtime_shell`, but that tablet binding still lives at a + - the Win32 input path now binds the active `WacomTablet*` through + `windows_runtime_state.*`, but that tablet binding still lives at a composition edge instead of a broader runtime/platform-owned controller - - the touched Win32 app/window/session queries now route through narrow - runtime-shell accessors, but the broader runtime/thread host still owns - composition-edge global state and shutdown sequencing + - the touched Win32 startup/session flow now routes through + `windows_runtime_flow.*` instead of `windows_runtime_shell.cpp`, but the + broader runtime/thread host still owns composition-edge global state and + shutdown sequencing - thread-affinity rules are enforced by convention and asserts instead of explicit runtime contracts - The UI ownership boundary is not finished: @@ -84,6 +86,16 @@ Completed, blocked, and superseded task history moved to the queue is now ordered by code movement instead. Current slice: +- `src/platform_windows/windows_runtime_flow.*` now owns the live Win32 + startup/session composition flow instead of leaving that body in + `src/platform_windows/windows_runtime_shell.cpp`. +- A bound runtime-flow owner now binds the live `MainWindowSession`, runs the + Win32 preflight startup steps, handles the existing `convert` / `-vrmode` + mode switch, and tears down the bound app/session through one destructor + path. +- `src/platform_windows/windows_runtime_shell.cpp` is down to a thin entry + wrapper over `run_main_application_flow(...)`, so the repeated app/session + teardown branches are gone from the shell. - The orphaned `src/platform_legacy/legacy_platform_services.*` shim and `src/platform_legacy/legacy_platform_fallback_behavior.h` helper are now deleted. diff --git a/src/platform_windows/windows_runtime_flow.cpp b/src/platform_windows/windows_runtime_flow.cpp index 5502ecaf..ae1d7f0c 100644 --- a/src/platform_windows/windows_runtime_flow.cpp +++ b/src/platform_windows/windows_runtime_flow.cpp @@ -2,9 +2,123 @@ #include "platform_windows/windows_runtime_flow.h" +#include "app.h" +#include "platform_windows/windows_bootstrap_helpers.h" +#include "platform_windows/windows_main_window_session.h" +#include "platform_windows/windows_platform_services.h" +#include "platform_windows/windows_runtime_state.h" +#include "platform_windows/windows_stylus_input.h" #include "platform_windows/windows_runtime_session.h" +#include "platform_windows/windows_window_shell.h" namespace pp::platform::windows { +namespace { + +struct BoundWindowsRuntimeFlow final { + explicit BoundWindowsRuntimeFlow(HINSTANCE instance_handle) + : splash(instance_handle), + app(initialize_bound_app_runtime()) + { + bind_main_window_session(&session); + + app.set_platform_services(&pp::platform::windows::platform_services()); + app.initLog(); + + pp::platform::windows::init_shcore_API(); + pp::platform::windows::initialize_stylus_input(); + + if (pp::platform::windows::SetProcessDpiAwareness_fn) + pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE); + + pp::platform::windows::ensure_runtime_data_directory(); + pp::platform::windows::initialize_retained_input_state(); + pp::platform::windows::setup_exception_handler(app); + pp::platform::windows::read_WMI_info(); + + app.create(); + } + + ~BoundWindowsRuntimeFlow() + { + release_bound_app(); + bind_main_window_session(nullptr); + } + + BoundWindowsRuntimeFlow(const BoundWindowsRuntimeFlow&) = delete; + BoundWindowsRuntimeFlow& operator=(const BoundWindowsRuntimeFlow&) = delete; + + MainWindowSession session{}; + SplashScreen splash; + App& app; +}; + +[[nodiscard]] int failure_exit_code(MainStartupResult result) noexcept +{ + switch (result) + { + case MainStartupResult::Ok: + return 0; + case MainStartupResult::GladLoadFailure: + return 0; + case MainStartupResult::MissingCoreContextSupport: + return -1; + } + + return -1; +} + +[[nodiscard]] bool handle_runtime_mode( + App& app, + int argc, + char** argv, + bool& start_in_vr) +{ + if (argc <= 1) + return false; + + switch (const_hash(argv[1])) + { + case const_hash("convert"): + app.initShaders(); + app.cmd_convert(argv[2], argv[3]); + return true; + case const_hash("-vrmode"): + start_in_vr = true; + return false; + default: + return false; + } +} + +} + +int run_main_application_flow(int argc, char** argv) +{ + const auto instance = GetModuleHandle(NULL); + auto runtime = BoundWindowsRuntimeFlow { instance }; + + auto startup = pp::platform::windows::initialize_main_window_startup_state(runtime.app); + auto context = pp::platform::windows::OpenGlWindowContext {}; + const auto startup_result = pp::platform::windows::initialize_main_window_and_gl( + startup, + runtime.session, + instance, + context); + if (startup_result != pp::platform::windows::MainStartupResult::Ok) + return failure_exit_code(startup_result); + + bool start_in_vr = false; + if (handle_runtime_mode(runtime.app, argc, argv, start_in_vr)) + return 0; + + pp::platform::windows::run_bound_main_window_runtime( + startup, + runtime.session, + start_in_vr, + instance, + runtime.splash); + return 0; +} void run_bound_main_window_runtime( const MainWindowStartupState& startup, diff --git a/src/platform_windows/windows_runtime_flow.h b/src/platform_windows/windows_runtime_flow.h index b84638ea..e9d53985 100644 --- a/src/platform_windows/windows_runtime_flow.h +++ b/src/platform_windows/windows_runtime_flow.h @@ -6,6 +6,8 @@ namespace pp::platform::windows { +int run_main_application_flow(int argc, char** argv); + void run_bound_main_window_runtime( const MainWindowStartupState& startup, MainWindowSession& session, diff --git a/src/platform_windows/windows_runtime_shell.cpp b/src/platform_windows/windows_runtime_shell.cpp index 022a3097..afa0431e 100644 --- a/src/platform_windows/windows_runtime_shell.cpp +++ b/src/platform_windows/windows_runtime_shell.cpp @@ -2,90 +2,13 @@ #include "platform_windows/windows_runtime_shell.h" -#include "app.h" -#include "platform_windows/windows_bootstrap_helpers.h" -#include "platform_windows/windows_main_window_session.h" -#include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_runtime_flow.h" -#include "platform_windows/windows_runtime_state.h" -#include "platform_windows/windows_stylus_input.h" -#include "platform_windows/windows_window_shell.h" namespace pp::platform::windows { int run_main_application(int argc, char** argv) { - const auto instance = GetModuleHandle(NULL); - auto session = MainWindowSession {}; - bind_main_window_session(&session); - - auto& app = initialize_bound_app_runtime(); - app.set_platform_services(&pp::platform::windows::platform_services()); - app.initLog(); - - pp::platform::windows::init_shcore_API(); - pp::platform::windows::initialize_stylus_input(); - - if (pp::platform::windows::SetProcessDpiAwareness_fn) - pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE); - - pp::platform::windows::ensure_runtime_data_directory(); - - pp::platform::windows::SplashScreen splash(instance); - - pp::platform::windows::initialize_retained_input_state(); - - pp::platform::windows::setup_exception_handler(app); - - pp::platform::windows::read_WMI_info(); - - app.create(); - - auto startup = pp::platform::windows::initialize_main_window_startup_state(app); - auto context = pp::platform::windows::OpenGlWindowContext {}; - switch (pp::platform::windows::initialize_main_window_and_gl( - startup, - session, - instance, - context)) - { - case pp::platform::windows::MainStartupResult::Ok: - break; - case pp::platform::windows::MainStartupResult::GladLoadFailure: - release_bound_app(); - bind_main_window_session(nullptr); - return 0; - case pp::platform::windows::MainStartupResult::MissingCoreContextSupport: - release_bound_app(); - bind_main_window_session(nullptr); - return -1; - } - - //wglSwapIntervalEXT(1); - - bool start_in_vr = false; - if (argc > 1) - { - switch (const_hash(argv[1])) - { - case const_hash("convert"): - app.initShaders(); - app.cmd_convert(argv[2], argv[3]); - release_bound_app(); - bind_main_window_session(nullptr); - return 0; - case const_hash("-vrmode"): - start_in_vr = true; - break; - default: - break; - } - } - - pp::platform::windows::run_bound_main_window_runtime(startup, session, start_in_vr, instance, splash); - release_bound_app(); - bind_main_window_session(nullptr); - return 0; + return run_main_application_flow(argc, argv); } }