diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 20d03de3..783be0c8 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -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 diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 39aa34e9..5cd65833 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -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 diff --git a/src/app_events.cpp b/src/app_events.cpp index b674b04c..ae6b0bb2 100644 --- a/src/app_events.cpp +++ b/src/app_events.cpp @@ -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 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 types, std::function 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 writer, std::function 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 types, std::function 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 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 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 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) { diff --git a/src/platform_windows/windows_bootstrap_helpers.cpp b/src/platform_windows/windows_bootstrap_helpers.cpp index f1653137..71c0ddec 100644 --- a/src/platform_windows/windows_bootstrap_helpers.cpp +++ b/src/platform_windows/windows_bootstrap_helpers.cpp @@ -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(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(&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(App::I->width * App::I->zoom), - static_cast(App::I->height * App::I->zoom), + static_cast(app.width * app.zoom), + static_cast(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, ...) diff --git a/src/platform_windows/windows_bootstrap_helpers.h b/src/platform_windows/windows_bootstrap_helpers.h index 67df88c0..cfddeda6 100644 --- a/src/platform_windows/windows_bootstrap_helpers.h +++ b/src/platform_windows/windows_bootstrap_helpers.h @@ -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); diff --git a/src/platform_windows/windows_runtime_shell.cpp b/src/platform_windows/windows_runtime_shell.cpp index 8584ffed..58ee8fc7 100644 --- a/src/platform_windows/windows_runtime_shell.cpp +++ b/src/platform_windows/windows_runtime_shell.cpp @@ -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)) {