#include "pch.h" #include "platform_legacy/legacy_platform_services.h" #include "platform_legacy/legacy_platform_state.h" #include "legacy_ui_gl_dispatch.h" #include "log.h" #include "platform_apple/apple_platform_services.h" #include "platform_api/network_tls_policy.h" #include "platform_api/platform_policy.h" #include "renderer_gl/opengl_capabilities.h" #ifdef __ANDROID__ #include "main.h" void displayKeyboard(bool pShow); void android_async_lock(); void android_async_swap(); void android_async_unlock(); void android_attach_jni(); void android_detach_jni(); void android_pick_file(std::function callback); void android_pick_file_save(std::function callback); std::string android_get_clipboard(); bool android_set_clipboard(const std::string& s); #elif __APPLE__ #include void delete_all_files_in_path(const std::string& source_path); #ifdef __IOS__ void save_image_library(const std::string& path); #endif #elif __LINUX__ #include #include "platform_linux/linux_platform_services.h" std::string linux_home_path(); int mkpath(const std::string& dir, mode_t mode = DEFFILEMODE); #elif __WEB__ void webgl_pick_file(std::function callback); void webgl_pick_file_save( const std::string& path, const std::string& name, std::function callback); void webgl_sync(); #endif namespace { // DEBT-0017: fallback for platforms that do not inject PlatformServices yet. class LegacyPlatformServices final : public pp::platform::PlatformServices { public: [[nodiscard]] pp::platform::PlatformStoragePaths prepare_storage_paths() override { #if defined(__IOS__) return pp::platform::apple::prepare_legacy_apple_storage_paths(); #elif defined(__OSX__) return pp::platform::apple::prepare_legacy_apple_storage_paths(); #elif __LINUX__ const std::string data_path = linux_home_path() + "/PanoPainter"; mkpath(data_path + "/brushes"); mkpath(data_path + "/brushes/thumbs"); mkpath(data_path + "/patterns"); mkpath(data_path + "/patterns/thumbs"); mkpath(data_path + "/settings"); mkpath(data_path + "/frames"); return { data_path, data_path, data_path + "/frames", {}, }; #elif __WEB__ const std::string data_path = "/PanoPainter"; mkdir(data_path.c_str(), 0777); mkdir((data_path + "/brushes").c_str(), 0777); mkdir((data_path + "/brushes/thumbs").c_str(), 0777); mkdir((data_path + "/patterns").c_str(), 0777); mkdir((data_path + "/patterns/thumbs").c_str(), 0777); mkdir((data_path + "/settings").c_str(), 0777); mkdir((data_path + "/frames").c_str(), 0777); return { data_path, data_path, data_path + "/frames", {}, }; #else return pp::platform::legacy::active_legacy_storage_paths(); #endif } void log_stacktrace() override { #if defined(__OSX__) NSString* callstack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; LOG("callstack:\n%s", [callstack cStringUsingEncoding:NSUTF8StringEncoding]); #endif } void trigger_crash_test() override { #ifdef __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().trigger_crash_test(); #elif __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().trigger_crash_test(); #elif defined(__ANDROID__) int *x = nullptr; *x = 42; LOG("%d", *x); #endif } [[nodiscard]] std::string clipboard_text() override { #if defined(__IOS__) || defined(__OSX__) const auto family = pp::platform::current_platform_family(); if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos) return pp::platform::apple::active_legacy_apple_document_platform_services().clipboard_text(); #endif #ifdef __ANDROID__ return android_get_clipboard(); #else return {}; #endif } [[nodiscard]] bool set_clipboard_text(std::string_view text) override { #if defined(__IOS__) || defined(__OSX__) const auto family = pp::platform::current_platform_family(); if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos) return pp::platform::apple::active_legacy_apple_document_platform_services().set_clipboard_text(text); #endif const std::string value(text); #ifdef __ANDROID__ return android_set_clipboard(value); #else (void)value; return false; #endif } void set_cursor_visible(bool visible) override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().set_cursor_visible(visible); #else (void)visible; #endif } void set_virtual_keyboard_visible(bool visible) override { #ifdef __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().set_virtual_keyboard_visible(visible); #elif __ANDROID__ displayKeyboard(visible); #else (void)visible; #endif } void attach_ui_thread() override { #ifdef __ANDROID__ android_attach_jni(); #endif } void detach_ui_thread() override { #ifdef __ANDROID__ android_detach_jni(); #endif } void acquire_render_context() override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().acquire_render_context(); #elif __ANDROID__ android_async_lock(); #elif __LINUX__ || __WEB__ pp::platform::legacy::acquire_legacy_glfw_render_context(); #endif } void release_render_context() override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().release_render_context(); #elif __ANDROID__ android_async_unlock(); #endif } void present_render_context() override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().present_render_context(); #elif __ANDROID__ android_async_swap(); #elif __LINUX__ || __WEB__ pp::platform::legacy::present_legacy_glfw_render_context(); #endif } void bind_default_render_target() override { pp::legacy::ui_gl::bind_opengl_framebuffer( pp::renderer::gl::framebuffer_target(), pp::renderer::gl::default_framebuffer_id()); } void bind_main_render_target() override { #if __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().bind_main_render_target(); #else bind_default_render_target(); #endif } void apply_render_platform_hints() override { #if defined(__OSX__) const auto status = pp::renderer::gl::apply_opengl_render_platform_hints( pp::renderer::gl::OpenGlRenderPlatformHintDispatch { .enable = pp::legacy::ui_gl::enable_opengl_state, }); if (!status.ok()) LOG("OpenGL legacy render platform hints failed: %s", status.message); #endif } void install_render_debug_callback() override { } void begin_render_capture_frame() override { } void end_render_capture_frame() override { } [[nodiscard]] bool deletes_recorded_files_on_clear() override { return pp::platform::platform_deletes_recorded_files_on_clear( pp::platform::current_platform_family()); } void clear_recorded_files(std::string_view recording_path) override { #if defined(__IOS__) || defined(__OSX__) delete_all_files_in_path(std::string(recording_path)); #else (void)recording_path; #endif } void publish_exported_image(std::string_view path) override { const auto family = pp::platform::current_platform_family(); if (pp::platform::legacy::handles_legacy_web_platform_family(family)) { pp::platform::legacy::publish_legacy_web_exported_image(path); return; } if (!pp::platform::platform_publishes_exported_images(family)) { (void)path; return; } #ifdef __IOS__ save_image_library(std::string(path)); #else (void)path; #endif } void flush_persistent_storage() override { const auto family = pp::platform::current_platform_family(); if (pp::platform::legacy::handles_legacy_web_platform_family(family)) { pp::platform::legacy::flush_legacy_web_persistent_storage(); return; } if (!pp::platform::platform_flushes_persistent_storage(family)) return; } [[nodiscard]] std::vector document_browse_roots( std::string_view work_path, std::string_view data_path) override { #if defined(__IOS__) || defined(__OSX__) return pp::platform::apple::active_legacy_apple_document_platform_services().document_browse_roots(work_path, data_path); #else return pp::platform::platform_document_browse_roots( pp::platform::current_platform_family(), work_path, data_path); #endif } void save_ui_state() override { if (!pp::platform::platform_saves_native_ui_state(pp::platform::current_platform_family())) return; #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().save_ui_state(); #endif } [[nodiscard]] bool enables_live_asset_reloading() override { return pp::platform::platform_enables_live_asset_reloading( pp::platform::current_platform_family()); } void update_platform_frame(float delta_time_seconds) override { (void)delta_time_seconds; } void report_rendered_frames(int frames) override { #ifdef __LINUX__ pp::platform::linux_desktop::report_rendered_frames(frames); #else (void)frames; #endif } void pick_image(pp::platform::PickedPathCallback callback) override { #ifdef __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_image(std::move(callback)); #elif __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_image(std::move(callback)); #elif __ANDROID__ android_pick_file(callback); #elif __LINUX__ if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false)) invoke_picked_path_if_selected(p, callback); #elif __WEB__ webgl_pick_file(callback); #else (void)callback; #endif } void pick_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { #ifdef __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback)); #elif __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback)); #elif __ANDROID__ android_pick_file(callback); #elif __LINUX__ if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false)) invoke_picked_path_if_selected(p, callback); #elif __WEB__ webgl_pick_file(callback); #else (void)file_types; (void)callback; #endif } void pick_save_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { #if __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_save_file(std::move(file_types), std::move(callback)); #elif __ANDROID__ android_pick_file_save(callback); #else (void)file_types; (void)callback; #endif } void pick_directory(pp::platform::PickedPathCallback callback) override { #ifdef __IOS__ (void)callback; #elif __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().pick_directory(std::move(callback)); #elif __ANDROID__ (void)callback; #else (void)callback; #endif } [[nodiscard]] bool supports_working_directory_picker() override { #if defined(__IOS__) || defined(__OSX__) return pp::platform::apple::active_legacy_apple_document_platform_services().supports_working_directory_picker(); #else return pp::platform::platform_supports_working_directory_picker( pp::platform::current_platform_family()); #endif } [[nodiscard]] std::string format_working_directory_path(std::string_view path) override { #if defined(__IOS__) || defined(__OSX__) return pp::platform::apple::active_legacy_apple_document_platform_services().format_working_directory_path(path); #endif return std::string(path); } [[nodiscard]] bool uses_prepared_file_writes() override { return pp::platform::platform_uses_prepared_file_writes( pp::platform::current_platform_family()); } [[nodiscard]] bool uses_work_directory_document_export_collections() override { return pp::platform::platform_uses_work_directory_document_export_collections( pp::platform::current_platform_family()); } [[nodiscard]] bool disables_network_tls_verification() override { return pp::platform::default_disables_network_tls_verification(); } [[nodiscard]] bool uses_ppbr_export_data_directory_override() override { return pp::platform::platform_uses_ppbr_export_data_directory_override( pp::platform::current_platform_family()); } [[nodiscard]] bool supports_sonarpen() override { return pp::platform::platform_supports_sonarpen(pp::platform::current_platform_family()); } void start_sonarpen() override { #if __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().start_sonarpen(); #endif } [[nodiscard]] int default_canvas_resolution() override { const auto family = pp::platform::current_platform_family(); if (pp::platform::legacy::handles_legacy_web_platform_family(family)) return pp::platform::legacy::default_legacy_web_canvas_resolution(); return pp::platform::platform_default_canvas_resolution(family); } [[nodiscard]] bool draws_canvas_tip_for_pointer( bool is_mouse, bool is_stylus, bool is_left_button_release) override { return pp::platform::platform_draws_canvas_tip_for_pointer( pp::platform::current_platform_family(), is_mouse, is_stylus, is_left_button_release); } [[nodiscard]] float adjust_canvas_input_pressure(float pressure) override { return pressure; } [[nodiscard]] pp::platform::PreparedFileTarget prepare_writable_file( std::string_view type, std::string_view default_name, std::string_view data_path, std::string_view temporary_path) override { return pp::platform::plan_platform_writable_file( pp::platform::current_platform_family(), type, default_name, data_path, temporary_path); } void display_file(std::string_view path) override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().display_file(path); #else (void)path; #endif } void share_file(std::string_view path) override { #if defined(__IOS__) || defined(__OSX__) pp::platform::apple::active_legacy_apple_document_platform_services().share_file(path); #else (void)path; #endif } void request_app_close() override { #ifdef __OSX__ pp::platform::apple::active_legacy_apple_document_platform_services().request_app_close(); #elif __LINUX__ pp::platform::legacy::request_legacy_glfw_app_close(); #endif } [[nodiscard]] bool start_vr_mode() override { return false; } void stop_vr_mode() override { } void save_prepared_file( std::string_view path, std::string_view suggested_name, pp::platform::PreparedFileCallback callback) override { const auto family = pp::platform::current_platform_family(); if (pp::platform::legacy::handles_legacy_web_platform_family(family)) { pp::platform::legacy::save_legacy_web_prepared_file(path, suggested_name, std::move(callback)); return; } const std::string value(path); const std::string name(suggested_name); #ifdef __IOS__ pp::platform::apple::active_legacy_apple_document_platform_services().save_prepared_file( value, name, std::move(callback)); #else (void)name; callback(value, false); #endif } }; } namespace pp::platform::legacy { PlatformServices& platform_services() { static LegacyPlatformServices services; return services; } }