Move Windows bootstrap off App::I

This commit is contained in:
2026-06-17 07:52:35 +02:00
parent 5c8a87faa0
commit 3930e70817
6 changed files with 90 additions and 72 deletions

View File

@@ -92,6 +92,13 @@ Current hotspot files:
Latest slice:
- The remaining dense Windows bootstrap singleton pocket moved off
`App::I`: `setup_exception_handler(...)`, `initialize_main_window_startup_state(...)`,
and `_pre_call_callback(...)` now use explicit app/bound-runtime state
instead of reading the app singleton directly in
`src/platform_windows/windows_bootstrap_helpers.*`, and the app-side
platform dispatch helpers in `src/app_events.cpp` now also use the
instance they are invoked on instead of a global `App::I` fallback.
- The retained Web fallback service object and the Apple storage-path
preparation helper now also live in
`src/platform_legacy/legacy_platform_state.*` instead of being built inline

View File

@@ -1202,6 +1202,13 @@ Why now:
platform-handle state on `App`, which blocks a real `pp_platform_*` shell split.
Current slice:
- The remaining dense Windows bootstrap singleton pocket moved off
`App::I`: `setup_exception_handler(...)`,
`initialize_main_window_startup_state(...)`, and `_pre_call_callback(...)`
now use explicit app/bound-runtime state in
`src/platform_windows/windows_bootstrap_helpers.*`, and
`src/app_events.cpp` now dispatches platform services through the
`App` instance it is operating on instead of a global fallback.
- The retained Web fallback service object and the Apple storage-path
preparation helper now also live in
`src/platform_legacy/legacy_platform_state.*` instead of being built inline

View File

@@ -46,11 +46,11 @@ namespace {
namespace {
[[nodiscard]] pp::platform::PlatformServices& active_platform_services()
[[nodiscard]] pp::platform::PlatformServices& active_platform_services(const App* app)
{
if (App::I)
if (app)
{
if (auto* services = App::I->platform_services())
if (auto* services = app->platform_services())
return *services;
}
return pp::platform::legacy::platform_services();
@@ -87,7 +87,7 @@ pp::platform::PlatformServices* App::platform_services() const noexcept
pp::platform::PlatformStoragePaths App::prepare_storage_paths()
{
return active_platform_services().prepare_storage_paths();
return active_platform_services(this).prepare_storage_paths();
}
std::string App::clipboard_get_text()
@@ -95,7 +95,7 @@ std::string App::clipboard_get_text()
if (pp::app::plan_clipboard_read() != pp::app::ClipboardReadAction::read_text)
return {};
return active_platform_services().clipboard_text();
return active_platform_services(this).clipboard_text();
}
bool App::clipboard_set_text(const std::string& s)
@@ -103,17 +103,17 @@ bool App::clipboard_set_text(const std::string& s)
if (pp::app::plan_clipboard_write(s) != pp::app::ClipboardWriteAction::write_text)
return false;
return active_platform_services().set_clipboard_text(s);
return active_platform_services(this).set_clipboard_text(s);
}
void App::stacktrace()
{
active_platform_services().log_stacktrace();
active_platform_services(this).log_stacktrace();
}
void App::crash_test()
{
active_platform_services().trigger_crash_test();
active_platform_services(this).trigger_crash_test();
}
void App::tick(float dt)
@@ -154,7 +154,7 @@ void App::show_cursor()
if (!should_dispatch_cursor_visibility(true))
return;
active_platform_services().set_cursor_visible(true);
active_platform_services(this).set_cursor_visible(true);
}
void App::hide_cursor()
@@ -162,7 +162,7 @@ void App::hide_cursor()
if (!should_dispatch_cursor_visibility(false))
return;
active_platform_services().set_cursor_visible(false);
active_platform_services(this).set_cursor_visible(false);
}
void App::showKeyboard()
@@ -172,7 +172,7 @@ void App::showKeyboard()
if (!should_dispatch_keyboard_visibility(true))
return;
active_platform_services().set_virtual_keyboard_visible(true);
active_platform_services(this).set_virtual_keyboard_visible(true);
}
void App::hideKeyboard()
@@ -182,26 +182,26 @@ void App::hideKeyboard()
if (!should_dispatch_keyboard_visibility(false))
return;
active_platform_services().set_virtual_keyboard_visible(false);
active_platform_services(this).set_virtual_keyboard_visible(false);
}
void App::pick_image(std::function<void(std::string path)> callback)
{
redraw = true;
active_platform_services().pick_image(std::move(callback));
active_platform_services(this).pick_image(std::move(callback));
}
void App::pick_file(std::vector<std::string> types, std::function<void (std::string)> callback)
{
redraw = true;
active_platform_services().pick_file(std::move(types), std::move(callback));
active_platform_services(this).pick_file(std::move(types), std::move(callback));
}
void App::pick_file_save(const std::string& type, const std::string& default_name,
std::function<void(std::string)> writer, std::function<void(const std::string& path, bool saved)> callback)
{
redraw = true;
const auto target = active_platform_services().prepare_writable_file(type, default_name, data_path, tmp_path);
const auto target = active_platform_services(this).prepare_writable_file(type, default_name, data_path, tmp_path);
if (target.path.empty())
{
callback({}, false);
@@ -239,47 +239,47 @@ void App::pick_file_save(const std::string& type, const std::string& default_nam
void App::pick_file_save(std::vector<std::string> types, std::function<void(std::string)> callback)
{
redraw = true;
active_platform_services().pick_save_file(std::move(types), std::move(callback));
active_platform_services(this).pick_save_file(std::move(types), std::move(callback));
}
bool App::uses_prepared_file_writes() const
{
return active_platform_services().uses_prepared_file_writes();
return active_platform_services(this).uses_prepared_file_writes();
}
bool App::uses_work_directory_document_export_collections() const
{
return active_platform_services().uses_work_directory_document_export_collections();
return active_platform_services(this).uses_work_directory_document_export_collections();
}
bool App::disables_network_tls_verification() const
{
return active_platform_services().disables_network_tls_verification();
return active_platform_services(this).disables_network_tls_verification();
}
bool App::uses_ppbr_export_data_directory_override() const
{
return active_platform_services().uses_ppbr_export_data_directory_override();
return active_platform_services(this).uses_ppbr_export_data_directory_override();
}
bool App::platform_supports_sonarpen() const
{
return active_platform_services().supports_sonarpen();
return active_platform_services(this).supports_sonarpen();
}
void App::start_platform_sonarpen()
{
active_platform_services().start_sonarpen();
active_platform_services(this).start_sonarpen();
}
int App::default_canvas_resolution() const
{
return active_platform_services().default_canvas_resolution();
return active_platform_services(this).default_canvas_resolution();
}
bool App::draws_canvas_tip_for_input(kEventSource source, kEventType type) const
{
return active_platform_services().draws_canvas_tip_for_pointer(
return active_platform_services(this).draws_canvas_tip_for_pointer(
source == kEventSource::Mouse,
source == kEventSource::Stylus,
type == kEventType::MouseUpL);
@@ -287,23 +287,23 @@ bool App::draws_canvas_tip_for_input(kEventSource source, kEventType type) const
float App::adjust_canvas_input_pressure(float pressure) const
{
return active_platform_services().adjust_canvas_input_pressure(pressure);
return active_platform_services(this).adjust_canvas_input_pressure(pressure);
}
void App::pick_dir(std::function<void(std::string path)> callback)
{
redraw = true;
active_platform_services().pick_directory(std::move(callback));
active_platform_services(this).pick_directory(std::move(callback));
}
bool App::supports_working_directory_picker() const
{
return active_platform_services().supports_working_directory_picker();
return active_platform_services(this).supports_working_directory_picker();
}
std::string App::format_working_directory_path(std::string_view path) const
{
return active_platform_services().format_working_directory_path(path);
return active_platform_services(this).format_working_directory_path(path);
}
void App::display_file(std::string path)
@@ -311,7 +311,7 @@ void App::display_file(std::string path)
if (pp::app::plan_display_file(path) == pp::app::DisplayFileAction::ignore_empty_path)
return;
active_platform_services().display_file(path);
active_platform_services(this).display_file(path);
}
void App::share_file(std::string path)
@@ -322,122 +322,122 @@ void App::share_file(std::string path)
message_box("Sharing failed", "Please save the document before sharing it.");
return;
}
active_platform_services().share_file(path);
active_platform_services(this).share_file(path);
}
void App::request_app_close()
{
active_platform_services().request_app_close();
active_platform_services(this).request_app_close();
}
bool App::start_platform_vr_mode()
{
return active_platform_services().start_vr_mode();
return active_platform_services(this).start_vr_mode();
}
void App::stop_platform_vr_mode()
{
active_platform_services().stop_vr_mode();
active_platform_services(this).stop_vr_mode();
}
void App::attach_ui_thread()
{
active_platform_services().attach_ui_thread();
active_platform_services(this).attach_ui_thread();
}
void App::detach_ui_thread()
{
active_platform_services().detach_ui_thread();
active_platform_services(this).detach_ui_thread();
}
void App::acquire_render_context()
{
active_platform_services().acquire_render_context();
active_platform_services(this).acquire_render_context();
}
void App::release_render_context()
{
active_platform_services().release_render_context();
active_platform_services(this).release_render_context();
}
void App::present_render_context()
{
active_platform_services().present_render_context();
active_platform_services(this).present_render_context();
}
void App::bind_default_render_target()
{
active_platform_services().bind_default_render_target();
active_platform_services(this).bind_default_render_target();
}
void App::bind_main_render_target()
{
active_platform_services().bind_main_render_target();
active_platform_services(this).bind_main_render_target();
}
void App::apply_render_platform_hints()
{
active_platform_services().apply_render_platform_hints();
active_platform_services(this).apply_render_platform_hints();
}
void App::install_render_debug_callback()
{
active_platform_services().install_render_debug_callback();
active_platform_services(this).install_render_debug_callback();
}
void App::begin_render_capture_frame()
{
active_platform_services().begin_render_capture_frame();
active_platform_services(this).begin_render_capture_frame();
}
void App::end_render_capture_frame()
{
active_platform_services().end_render_capture_frame();
active_platform_services(this).end_render_capture_frame();
}
bool App::platform_deletes_recorded_files_on_clear()
{
return active_platform_services().deletes_recorded_files_on_clear();
return active_platform_services(this).deletes_recorded_files_on_clear();
}
void App::clear_platform_recorded_files(std::string path)
{
active_platform_services().clear_recorded_files(path);
active_platform_services(this).clear_recorded_files(path);
}
void App::publish_exported_image(std::string path)
{
active_platform_services().publish_exported_image(path);
active_platform_services(this).publish_exported_image(path);
}
void App::flush_platform_storage()
{
active_platform_services().flush_persistent_storage();
active_platform_services(this).flush_persistent_storage();
}
std::vector<std::string> App::document_browse_roots() const
{
return active_platform_services().document_browse_roots(work_path, data_path);
return active_platform_services(this).document_browse_roots(work_path, data_path);
}
void App::save_platform_ui_state()
{
active_platform_services().save_ui_state();
active_platform_services(this).save_ui_state();
}
bool App::platform_enables_live_asset_reloading()
{
return active_platform_services().enables_live_asset_reloading();
return active_platform_services(this).enables_live_asset_reloading();
}
void App::update_platform_frame(float delta_time_seconds)
{
active_platform_services().update_platform_frame(delta_time_seconds);
active_platform_services(this).update_platform_frame(delta_time_seconds);
}
void App::report_rendered_frames(int frames)
{
active_platform_services().report_rendered_frames(frames);
active_platform_services(this).report_rendered_frames(frames);
}
VrSessionSnapshot App::vr_session_snapshot() const
@@ -454,7 +454,7 @@ void App::save_prepared_file(
std::string suggested_name,
std::function<void(const std::string& path, bool saved)> callback)
{
active_platform_services().save_prepared_file(
active_platform_services(this).save_prepared_file(
path,
suggested_name,
[callback = std::move(callback)](std::string saved_path, bool saved) {

View File

@@ -25,6 +25,7 @@
namespace pp::platform::windows {
void set_async_render_context(HDC hdc, HGLRC hrc);
App* bound_app() noexcept;
}
namespace pp::platform::windows {
@@ -130,7 +131,7 @@ int run_winmain_entry(int (*entry_point)(int, char**))
return entry_point(argc, argv);
}
void setup_exception_handler()
void setup_exception_handler(const App& app)
{
// Setup exception handler
BT_SetAppName(_T("PanoPainter"));
@@ -155,11 +156,12 @@ void setup_exception_handler()
// Add custom log file using default name
TCHAR wpath[MAX_PATH];
//GetFullPathNameW(L"panopainter-log.txt", 1024, wpath, nullptr);
auto log_file = App::I->data_path + "/panopainter-log.txt";
auto log_file = app.data_path + "/panopainter-log.txt";
std::mbstowcs(wpath, log_file.c_str(), log_file.size());
BT_AddLogFile(wpath);
BT_SetPreErrHandler([](INT_PTR){
BT_SetPreErrHandler([](INT_PTR nErrHandlerParam){
const auto* app = reinterpret_cast<const App*>(nErrHandlerParam);
if (Canvas::I && Canvas::I->m_unsaved)
{
auto t = std::time(nullptr);
@@ -167,7 +169,7 @@ void setup_exception_handler()
std::ostringstream oss;
oss << std::put_time(&tm, "%d-%m-%Y %H-%M-%S");
auto path = App::I->data_path + "/" + App::I->doc_name + "-recovery (" + oss.str() + ").ppi";
auto path = app->data_path + "/" + app->doc_name + "-recovery (" + oss.str() + ").ppi";
Canvas::I->project_save_thread(path, false);
static char abspath[MAX_PATH];
GetFullPathNameA(path.c_str(), MAX_PATH, abspath, NULL);
@@ -176,7 +178,7 @@ void setup_exception_handler()
MessageBoxA(retained_state().hWnd, message, "File Recovery", MB_OK | MB_ICONWARNING);
}
LogRemote::I.file_close();
}, 0);
}, reinterpret_cast<INT_PTR>(&app));
BT_SetTerminate();
}
@@ -373,7 +375,7 @@ int read_WMI_info()
return 0;
}
MainWindowStartupState initialize_main_window_startup_state()
MainWindowStartupState initialize_main_window_startup_state(App& app)
{
auto startup = MainWindowStartupState {};
const auto hInst = GetModuleHandle(NULL);
@@ -392,26 +394,26 @@ MainWindowStartupState initialize_main_window_startup_state()
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
App::I->display_density = (float)x / 96.f;
app.display_density = (float)x / 96.f;
const auto window_preferences = pp::panopainter::read_legacy_window_preferences(SW_NORMAL);
if (window_preferences.has_ui_scale)
App::I->zoom = window_preferences.ui_scale;
app.zoom = window_preferences.ui_scale;
else
App::I->zoom = (float)x / 96.f;
app.zoom = (float)x / 96.f;
startup.show_command = window_preferences.show_command;
startup.client_rect = {
0,
0,
static_cast<LONG>(App::I->width * App::I->zoom),
static_cast<LONG>(App::I->height * App::I->zoom),
static_cast<LONG>(app.width * app.zoom),
static_cast<LONG>(app.height * app.zoom),
};
if (window_preferences.has_window_rect)
{
auto wnd_rect = window_preferences.window_rect;
App::I->width = wnd_rect.z - wnd_rect.x;
App::I->height = wnd_rect.w - wnd_rect.y;
app.width = wnd_rect.z - wnd_rect.x;
app.height = wnd_rect.w - wnd_rect.y;
startup.client_rect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
startup.client_pos = { wnd_rect.x, wnd_rect.y };
}
@@ -577,7 +579,7 @@ BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...)
{
assert(App::I->is_render_thread());
assert(bound_app()->is_render_thread());
}
void _post_call_callback(const char* name, void* funcptr, int len_args, ...)

View File

@@ -7,6 +7,8 @@
#include "renderer_gl/opengl_capabilities.h"
class App;
namespace pp::platform::windows {
bool win32_renderdoc_init();
@@ -47,9 +49,9 @@ enum class MainStartupResult
};
void ensure_runtime_data_directory();
void setup_exception_handler();
void setup_exception_handler(const App& app);
int run_winmain_entry(int (*entry_point)(int, char**));
MainWindowStartupState initialize_main_window_startup_state();
MainWindowStartupState initialize_main_window_startup_state(App& app);
void create_main_window(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title);
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format);
bool load_glad_entry_points(HDC device_context);

View File

@@ -161,13 +161,13 @@ int run_main_application(int argc, char** argv)
pp::platform::windows::initialize_retained_input_state();
pp::platform::windows::setup_exception_handler();
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();
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, state.hWnd, state.hInst, state.window_title, context))
{