Retain Apple bridge services and bind Win32 runtime

This commit is contained in:
2026-06-17 01:44:20 +02:00
parent fd462dc406
commit 3cbc88fe78
9 changed files with 311 additions and 203 deletions

View File

@@ -92,6 +92,17 @@ Current hotspot files:
Latest slice: Latest slice:
- The full retained Apple document bridge construction no longer lives inline
in `src/platform_legacy/legacy_platform_services.cpp`; it now lives behind
`active_legacy_apple_document_platform_services()` in
`src/platform_legacy/legacy_platform_state.*`, and that retained service now
resets when seeded Apple handles change so first-use bridge capture stays in
sync with the active entrypoint state.
- Win32 main-thread task dispatch no longer reaches `AppRuntime` through
`App::I` inside `src/platform_windows/windows_platform_services.cpp`;
`src/platform_windows/windows_runtime_shell.*` now binds the active runtime
explicitly and clears that binding on shutdown, leaving the Windows queue
helper as a thinner runtime forwarder.
- `App` no longer owns `and_app` or `and_engine`; the retained Android - `App` no longer owns `and_app` or `and_engine`; the retained Android
entrypoint now seeds only the explicit legacy platform storage snapshot entrypoint now seeds only the explicit legacy platform storage snapshot
needed by touched platform services instead of storing Android-native needed by touched platform services instead of storing Android-native
@@ -227,7 +238,9 @@ Current architecture mismatches that must be treated as real blockers:
`platform_legacy`-mirrored Apple/GLFW handle cluster is now seeded `platform_legacy`-mirrored Apple/GLFW handle cluster is now seeded
explicitly from platform entrypoints instead of being copied out of `App`, explicitly from platform entrypoints instead of being copied out of `App`,
and retained storage roots are now also seeded explicitly instead of being and retained storage roots are now also seeded explicitly instead of being
lazily copied from `App::I` inside `active_legacy_storage_paths()`. lazily copied from `App::I` inside `active_legacy_storage_paths()`, while the
retained Apple document bridge now also lives in `legacy_platform_state.*`
instead of being built inline in `legacy_platform_services.cpp`.
- `src/platform_legacy/legacy_platform_services.*` is still part of the live - `src/platform_legacy/legacy_platform_services.*` is still part of the live
app shell. app shell.
- `pp_panopainter_ui` still depends on `pp_legacy_app`. - `pp_panopainter_ui` still depends on `pp_legacy_app`.

View File

@@ -1154,6 +1154,11 @@ Current slice:
also live in `src/platform_legacy/legacy_platform_state.*`, and also live in `src/platform_legacy/legacy_platform_state.*`, and
`src/platform_legacy/legacy_platform_services.cpp` now consumes those `src/platform_legacy/legacy_platform_services.cpp` now consumes those
snapshots without direct `App::I` reads in the touched paths snapshots without direct `App::I` reads in the touched paths
- the retained Apple document bridge now also lives behind
`active_legacy_apple_document_platform_services()` in
`src/platform_legacy/legacy_platform_state.*` instead of being built inline
inside `src/platform_legacy/legacy_platform_services.cpp`, and that retained
service resets when seeded Apple handles change
- retained Apple callback injection and broader `platform_legacy` singleton - retained Apple callback injection and broader `platform_legacy` singleton
reach are still open reach are still open
- the `platform_legacy`-mirrored Apple/GLFW handle cluster is now seeded - the `platform_legacy`-mirrored Apple/GLFW handle cluster is now seeded
@@ -1210,6 +1215,11 @@ Current slice:
- `App` also no longer owns `and_app` or `and_engine`; the retained Android - `App` also no longer owns `and_app` or `and_engine`; the retained Android
entrypoint now seeds only the explicit legacy platform storage snapshot entrypoint now seeds only the explicit legacy platform storage snapshot
needed by touched platform services. needed by touched platform services.
- Win32 main-thread task dispatch also no longer reaches `AppRuntime` through
`App::I`; `src/platform_windows/windows_runtime_shell.*` now binds the
active runtime explicitly and
`src/platform_windows/windows_platform_services.cpp` consumes that bound
runtime for enqueue/drain.
- `App` still owns broader retained legacy platform state, so this remains a - `App` still owns broader retained legacy platform state, so this remains a
live ownership task. live ownership task.

View File

@@ -23,13 +23,6 @@ std::string android_get_clipboard();
bool android_set_clipboard(const std::string& s); bool android_set_clipboard(const std::string& s);
#elif __APPLE__ #elif __APPLE__
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
#include "objc_utils.h"
#ifdef __IOS__
#include "AppDelegate.h"
#include "GameViewController.h"
#elif defined(__OSX__)
#include "main.h"
#endif
void delete_all_files_in_path(const std::string& source_path); void delete_all_files_in_path(const std::string& source_path);
#ifdef __IOS__ #ifdef __IOS__
void save_image_library(const std::string& path); void save_image_library(const std::string& path);
@@ -93,16 +86,6 @@ public:
} }
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
{
NSMutableArray<NSString*>* types = [NSMutableArray arrayWithCapacity:file_types.size()];
for (const auto& type : file_types)
{
[types addObject:[NSString stringWithCString:type.c_str() encoding:NSUTF8StringEncoding]];
}
return types;
}
[[nodiscard]] pp::platform::PlatformStoragePaths prepare_legacy_apple_storage_paths() [[nodiscard]] pp::platform::PlatformStoragePaths prepare_legacy_apple_storage_paths()
{ {
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state(); const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
@@ -113,161 +96,6 @@ public:
#endif #endif
return pp::platform::legacy::active_legacy_storage_paths(); return pp::platform::legacy::active_legacy_storage_paths();
} }
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices& active_apple_document_platform_services()
{
#ifdef __IOS__
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
auto* const ios_view = apple_state.ios_view;
auto* const ios_app = apple_state.ios_app;
static pp::platform::apple::AppleDocumentPlatformServices services(
pp::platform::PlatformFamily::ios,
[ios_view] {
pp::platform::apple::AppleDocumentPickerBridge bridge;
bridge.clipboard_text = [ios_view] {
return [ios_view clipboard_get_string];
};
bridge.set_clipboard_text = [ios_view](std::string_view text) {
const std::string value(text);
return [ios_view clipboard_set_string:value];
};
bridge.set_virtual_keyboard_visible = [ios_view](bool visible) {
dispatch_async(dispatch_get_main_queue(), ^{
if (visible)
[ios_view show_keyboard];
else
[ios_view hide_keyboard];
});
};
bridge.trigger_crash_test = [ios_view] {
[ios_view crash];
};
bridge.start_sonarpen = [ios_app] {
[ios_app sonarpen_start];
};
bridge.acquire_render_context = [ios_view] {
[ios_view async_lock];
};
bridge.release_render_context = [ios_view] {
[ios_view async_unlock];
};
bridge.present_render_context = [ios_view] {
[ios_view async_swap];
};
bridge.bind_main_render_target = [ios_view] {
[ios_view->glview bindDrawable];
};
bridge.display_file = [ios_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view display_file:path];
});
};
bridge.share_file = [ios_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view share_file:[NSString stringWithUTF8String:path.c_str()]];
});
};
bridge.pick_image = [ios_view](pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_photo:callback];
});
};
bridge.pick_file = [ios_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_file:apple_file_types_array(file_types) then:callback];
});
};
bridge.save_prepared_file = [ios_view](
std::string path,
std::string suggested_name,
pp::platform::PreparedFileCallback callback) {
(void)suggested_name;
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_file_save:path];
});
callback(path, true);
};
return bridge;
}());
return services;
#else
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
auto* const osx_view = apple_state.osx_view;
auto* const osx_app = apple_state.osx_app;
static pp::platform::apple::AppleDocumentPlatformServices services(
pp::platform::PlatformFamily::macos,
[osx_view, osx_app] {
pp::platform::apple::AppleDocumentPickerBridge bridge;
bridge.clipboard_text = [osx_view] {
return [osx_view clipboard_get_string];
};
bridge.set_clipboard_text = [osx_view](std::string_view text) {
const std::string value(text);
return [osx_view clipboard_set_string:value];
};
bridge.share_file = [osx_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[osx_view share_file:[NSString stringWithUTF8String:path.c_str()]];
});
};
bridge.trigger_crash_test = [osx_view] {
[osx_view hockeyapp_crash];
};
bridge.request_app_close = [osx_view] {
dispatch_async(dispatch_get_main_queue(), ^{
[osx_view close];
});
};
bridge.acquire_render_context = [osx_view] {
[osx_view async_lock];
};
bridge.release_render_context = [osx_view] {
[osx_view async_unlock];
};
bridge.present_render_context = [osx_view] {
[osx_view async_swap];
};
bridge.set_cursor_visible = [osx_view](bool visible) {
[osx_view show_cursor:visible];
};
bridge.save_ui_state = [osx_app] {
[osx_app save_ui_state];
};
bridge.pick_file = [osx_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_file:apple_file_types_array(file_types)];
callback(path);
});
};
bridge.pick_save_file = [osx_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_file_save:apple_file_types_array(file_types)];
callback(path);
});
};
bridge.pick_directory = [osx_view](pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_dir];
callback(path);
});
};
bridge.format_working_directory_path = [](std::string_view path) {
char path_buffer[4096] = {};
if (realpath(std::string(path).c_str(), path_buffer))
return std::string(path_buffer);
return std::string(path);
};
return bridge;
}());
return services;
#endif
}
#endif #endif
// DEBT-0017: fallback for platforms that do not inject PlatformServices yet. // DEBT-0017: fallback for platforms that do not inject PlatformServices yet.
@@ -324,9 +152,9 @@ public:
void trigger_crash_test() override void trigger_crash_test() override
{ {
#ifdef __IOS__ #ifdef __IOS__
active_apple_document_platform_services().trigger_crash_test(); pp::platform::legacy::active_legacy_apple_document_platform_services().trigger_crash_test();
#elif __OSX__ #elif __OSX__
active_apple_document_platform_services().trigger_crash_test(); pp::platform::legacy::active_legacy_apple_document_platform_services().trigger_crash_test();
#elif defined(__ANDROID__) #elif defined(__ANDROID__)
int *x = nullptr; *x = 42; int *x = nullptr; *x = 42;
LOG("%d", *x); LOG("%d", *x);
@@ -338,7 +166,7 @@ public:
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
const auto family = pp::platform::current_platform_family(); const auto family = pp::platform::current_platform_family();
if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos) if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos)
return active_apple_document_platform_services().clipboard_text(); return pp::platform::legacy::active_legacy_apple_document_platform_services().clipboard_text();
#endif #endif
#ifdef __ANDROID__ #ifdef __ANDROID__
return android_get_clipboard(); return android_get_clipboard();
@@ -352,7 +180,7 @@ public:
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
const auto family = pp::platform::current_platform_family(); const auto family = pp::platform::current_platform_family();
if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos) if (family == pp::platform::PlatformFamily::ios || family == pp::platform::PlatformFamily::macos)
return active_apple_document_platform_services().set_clipboard_text(text); return pp::platform::legacy::active_legacy_apple_document_platform_services().set_clipboard_text(text);
#endif #endif
const std::string value(text); const std::string value(text);
#ifdef __ANDROID__ #ifdef __ANDROID__
@@ -366,7 +194,7 @@ public:
void set_cursor_visible(bool visible) override void set_cursor_visible(bool visible) override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().set_cursor_visible(visible); pp::platform::legacy::active_legacy_apple_document_platform_services().set_cursor_visible(visible);
#else #else
(void)visible; (void)visible;
#endif #endif
@@ -375,7 +203,7 @@ public:
void set_virtual_keyboard_visible(bool visible) override void set_virtual_keyboard_visible(bool visible) override
{ {
#ifdef __IOS__ #ifdef __IOS__
active_apple_document_platform_services().set_virtual_keyboard_visible(visible); pp::platform::legacy::active_legacy_apple_document_platform_services().set_virtual_keyboard_visible(visible);
#elif __ANDROID__ #elif __ANDROID__
displayKeyboard(visible); displayKeyboard(visible);
#else #else
@@ -400,7 +228,7 @@ public:
void acquire_render_context() override void acquire_render_context() override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().acquire_render_context(); pp::platform::legacy::active_legacy_apple_document_platform_services().acquire_render_context();
#elif __ANDROID__ #elif __ANDROID__
android_async_lock(); android_async_lock();
#elif __LINUX__ || __WEB__ #elif __LINUX__ || __WEB__
@@ -411,7 +239,7 @@ public:
void release_render_context() override void release_render_context() override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().release_render_context(); pp::platform::legacy::active_legacy_apple_document_platform_services().release_render_context();
#elif __ANDROID__ #elif __ANDROID__
android_async_unlock(); android_async_unlock();
#endif #endif
@@ -420,7 +248,7 @@ public:
void present_render_context() override void present_render_context() override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().present_render_context(); pp::platform::legacy::active_legacy_apple_document_platform_services().present_render_context();
#elif __ANDROID__ #elif __ANDROID__
android_async_swap(); android_async_swap();
#elif __LINUX__ || __WEB__ #elif __LINUX__ || __WEB__
@@ -438,7 +266,7 @@ public:
void bind_main_render_target() override void bind_main_render_target() override
{ {
#if __IOS__ #if __IOS__
active_apple_document_platform_services().bind_main_render_target(); pp::platform::legacy::active_legacy_apple_document_platform_services().bind_main_render_target();
#else #else
bind_default_render_target(); bind_default_render_target();
#endif #endif
@@ -520,7 +348,7 @@ public:
std::string_view data_path) override std::string_view data_path) override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
return active_apple_document_platform_services().document_browse_roots(work_path, data_path); return pp::platform::legacy::active_legacy_apple_document_platform_services().document_browse_roots(work_path, data_path);
#else #else
return pp::platform::platform_document_browse_roots( return pp::platform::platform_document_browse_roots(
pp::platform::current_platform_family(), pp::platform::current_platform_family(),
@@ -534,7 +362,7 @@ public:
if (!pp::platform::platform_saves_native_ui_state(pp::platform::current_platform_family())) if (!pp::platform::platform_saves_native_ui_state(pp::platform::current_platform_family()))
return; return;
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().save_ui_state(); pp::platform::legacy::active_legacy_apple_document_platform_services().save_ui_state();
#endif #endif
} }
@@ -561,9 +389,9 @@ public:
void pick_image(pp::platform::PickedPathCallback callback) override void pick_image(pp::platform::PickedPathCallback callback) override
{ {
#ifdef __IOS__ #ifdef __IOS__
active_apple_document_platform_services().pick_image(std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_image(std::move(callback));
#elif __OSX__ #elif __OSX__
active_apple_document_platform_services().pick_image(std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_image(std::move(callback));
#elif __ANDROID__ #elif __ANDROID__
android_pick_file(callback); android_pick_file(callback);
#elif __LINUX__ #elif __LINUX__
@@ -579,9 +407,9 @@ public:
void pick_file(std::vector<std::string> file_types, pp::platform::PickedPathCallback callback) override void pick_file(std::vector<std::string> file_types, pp::platform::PickedPathCallback callback) override
{ {
#ifdef __IOS__ #ifdef __IOS__
active_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback));
#elif __OSX__ #elif __OSX__
active_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_file(std::move(file_types), std::move(callback));
#elif __ANDROID__ #elif __ANDROID__
android_pick_file(callback); android_pick_file(callback);
#elif __LINUX__ #elif __LINUX__
@@ -598,7 +426,7 @@ public:
void pick_save_file(std::vector<std::string> file_types, pp::platform::PickedPathCallback callback) override void pick_save_file(std::vector<std::string> file_types, pp::platform::PickedPathCallback callback) override
{ {
#if __OSX__ #if __OSX__
active_apple_document_platform_services().pick_save_file(std::move(file_types), std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_save_file(std::move(file_types), std::move(callback));
#elif __ANDROID__ #elif __ANDROID__
android_pick_file_save(callback); android_pick_file_save(callback);
#else #else
@@ -612,7 +440,7 @@ public:
#ifdef __IOS__ #ifdef __IOS__
(void)callback; (void)callback;
#elif __OSX__ #elif __OSX__
active_apple_document_platform_services().pick_directory(std::move(callback)); pp::platform::legacy::active_legacy_apple_document_platform_services().pick_directory(std::move(callback));
#elif __ANDROID__ #elif __ANDROID__
(void)callback; (void)callback;
#else #else
@@ -623,7 +451,7 @@ public:
[[nodiscard]] bool supports_working_directory_picker() override [[nodiscard]] bool supports_working_directory_picker() override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
return active_apple_document_platform_services().supports_working_directory_picker(); return pp::platform::legacy::active_legacy_apple_document_platform_services().supports_working_directory_picker();
#else #else
return pp::platform::platform_supports_working_directory_picker( return pp::platform::platform_supports_working_directory_picker(
pp::platform::current_platform_family()); pp::platform::current_platform_family());
@@ -633,7 +461,7 @@ public:
[[nodiscard]] std::string format_working_directory_path(std::string_view path) override [[nodiscard]] std::string format_working_directory_path(std::string_view path) override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
return active_apple_document_platform_services().format_working_directory_path(path); return pp::platform::legacy::active_legacy_apple_document_platform_services().format_working_directory_path(path);
#endif #endif
return std::string(path); return std::string(path);
} }
@@ -669,7 +497,7 @@ public:
void start_sonarpen() override void start_sonarpen() override
{ {
#if __IOS__ #if __IOS__
active_apple_document_platform_services().start_sonarpen(); pp::platform::legacy::active_legacy_apple_document_platform_services().start_sonarpen();
#endif #endif
} }
@@ -715,7 +543,7 @@ public:
void display_file(std::string_view path) override void display_file(std::string_view path) override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().display_file(path); pp::platform::legacy::active_legacy_apple_document_platform_services().display_file(path);
#else #else
(void)path; (void)path;
#endif #endif
@@ -724,7 +552,7 @@ public:
void share_file(std::string_view path) override void share_file(std::string_view path) override
{ {
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
active_apple_document_platform_services().share_file(path); pp::platform::legacy::active_legacy_apple_document_platform_services().share_file(path);
#else #else
(void)path; (void)path;
#endif #endif
@@ -733,7 +561,7 @@ public:
void request_app_close() override void request_app_close() override
{ {
#ifdef __OSX__ #ifdef __OSX__
active_apple_document_platform_services().request_app_close(); pp::platform::legacy::active_legacy_apple_document_platform_services().request_app_close();
#elif __LINUX__ #elif __LINUX__
pp::platform::legacy::active_legacy_glfw_window_hooks().request_app_close(); pp::platform::legacy::active_legacy_glfw_window_hooks().request_app_close();
#endif #endif
@@ -766,7 +594,7 @@ public:
const std::string value(path); const std::string value(path);
const std::string name(suggested_name); const std::string name(suggested_name);
#ifdef __IOS__ #ifdef __IOS__
active_apple_document_platform_services().save_prepared_file( pp::platform::legacy::active_legacy_apple_document_platform_services().save_prepared_file(
value, value,
name, name,
std::move(callback)); std::move(callback));

View File

@@ -1,6 +1,11 @@
#include "pch.h" #include "pch.h"
#include "platform_legacy/legacy_platform_state.h" #include "platform_legacy/legacy_platform_state.h"
#if defined(__APPLE__)
#include <Foundation/Foundation.h>
#include "objc_utils.h"
#endif
#if defined(__LINUX__) || defined(__WEB__) #if defined(__LINUX__) || defined(__WEB__)
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#endif #endif
@@ -18,6 +23,187 @@ struct RetainedLegacyStoragePaths final {
return state; return state;
} }
#if defined(__IOS__) || defined(__OSX__)
struct RetainedLegacyAppleDocumentPlatformState final {
std::unique_ptr<pp::platform::apple::AppleDocumentPlatformServices> services;
};
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
{
NSMutableArray<NSString*>* types = [NSMutableArray arrayWithCapacity:file_types.size()];
for (const auto& type : file_types)
{
[types addObject:[NSString stringWithCString:type.c_str() encoding:NSUTF8StringEncoding]];
}
return types;
}
[[nodiscard]] RetainedLegacyAppleDocumentPlatformState& retained_legacy_apple_document_platform_state()
{
static RetainedLegacyAppleDocumentPlatformState state;
return state;
}
#ifdef __IOS__
[[nodiscard]] pp::platform::apple::AppleDocumentPickerBridge make_legacy_apple_document_picker_bridge()
{
const auto& apple_state = active_legacy_apple_state();
auto* const ios_view = apple_state.ios_view;
auto* const ios_app = apple_state.ios_app;
pp::platform::apple::AppleDocumentPickerBridge bridge;
bridge.clipboard_text = [ios_view] {
return [ios_view clipboard_get_string];
};
bridge.set_clipboard_text = [ios_view](std::string_view text) {
const std::string value(text);
return [ios_view clipboard_set_string:value];
};
bridge.set_virtual_keyboard_visible = [ios_view](bool visible) {
dispatch_async(dispatch_get_main_queue(), ^{
if (visible)
[ios_view show_keyboard];
else
[ios_view hide_keyboard];
});
};
bridge.trigger_crash_test = [ios_view] {
[ios_view crash];
};
bridge.start_sonarpen = [ios_app] {
[ios_app sonarpen_start];
};
bridge.acquire_render_context = [ios_view] {
[ios_view async_lock];
};
bridge.release_render_context = [ios_view] {
[ios_view async_unlock];
};
bridge.present_render_context = [ios_view] {
[ios_view async_swap];
};
bridge.bind_main_render_target = [ios_view] {
[ios_view->glview bindDrawable];
};
bridge.display_file = [ios_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view display_file:path];
});
};
bridge.share_file = [ios_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view share_file:[NSString stringWithUTF8String:path.c_str()]];
});
};
bridge.pick_image = [ios_view](pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_photo:callback];
});
};
bridge.pick_file = [ios_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_file:apple_file_types_array(file_types) then:callback];
});
};
bridge.save_prepared_file = [ios_view](
std::string path,
std::string suggested_name,
pp::platform::PreparedFileCallback callback) {
(void)suggested_name;
dispatch_async(dispatch_get_main_queue(), ^{
[ios_view pick_file_save:path];
});
callback(path, true);
};
return bridge;
}
#elif defined(__OSX__)
[[nodiscard]] pp::platform::apple::AppleDocumentPickerBridge make_legacy_apple_document_picker_bridge()
{
const auto& apple_state = active_legacy_apple_state();
auto* const osx_view = apple_state.osx_view;
auto* const osx_app = apple_state.osx_app;
pp::platform::apple::AppleDocumentPickerBridge bridge;
bridge.clipboard_text = [osx_view] {
return [osx_view clipboard_get_string];
};
bridge.set_clipboard_text = [osx_view](std::string_view text) {
const std::string value(text);
return [osx_view clipboard_set_string:value];
};
bridge.share_file = [osx_view](std::string path) {
dispatch_async(dispatch_get_main_queue(), ^{
[osx_view share_file:[NSString stringWithUTF8String:path.c_str()]];
});
};
bridge.trigger_crash_test = [osx_view] {
[osx_view hockeyapp_crash];
};
bridge.request_app_close = [osx_view] {
dispatch_async(dispatch_get_main_queue(), ^{
[osx_view close];
});
};
bridge.acquire_render_context = [osx_view] {
[osx_view async_lock];
};
bridge.release_render_context = [osx_view] {
[osx_view async_unlock];
};
bridge.present_render_context = [osx_view] {
[osx_view async_swap];
};
bridge.set_cursor_visible = [osx_view](bool visible) {
[osx_view show_cursor:visible];
};
bridge.save_ui_state = [osx_app] {
[osx_app save_ui_state];
};
bridge.pick_file = [osx_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_file:apple_file_types_array(file_types)];
callback(path);
});
};
bridge.pick_save_file = [osx_view](
std::vector<std::string> file_types,
pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_file_save:apple_file_types_array(file_types)];
callback(path);
});
};
bridge.pick_directory = [osx_view](pp::platform::PickedPathCallback callback) {
dispatch_async(dispatch_get_main_queue(), ^{
const std::string path = [osx_view pick_dir];
callback(path);
});
};
bridge.format_working_directory_path = [](std::string_view path) {
char path_buffer[4096] = {};
if (realpath(std::string(path).c_str(), path_buffer))
return std::string(path_buffer);
return std::string(path);
};
return bridge;
}
#endif
[[nodiscard]] pp::platform::PlatformFamily legacy_apple_platform_family()
{
#ifdef __IOS__
return pp::platform::PlatformFamily::ios;
#else
return pp::platform::PlatformFamily::macos;
#endif
}
#endif
} }
#if defined(__LINUX__) || defined(__WEB__) #if defined(__LINUX__) || defined(__WEB__)
@@ -55,6 +241,19 @@ void set_legacy_glfw_window(GLFWwindow* window)
return state; return state;
} }
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices&
active_legacy_apple_document_platform_services()
{
auto& retained = retained_legacy_apple_document_platform_state();
if (!retained.services)
{
retained.services = std::make_unique<pp::platform::apple::AppleDocumentPlatformServices>(
legacy_apple_platform_family(),
make_legacy_apple_document_picker_bridge());
}
return *retained.services;
}
void set_legacy_apple_state( void set_legacy_apple_state(
#ifdef __IOS__ #ifdef __IOS__
GameViewController* ios_view, GameViewController* ios_view,
@@ -66,17 +265,32 @@ void set_legacy_apple_state(
) )
{ {
auto& retained = active_legacy_apple_state(); auto& retained = active_legacy_apple_state();
bool changed = false;
#ifdef __IOS__ #ifdef __IOS__
if (ios_view) if (ios_view)
{
changed = changed || retained.ios_view != ios_view;
retained.ios_view = ios_view; retained.ios_view = ios_view;
}
if (ios_app) if (ios_app)
{
changed = changed || retained.ios_app != ios_app;
retained.ios_app = ios_app; retained.ios_app = ios_app;
}
#elif defined(__OSX__) #elif defined(__OSX__)
if (osx_view) if (osx_view)
{
changed = changed || retained.osx_view != osx_view;
retained.osx_view = osx_view; retained.osx_view = osx_view;
}
if (osx_app) if (osx_app)
{
changed = changed || retained.osx_app != osx_app;
retained.osx_app = osx_app; retained.osx_app = osx_app;
}
#endif #endif
if (changed)
retained_legacy_apple_document_platform_state().services.reset();
} }
#endif #endif

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "platform_apple/apple_platform_services.h"
#include "platform_api/platform_services.h" #include "platform_api/platform_services.h"
#if __LINUX__ || __WEB__ #if __LINUX__ || __WEB__
@@ -47,6 +48,8 @@ struct RetainedLegacyAppleState final {
}; };
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state(); [[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state();
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices&
active_legacy_apple_document_platform_services();
void set_legacy_apple_state( void set_legacy_apple_state(
#ifdef __IOS__ #ifdef __IOS__
GameViewController* ios_view, GameViewController* ios_view,

View File

@@ -4,6 +4,7 @@
#include "app.h" #include "app.h"
#include "legacy_preference_storage.h" #include "legacy_preference_storage.h"
#include "platform_windows/windows_runtime_shell.h"
#include "platform_windows/windows_stylus_input.h" #include "platform_windows/windows_stylus_input.h"
namespace pp::platform::windows { namespace pp::platform::windows {
@@ -50,6 +51,7 @@ void handle_window_close_message(VrShellState& vr)
App::I->runtime().ui_thread_stop(); App::I->runtime().ui_thread_stop();
App::I->runtime().render_thread_stop(); App::I->runtime().render_thread_stop();
App::I->terminate(); App::I->terminate();
bind_runtime(nullptr);
delete App::I; delete App::I;
PostQuitMessage(0); PostQuitMessage(0);
} }

View File

@@ -2,9 +2,11 @@
#include "platform_windows/windows_bootstrap_helpers.h" #include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_lifecycle_shell.h" #include "platform_windows/windows_lifecycle_shell.h"
#include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_runtime_shell.h"
#include "platform_windows/windows_stylus_input.h" #include "platform_windows/windows_stylus_input.h"
#include "platform_windows/windows_window_shell.h" #include "platform_windows/windows_window_shell.h"
#include "app_runtime.h"
#include "log.h" #include "log.h"
#include "legacy_gl_runtime_dispatch.h" #include "legacy_gl_runtime_dispatch.h"
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
@@ -171,18 +173,25 @@ void swap_async_render_context()
void enqueue_main_thread_task(std::packaged_task<void()> task) void enqueue_main_thread_task(std::packaged_task<void()> task)
{ {
if (!App::I) if (auto* runtime = bound_runtime())
{ {
task(); runtime->main_thread_task(std::move(task));
return; return;
} }
App::I->runtime().main_thread_task(std::move(task));
if (!task.valid())
return;
task();
} }
void drain_main_thread_tasks() void drain_main_thread_tasks()
{ {
if (App::I) if (auto* runtime = bound_runtime())
App::I->runtime().drain_main_thread_tasks(); {
runtime->drain_main_thread_tasks();
return;
}
} }
} // namespace pp::platform::windows } // namespace pp::platform::windows

View File

@@ -3,6 +3,7 @@
#include "platform_windows/windows_runtime_shell.h" #include "platform_windows/windows_runtime_shell.h"
#include "app.h" #include "app.h"
#include "app_runtime.h"
#include "log.h" #include "log.h"
#include "platform_windows/windows_bootstrap_helpers.h" #include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_lifecycle_shell.h" #include "platform_windows/windows_lifecycle_shell.h"
@@ -16,6 +17,16 @@ namespace pp::platform::windows {
namespace { namespace {
struct RetainedWindowsRuntimeState final {
AppRuntime* runtime = nullptr;
};
[[nodiscard]] RetainedWindowsRuntimeState& retained_runtime_state()
{
static RetainedWindowsRuntimeState state;
return state;
}
void register_touch_window(HWND hWnd) void register_touch_window(HWND hWnd)
{ {
// link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow // link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow
@@ -102,12 +113,23 @@ void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTAN
} }
void bind_runtime(AppRuntime* runtime) noexcept
{
retained_runtime_state().runtime = runtime;
}
AppRuntime* bound_runtime() noexcept
{
return retained_runtime_state().runtime;
}
int run_main_application(int argc, char** argv) int run_main_application(int argc, char** argv)
{ {
auto& state = retained_state(); auto& state = retained_state();
state.hInst = GetModuleHandle(NULL); state.hInst = GetModuleHandle(NULL);
App::I = new App(); App::I = new App();
bind_runtime(&App::I->runtime());
App::I->set_platform_services(&pp::platform::windows::platform_services()); App::I->set_platform_services(&pp::platform::windows::platform_services());
App::I->initLog(); App::I->initLog();
@@ -136,8 +158,10 @@ int run_main_application(int argc, char** argv)
case pp::platform::windows::MainStartupResult::Ok: case pp::platform::windows::MainStartupResult::Ok:
break; break;
case pp::platform::windows::MainStartupResult::GladLoadFailure: case pp::platform::windows::MainStartupResult::GladLoadFailure:
bind_runtime(nullptr);
return 0; return 0;
case pp::platform::windows::MainStartupResult::MissingCoreContextSupport: case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
bind_runtime(nullptr);
return -1; return -1;
} }
@@ -151,6 +175,7 @@ int run_main_application(int argc, char** argv)
case const_hash("convert"): case const_hash("convert"):
App::I->initShaders(); App::I->initShaders();
App::I->cmd_convert(argv[2], argv[3]); App::I->cmd_convert(argv[2], argv[3]);
bind_runtime(nullptr);
return 0; return 0;
case const_hash("-vrmode"): case const_hash("-vrmode"):
start_in_vr = true; start_in_vr = true;

View File

@@ -3,9 +3,13 @@
#include "platform_windows/windows_bootstrap_helpers.h" #include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_splash.h" #include "platform_windows/windows_splash.h"
class AppRuntime;
namespace pp::platform::windows { namespace pp::platform::windows {
int run_main_application(int argc, char** argv); int run_main_application(int argc, char** argv);
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash); void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash);
void bind_runtime(AppRuntime* runtime) noexcept;
[[nodiscard]] AppRuntime* bound_runtime() noexcept;
} }