diff --git a/CMakeLists.txt b/CMakeLists.txt index c5ef26c5..f8912d47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,6 +286,18 @@ target_link_libraries(pp_platform_linux PRIVATE pp_project_warnings) +add_library(pp_platform_android STATIC + ${PP_PLATFORM_ANDROID_SOURCES}) +target_include_directories(pp_platform_android + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/src") +target_link_libraries(pp_platform_android + PUBLIC + pp_platform_api + pp_project_options + PRIVATE + pp_project_warnings) + add_library(pp_app_core STATIC src/app_core/about_menu.h src/app_core/app_dialog.h diff --git a/android/src/cpp/main.cpp b/android/src/cpp/main.cpp index c2cbe2f5..41296f10 100644 --- a/android/src/cpp/main.cpp +++ b/android/src/cpp/main.cpp @@ -31,8 +31,7 @@ #include "pch.h" #include "app.h" -#include "platform_legacy/legacy_platform_services.h" -#include "platform_legacy/legacy_platform_state.h" +#include "platform_android/android_platform_services.h" #include "asset.h" #include "keymap.h" #include "main.h" @@ -1092,8 +1091,8 @@ void android_main(struct android_app* state) { // Make sure glue isn't stripped. // DON'T REMOVE, even if the compiler say it's deprecated app_dummy(); - auto platform_services = pp::platform::legacy::create_platform_services({ - .android_bridge = { + auto platform_services = pp::platform::android::create_platform_services({ + .bridge = { .clipboard_text = [] { return android_get_clipboard(); }, .set_clipboard_text = [](std::string_view text) { return android_set_clipboard(std::string(text)); @@ -1111,7 +1110,7 @@ void android_main(struct android_app* state) { android_pick_file_save(std::move(callback)); }, }, - .android_storage_paths = g_android_storage_paths, + .storage_paths = g_android_storage_paths, }); App::I = new App; diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 75a4689c..73268d2e 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -117,6 +117,11 @@ set(PP_PLATFORM_LINUX_SOURCES src/platform_linux/linux_platform_services.h ) +set(PP_PLATFORM_ANDROID_SOURCES + src/platform_android/android_platform_services.cpp + src/platform_android/android_platform_services.h +) + set(PP_PLATFORM_APPLE_SOURCES src/platform_apple/apple_platform_state.cpp src/platform_apple/apple_platform_services.cpp diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 0da41238..097d18d6 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,13 @@ agent or engineer to remove them without reconstructing context from chat. ## Reductions +- 2026-06-17: `DEBT-0016`/`DEBT-0017` were narrowed again. + `src/platform_android/android_platform_services.*` now owns the concrete + Android `PlatformServices` implementation and + `android/src/cpp/main.cpp` now binds that owned service directly, so + `src/platform_legacy/legacy_platform_services.*` no longer carries the + Android bridge/configuration surface or the touched Android execution + branches. - 2026-06-17: `DEBT-0016`/`DEBT-0017`/`DEBT-0050`/`DEBT-0051`/`DEBT-0052`/ `DEBT-0053` were narrowed again. `src/platform_apple/apple_platform_services.*` now owns the concrete Apple `PlatformServices` implementation and @@ -2397,8 +2404,8 @@ agent or engineer to remove them without reconstructing context from chat. | DEBT-0013 | Open | Modernization | `pp_assets`, `pp_document`, `pano_cli inspect-project`, `pano_cli load-project`, and `pano_cli save-project` validate the fixed PPI header, thumbnail/body byte layout, generated multi-layer/multi-frame PPI writing with explicit layer opacity/blend/alpha-lock/visibility metadata, per-layer frame durations, metadata-only and targeted dirty-face-payload save/load round-trips, layer/frame index, dirty-face descriptors, dirty-face PNG payload metadata, asset-level RGBA PNG payload decoding, pure document-to-PPI export, CLI document export automation, file-writing document export automation, stroke-script-generated document payload export, decoded pixel attachment to `pp_document`, live save-path snapshot-readiness reporting, and app-core canvas-snapshot-to-PPI export automation, but full legacy PPI round-trip parity and pure live save writer replacement are not yet extracted | Full PPI save parity requires staged extraction of legacy `Canvas` serialization and image/layer payload handling | `ctest --preset desktop-fast --build-config Debug`; `pp_assets_image_pixels_tests`; `pp_assets_ppi_header_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_inspect_project_layout_smoke`; `pano_cli_load_project_metadata_smoke`; `pano_cli_save_project_roundtrip_smoke`; `pano_cli_save_project_payload_roundtrip_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Full PPI load/save fixtures cover thumbnails, decoded layer face payloads attached to documents, frames, corrupt payloads, dirty-face payload saving, arbitrary legacy canvas payload/layout combinations, and legacy app round-trip compatibility | | DEBT-0014 | Open | Modernization | `windows-clangcl-asan` now configures as a headless Ninja/clang-cl preset and uses the release MSVC runtime required by ASan, but local builds still fail because installed clang-cl 18.1.8 is paired with VS 2026-preview STL headers that require Clang 20 or newer | Sanitizer validation should be local and repeatable, but this machine's compiler/header pairing is incompatible | `cmake --fresh --preset windows-clangcl-asan`; `cmake --build --preset windows-clangcl-asan --target pp_foundation` | Install/use Clang 20+ with the VS 2026 STL, or point the preset at a compatible VS 2022 toolchain, then make `platform-build.ps1 -Presets windows-clangcl-asan` pass for the headless matrix | | DEBT-0015 | Open | Modernization | Cursor visibility requests now consume pure `pp_app_core` planning through `pano_cli plan-cursor-visibility`, `App::show_cursor`/`App::hide_cursor` dispatch through `PlatformServices` without platform guards, and Windows live execution uses injected `WindowsPlatformServices`, but macOS cursor execution still reaches the retained fallback adapter | Keep canvas cursor behavior stable while platform shells are extracted incrementally | `pp_app_core_document_platform_io_tests`; `pano_cli plan-cursor-visibility --visible`; `ctest --preset desktop-fast --build-config Debug` | Cursor visibility execution is owned by injected `pp_platform_*` services for every supported platform | -| DEBT-0016 | Open | Modernization | Clipboard get/set requests now consume pure `pp_app_core` planning through `pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write`; Windows live execution uses injected `WindowsPlatformServices`, Apple clipboard execution now uses `src/platform_apple/apple_platform_services.*`, and Android clipboard execution still reaches the retained non-Windows fallback adapter | Keep picker/color text clipboard behavior stable while platform shells are extracted incrementally | `pp_app_core_document_platform_io_tests`; `pano_cli plan-clipboard-write --text #ff00aa`; `ctest --preset desktop-fast --build-config Debug` | Clipboard execution is owned by injected `pp_platform_*` services for every supported platform | -| DEBT-0017 | Open | Modernization | Startup storage path preparation, `App::clipboard_get_text`, `App::clipboard_set_text`, `App::show_cursor`, `App::hide_cursor`, `App::showKeyboard`, `App::hideKeyboard`, `App::display_file`, `App::share_file`, native app/window close, UI-thread lifecycle hooks, render-context acquire/release/present hooks, render-target binding hooks, render platform hint hooks, render debug callback hooks, render-capture frame hooks, recording cleanup, live asset/layout reload policy, diagnostic stacktrace/crash hooks, per-frame platform hooks, `App::pick_image`, `App::pick_file`, the non-writer `App::pick_file_save`, `App::pick_dir`, working-directory picker/display-path policy, canvas input tip/pressure policy, prepared-file save/download handoff, work-directory document export collection policy, app network TLS verification policy, PPBR export data-directory policy, SonarPen availability/startup, and VR mode start/stop now call the SDK-free `pp::platform::PlatformServices` interface. Windows injects `WindowsPlatformServices` from `src/platform_windows/windows_platform_services.*`, Apple now injects `src/platform_apple/apple_platform_services.*`, and the retained non-Windows fallback adapter in `src/platform_legacy/legacy_platform_services.*` is narrowed to Android/Linux/Web bridge functions plus retained no-op branches, including retained iOS canvas tip behavior, retained non-Windows VR unsupported/no-op behavior, and retained macOS PPBR export directory override; `pp_platform_api` also owns the default network TLS policy helper consumed by retained curl sites that cannot yet depend on injected services | Preserve behavior while moving platform execution behind a testable service boundary before platform shell implementations are injected | `pp_platform_api_tests`; `pp_app_core_document_export_tests`; `pp_app_core_document_platform_io_tests`; `ctest --preset desktop-fast --build-config Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug` | Replace `src/platform_legacy/legacy_platform_services.*` with injected `pp_platform_*` service implementations owned by each non-Windows platform shell | +| DEBT-0016 | Open | Modernization | Clipboard get/set requests now consume pure `pp_app_core` planning through `pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write`; Windows live execution uses injected `WindowsPlatformServices`, Apple clipboard execution now uses `src/platform_apple/apple_platform_services.*`, Android clipboard execution now uses `src/platform_android/android_platform_services.*`, and only Linux/Web fallback behavior still routes through the retained non-Windows adapter | Keep picker/color text clipboard behavior stable while platform shells are extracted incrementally | `pp_app_core_document_platform_io_tests`; `pano_cli plan-clipboard-write --text #ff00aa`; `ctest --preset desktop-fast --build-config Debug` | Clipboard execution is owned by injected `pp_platform_*` services for every supported platform | +| DEBT-0017 | Open | Modernization | Startup storage path preparation, `App::clipboard_get_text`, `App::clipboard_set_text`, `App::show_cursor`, `App::hide_cursor`, `App::showKeyboard`, `App::hideKeyboard`, `App::display_file`, `App::share_file`, native app/window close, UI-thread lifecycle hooks, render-context acquire/release/present hooks, render-target binding hooks, render platform hint hooks, render debug callback hooks, render-capture frame hooks, recording cleanup, live asset/layout reload policy, diagnostic stacktrace/crash hooks, per-frame platform hooks, `App::pick_image`, `App::pick_file`, the non-writer `App::pick_file_save`, `App::pick_dir`, working-directory picker/display-path policy, canvas input tip/pressure policy, prepared-file save/download handoff, work-directory document export collection policy, app network TLS verification policy, PPBR export data-directory policy, SonarPen availability/startup, and VR mode start/stop now call the SDK-free `pp::platform::PlatformServices` interface. Windows injects `WindowsPlatformServices` from `src/platform_windows/windows_platform_services.*`, Apple now injects `src/platform_apple/apple_platform_services.*`, Android now injects `src/platform_android/android_platform_services.*`, and the retained non-Windows fallback adapter in `src/platform_legacy/legacy_platform_services.*` is narrowed to Linux/Web behavior plus retained no-op branches, including retained iOS canvas tip behavior, retained non-Windows VR unsupported/no-op behavior, and retained macOS PPBR export directory override; `pp_platform_api` also owns the default network TLS policy helper consumed by retained curl sites that cannot yet depend on injected services | Preserve behavior while moving platform execution behind a testable service boundary before platform shell implementations are injected | `pp_platform_api_tests`; `pp_app_core_document_export_tests`; `pp_app_core_document_platform_io_tests`; `ctest --preset desktop-fast --build-config Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug` | Replace `src/platform_legacy/legacy_platform_services.*` with injected `pp_platform_*` service implementations owned by each non-Windows platform shell | | DEBT-0019 | Open | Modernization | Unreferenced-parameter warnings are muted globally through `pp_project_warnings` with MSVC `/wd4100` and Clang/GCC `-Wno-unused-parameter` | Legacy callbacks, virtual hooks, serializer methods, and platform/API compatibility functions carry many intentionally unused parameters during the component split; muting this keeps stricter warning builds focused on higher-signal migration issues | `cmake --build --preset windows-msvc-default --config Debug --target PanoPainter`; `ctest --preset desktop-fast --build-config Debug`; `cmake --build --preset linux-clang --target pp_foundation` | Remove `/wd4100` and `-Wno-unused-parameter`, mark intentionally unused parameters with names/comments or `[[maybe_unused]]`, and make the Windows app plus headless Clang/GCC tests pass without unreferenced-parameter warnings | | DEBT-0020 | Open | Modernization | Document resize dialog state, selected-resolution planning, and execution dispatch now consume pure `pp_app_core` through `NodeDialogResize`, `App::dialog_resize`, `pano_cli plan-document-resize`, and the `DocumentResizeServices` boundary, and live resize shares `src/legacy_document_canvas_services.*` with canvas clear commands; resize history clearing is an explicit app-core execution output implemented directly by the retained `ActionManager`, but the shared live bridge still calls legacy `Canvas::resize`, updates the legacy app title, and owns the retained `ActionManager` call site | Preserve existing layer/frame GPU resize behavior while the document model and canvas execution boundary are extracted incrementally | `pp_app_core_document_resize_tests`; `pano_cli plan-document-resize --current-resolution 2048 --selected-resolution-index 4`; `ctest --preset desktop-fast --build-config Debug` | Document resize execution is owned by injected document/app services with no legacy resize adapter, title shim, or retained `ActionManager` history clearing | | DEBT-0021 | Open | Modernization | Layer rename planning/execution dispatch, layer panel operation planning/execution dispatch, layer panel selected-control/visibility view projection, and explicit layer history-intent helpers now consume pure `pp_app_core` through `App::dialog_layer_rename`, `App::init_sidebar` layer callbacks, `NodePanelLayer::update_attributes()`, `pano_cli plan-layer-rename`, `pano_cli plan-layer-operation`, `pano_cli plan-layer-panel-view`, `DocumentLayerRenameServices`, and `DocumentLayerOperationServices`, and the live execution adapters are centralized in `src/legacy_document_layer_services.*`; rename now records undo before applying the new name through separate app-core service calls, but the shared bridge and panel adapter still mutate legacy `Canvas` layer state, `NodeLayer`/`NodePanelLayer`, and retained `ActionManager` undo entries for add/remove/property-change/clear paths | Preserve existing UI/canvas behavior while document layer commands, panel projection, and undo history are extracted incrementally | `pp_app_core_document_layer_tests`; `pano_cli plan-layer-rename --old-name Base --new-name Paint`; `pano_cli plan-layer-operation --kind add --layer-count 2 --index 1 --name Paint`; `pano_cli plan-layer-panel-view --layer-count 3 --current-index 1 --hidden-index 2 --locked-index 1 --current-opacity 0.25 --current-blend-mode 4`; `ctest --preset desktop-fast --build-config Debug` | Layer command execution and panel state projection are owned by the document/app command boundary with legacy `Canvas`/UI nodes acting only as adapters or removed entirely | diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 19ac4ba5..42536d29 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -70,6 +70,20 @@ What is already real: - `pp_app_core` Latest slice: +- `src/platform_android/android_platform_services.*` now owns the concrete + Android `PlatformServices` implementation and `create_platform_services()` + instead of leaving the live Android execution surface inside + `platform_legacy`. +- `android/src/cpp/main.cpp` now binds that owned Android `PlatformServices` + instance into `App` directly at the Android entrypoint. +- The touched Android clipboard, keyboard visibility, JNI thread + attach/detach, async render-context, and file-picker execution now route + through `src/platform_android/android_platform_services.*` instead of the + cross-platform fallback adapter. +- `src/platform_legacy/legacy_platform_services.*` no longer carries the + Android bridge/configuration surface or the touched Android method branches, + so the retained fallback adapter is narrower again and now focused on the + Linux/Web path plus generic fallback policy. - `src/platform_apple/apple_platform_services.*` now owns the concrete Apple `PlatformServices` implementation plus the `create_apple_platform_services()` factory instead of leaving the live Apple execution surface inside @@ -86,15 +100,6 @@ Latest slice: document-service provider/configuration surface or the touched Apple method branches, so the retained fallback adapter is narrower and now focused on the Android/Linux/Web path. -- `src/platform_legacy/legacy_platform_services.*` now takes an explicit - Android bridge through `create_platform_services(...)` instead of declaring - Android JNI/EGL/clipboard/file-picker hooks directly inside the legacy - adapter. -- `android/src/cpp/main.cpp` now seeds that Android-owned bridge into its - owned legacy `PlatformServices` instance. -- The touched Android clipboard, keyboard visibility, JNI thread attach/detach, - async render-context, and file-picker ownership now sit at the Android - entrypoint instead of the cross-platform fallback adapter body. - `src/platform_legacy/legacy_platform_services.*` now takes an explicit `WebPlatformServices*` dependency through `create_platform_services(...)` instead of routing WebGL publish/flush/default-canvas/save-prepared-file diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index cf402807..297038b4 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -51,8 +51,9 @@ Completed, blocked, and superseded task history moved to `src/platform_apple/apple_platform_state.cpp` and `src/platform_apple/apple_platform_services.*`, and the live Apple `PlatformServices` surface now binds directly from those Apple-owned files, - but the broader non-Windows fallback adapter still exists for - Android/Linux/Web + and Android now also binds directly from + `src/platform_android/android_platform_services.*`, but the broader + non-Windows fallback adapter still exists for Linux/Web - `platform_legacy` is still part of the live app shell - The app runtime boundary is not finished: - render/UI queues are static `App` state @@ -80,6 +81,20 @@ Completed, blocked, and superseded task history moved to the queue is now ordered by code movement instead. Current slice: +- `src/platform_android/android_platform_services.*` now owns the concrete + Android `PlatformServices` implementation and `create_platform_services()` + instead of leaving the live Android execution surface in + `platform_legacy`. +- `android/src/cpp/main.cpp` now binds that owned Android `PlatformServices` + instance into `App` directly at the Android entrypoint. +- The touched Android clipboard, keyboard visibility, JNI thread + attach/detach, async render-context, and file-picker execution now route + through `src/platform_android/android_platform_services.*` instead of the + cross-platform fallback adapter. +- `src/platform_legacy/legacy_platform_services.*` no longer carries the + Android bridge/configuration surface or the touched Android method branches, + so the retained fallback adapter is narrower again and now focused on the + Linux/Web path plus generic fallback policy. - `src/platform_apple/apple_platform_services.*` now owns the concrete Apple `PlatformServices` implementation plus the `create_apple_platform_services()` factory instead of leaving the live Apple execution surface in @@ -96,15 +111,6 @@ Current slice: document-service provider/configuration surface or the touched Apple method branches, so the retained fallback adapter is narrower and now focused on the Android/Linux/Web path. -- `src/platform_legacy/legacy_platform_services.*` now takes an explicit - Android bridge through `create_platform_services(...)` instead of declaring - Android JNI/EGL/clipboard/file-picker hooks directly inside the legacy - adapter. -- `android/src/cpp/main.cpp` now seeds that Android-owned bridge into its - owned legacy `PlatformServices` instance. -- The touched Android clipboard, keyboard visibility, JNI thread attach/detach, - async render-context, and file-picker ownership now sit at the Android - entrypoint instead of the cross-platform fallback adapter body. - `src/platform_legacy/legacy_platform_services.*` now takes an explicit `WebPlatformServices*` dependency through `create_platform_services(...)` instead of routing WebGL publish/flush/default-canvas/save-prepared-file diff --git a/src/platform_android/android_platform_services.cpp b/src/platform_android/android_platform_services.cpp new file mode 100644 index 00000000..168c4156 --- /dev/null +++ b/src/platform_android/android_platform_services.cpp @@ -0,0 +1,316 @@ +#include "platform_android/android_platform_services.h" + +#include "platform_api/network_tls_policy.h" +#include "platform_api/platform_policy.h" + +#include +#include + +#if defined(__ANDROID__) +#include +#endif + +namespace pp::platform::android { +namespace { + +constexpr auto kPlatformFamily = pp::platform::PlatformFamily::android; + +class AndroidPlatformServices final : public pp::platform::PlatformServices { +public: + explicit AndroidPlatformServices(AndroidPlatformServicesConfig config) + : bridge_(std::move(config.bridge)) + , storage_paths_(std::move(config.storage_paths)) + { + } + + [[nodiscard]] PlatformStoragePaths prepare_storage_paths() override + { + return storage_paths_ ? *storage_paths_ : PlatformStoragePaths {}; + } + + void log_stacktrace() override + { + } + + void trigger_crash_test() override + { +#if defined(__ANDROID__) + int* x = nullptr; + *x = 42; +#endif + } + + [[nodiscard]] std::string clipboard_text() override + { + if (bridge_.clipboard_text) + return bridge_.clipboard_text(); + return {}; + } + + [[nodiscard]] bool set_clipboard_text(std::string_view text) override + { + if (bridge_.set_clipboard_text) + return bridge_.set_clipboard_text(text); + return false; + } + + void set_cursor_visible(bool visible) override + { + (void)visible; + } + + void set_virtual_keyboard_visible(bool visible) override + { + if (bridge_.set_virtual_keyboard_visible) + bridge_.set_virtual_keyboard_visible(visible); + } + + void attach_ui_thread() override + { + if (bridge_.attach_ui_thread) + bridge_.attach_ui_thread(); + } + + void detach_ui_thread() override + { + if (bridge_.detach_ui_thread) + bridge_.detach_ui_thread(); + } + + void acquire_render_context() override + { + if (bridge_.acquire_render_context) + bridge_.acquire_render_context(); + } + + void release_render_context() override + { + if (bridge_.release_render_context) + bridge_.release_render_context(); + } + + void present_render_context() override + { + if (bridge_.present_render_context) + bridge_.present_render_context(); + } + + void bind_default_render_target() override + { +#if defined(__ANDROID__) + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + } + + void bind_main_render_target() override + { + bind_default_render_target(); + } + + void apply_render_platform_hints() override + { + } + + 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 platform_deletes_recorded_files_on_clear(kPlatformFamily); + } + + void clear_recorded_files(std::string_view recording_path) override + { + (void)recording_path; + } + + void publish_exported_image(std::string_view path) override + { + (void)path; + } + + void flush_persistent_storage() override + { + } + + [[nodiscard]] std::vector document_browse_roots( + std::string_view work_path, + std::string_view data_path) override + { + return platform_document_browse_roots(kPlatformFamily, work_path, data_path); + } + + void save_ui_state() override + { + } + + [[nodiscard]] bool enables_live_asset_reloading() override + { + return platform_enables_live_asset_reloading(kPlatformFamily); + } + + void update_platform_frame(float delta_time_seconds) override + { + (void)delta_time_seconds; + } + + void report_rendered_frames(int frames) override + { + (void)frames; + } + + void display_file(std::string_view path) override + { + (void)path; + } + + void share_file(std::string_view path) override + { + (void)path; + } + + void request_app_close() override + { + } + + [[nodiscard]] bool start_vr_mode() override + { + return false; + } + + void stop_vr_mode() override + { + } + + void pick_image(PickedPathCallback callback) override + { + if (bridge_.pick_file) + bridge_.pick_file(std::move(callback)); + } + + void pick_file(std::vector file_types, PickedPathCallback callback) override + { + (void)file_types; + if (bridge_.pick_file) + bridge_.pick_file(std::move(callback)); + } + + void pick_save_file(std::vector file_types, PickedPathCallback callback) override + { + (void)file_types; + if (bridge_.pick_save_file) + bridge_.pick_save_file(std::move(callback)); + } + + void pick_directory(PickedPathCallback callback) override + { + (void)callback; + } + + [[nodiscard]] bool supports_working_directory_picker() override + { + return platform_supports_working_directory_picker(kPlatformFamily); + } + + [[nodiscard]] std::string format_working_directory_path(std::string_view path) override + { + return std::string(path); + } + + [[nodiscard]] bool uses_prepared_file_writes() override + { + return platform_uses_prepared_file_writes(kPlatformFamily); + } + + [[nodiscard]] bool uses_work_directory_document_export_collections() override + { + return platform_uses_work_directory_document_export_collections(kPlatformFamily); + } + + [[nodiscard]] bool disables_network_tls_verification() override + { + return default_disables_network_tls_verification(); + } + + [[nodiscard]] bool uses_ppbr_export_data_directory_override() override + { + return platform_uses_ppbr_export_data_directory_override(kPlatformFamily); + } + + [[nodiscard]] bool supports_sonarpen() override + { + return platform_supports_sonarpen(kPlatformFamily); + } + + void start_sonarpen() override + { + } + + [[nodiscard]] int default_canvas_resolution() override + { + return platform_default_canvas_resolution(kPlatformFamily); + } + + [[nodiscard]] bool draws_canvas_tip_for_pointer( + bool is_mouse, + bool is_stylus, + bool is_left_button_release) override + { + return platform_draws_canvas_tip_for_pointer( + kPlatformFamily, + is_mouse, + is_stylus, + is_left_button_release); + } + + [[nodiscard]] float adjust_canvas_input_pressure(float pressure) override + { + return pressure; + } + + [[nodiscard]] 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 plan_platform_writable_file( + kPlatformFamily, + type, + default_name, + data_path, + temporary_path); + } + + void save_prepared_file( + std::string_view path, + std::string_view suggested_name, + PreparedFileCallback callback) override + { + (void)suggested_name; + callback(std::string(path), false); + } + +private: + AndroidPlatformBridge bridge_; + std::shared_ptr storage_paths_; +}; + +} + +std::unique_ptr create_platform_services( + AndroidPlatformServicesConfig config) +{ + return std::make_unique(std::move(config)); +} + +} diff --git a/src/platform_android/android_platform_services.h b/src/platform_android/android_platform_services.h new file mode 100644 index 00000000..d56ce147 --- /dev/null +++ b/src/platform_android/android_platform_services.h @@ -0,0 +1,32 @@ +#pragma once + +#include "platform_api/platform_services.h" + +#include +#include +#include + +namespace pp::platform::android { + +struct AndroidPlatformBridge { + std::function clipboard_text; + std::function set_clipboard_text; + std::function set_virtual_keyboard_visible; + std::function attach_ui_thread; + std::function detach_ui_thread; + std::function acquire_render_context; + std::function release_render_context; + std::function present_render_context; + std::function pick_file; + std::function pick_save_file; +}; + +struct AndroidPlatformServicesConfig { + AndroidPlatformBridge bridge; + std::shared_ptr storage_paths; +}; + +[[nodiscard]] std::unique_ptr create_platform_services( + AndroidPlatformServicesConfig config = {}); + +} diff --git a/src/platform_legacy/legacy_platform_services.cpp b/src/platform_legacy/legacy_platform_services.cpp index d8b4a94d..6b20fe07 100644 --- a/src/platform_legacy/legacy_platform_services.cpp +++ b/src/platform_legacy/legacy_platform_services.cpp @@ -9,9 +9,7 @@ #include "platform_api/platform_policy.h" #include "renderer_gl/opengl_capabilities.h" -#ifdef __ANDROID__ -#include "main.h" -#elif __LINUX__ +#ifdef __LINUX__ #include #include "platform_linux/linux_platform_services.h" std::string linux_home_path(); @@ -33,10 +31,6 @@ class LegacyPlatformServices final : public pp::platform::PlatformServices { public: explicit LegacyPlatformServices(pp::platform::legacy::LegacyPlatformServicesConfig config = {}) : glfw_shell_(std::move(config.glfw_shell)) - , android_bridge_(std::move(config.android_bridge)) -#ifdef __ANDROID__ - , android_storage_paths_(std::move(config.android_storage_paths)) -#endif , web_platform_services_(config.web_platform_services) { } @@ -72,8 +66,6 @@ public: data_path + "/frames", {}, }; -#elif defined(__ANDROID__) - return android_storage_paths_ ? *android_storage_paths_ : pp::platform::PlatformStoragePaths {}; #else return {}; #endif @@ -85,34 +77,18 @@ public: void trigger_crash_test() override { -#if defined(__ANDROID__) - int *x = nullptr; *x = 42; - LOG("%d", *x); -#endif } [[nodiscard]] std::string clipboard_text() override { -#ifdef __ANDROID__ - if (android_bridge_.clipboard_text) - return android_bridge_.clipboard_text(); return {}; -#else - return {}; -#endif } [[nodiscard]] bool set_clipboard_text(std::string_view text) override { const std::string value(text); -#ifdef __ANDROID__ - if (android_bridge_.set_clipboard_text) - return android_bridge_.set_clipboard_text(value); - return false; -#else (void)value; return false; -#endif } void set_cursor_visible(bool visible) override @@ -122,54 +98,31 @@ public: void set_virtual_keyboard_visible(bool visible) override { -#ifdef __ANDROID__ - if (android_bridge_.set_virtual_keyboard_visible) - android_bridge_.set_virtual_keyboard_visible(visible); -#else (void)visible; -#endif } void attach_ui_thread() override { -#ifdef __ANDROID__ - if (android_bridge_.attach_ui_thread) - android_bridge_.attach_ui_thread(); -#endif } void detach_ui_thread() override { -#ifdef __ANDROID__ - if (android_bridge_.detach_ui_thread) - android_bridge_.detach_ui_thread(); -#endif } void acquire_render_context() override { -#if __ANDROID__ - if (android_bridge_.acquire_render_context) - android_bridge_.acquire_render_context(); -#elif __LINUX__ || __WEB__ +#if __LINUX__ || __WEB__ invoke_legacy_glfw_shell_callback(glfw_shell_.acquire_render_context); #endif } void release_render_context() override { -#if __ANDROID__ - if (android_bridge_.release_render_context) - android_bridge_.release_render_context(); -#endif } void present_render_context() override { -#if __ANDROID__ - if (android_bridge_.present_render_context) - android_bridge_.present_render_context(); -#elif __LINUX__ || __WEB__ +#if __LINUX__ || __WEB__ invoke_legacy_glfw_shell_callback(glfw_shell_.present_render_context); #endif } @@ -279,10 +232,7 @@ public: void pick_image(pp::platform::PickedPathCallback callback) override { -#ifdef __ANDROID__ - if (android_bridge_.pick_file) - android_bridge_.pick_file(std::move(callback)); -#elif __LINUX__ +#ifdef __LINUX__ if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false)) invoke_picked_path_if_selected(p, callback); #elif __WEB__ @@ -294,10 +244,7 @@ public: void pick_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { -#ifdef __ANDROID__ - if (android_bridge_.pick_file) - android_bridge_.pick_file(std::move(callback)); -#elif __LINUX__ +#ifdef __LINUX__ if (auto p = tinyfd_openFileDialog("Open File", "", 0, nullptr, nullptr, false)) invoke_picked_path_if_selected(p, callback); #elif __WEB__ @@ -310,13 +257,8 @@ public: void pick_save_file(std::vector file_types, pp::platform::PickedPathCallback callback) override { -#if __ANDROID__ - if (android_bridge_.pick_save_file) - android_bridge_.pick_save_file(std::move(callback)); -#else (void)file_types; (void)callback; -#endif } void pick_directory(pp::platform::PickedPathCallback callback) override @@ -472,10 +414,6 @@ private: } pp::platform::legacy::LegacyGlfwPlatformShell glfw_shell_; - pp::platform::legacy::LegacyAndroidPlatformBridge android_bridge_; -#ifdef __ANDROID__ - std::shared_ptr android_storage_paths_; -#endif pp::platform::WebPlatformServices* web_platform_services_ = nullptr; }; diff --git a/src/platform_legacy/legacy_platform_services.h b/src/platform_legacy/legacy_platform_services.h index 183521cf..074b4f61 100644 --- a/src/platform_legacy/legacy_platform_services.h +++ b/src/platform_legacy/legacy_platform_services.h @@ -13,23 +13,8 @@ struct LegacyGlfwPlatformShell { std::function request_app_close; }; -struct LegacyAndroidPlatformBridge { - std::function clipboard_text; - std::function set_clipboard_text; - std::function set_virtual_keyboard_visible; - std::function attach_ui_thread; - std::function detach_ui_thread; - std::function acquire_render_context; - std::function release_render_context; - std::function present_render_context; - std::function pick_file; - std::function pick_save_file; -}; - struct LegacyPlatformServicesConfig { LegacyGlfwPlatformShell glfw_shell; - LegacyAndroidPlatformBridge android_bridge; - std::shared_ptr android_storage_paths; pp::platform::WebPlatformServices* web_platform_services = nullptr; }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d6f89247..a47fc624 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -358,6 +358,9 @@ endif() if(TARGET pp_platform_linux) target_link_libraries(pp_platform_api_tests PRIVATE pp_platform_linux) endif() +if(TARGET pp_platform_android) + target_link_libraries(pp_platform_api_tests PRIVATE pp_platform_android) +endif() add_test(NAME pp_platform_api_tests COMMAND pp_platform_api_tests) set_tests_properties(pp_platform_api_tests PROPERTIES