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

@@ -1,6 +1,11 @@
#include "pch.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__)
#include <GLFW/glfw3.h>
#endif
@@ -18,6 +23,187 @@ struct RetainedLegacyStoragePaths final {
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__)
@@ -55,6 +241,19 @@ void set_legacy_glfw_window(GLFWwindow* window)
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(
#ifdef __IOS__
GameViewController* ios_view,
@@ -66,17 +265,32 @@ void set_legacy_apple_state(
)
{
auto& retained = active_legacy_apple_state();
bool changed = false;
#ifdef __IOS__
if (ios_view)
{
changed = changed || retained.ios_view != ios_view;
retained.ios_view = ios_view;
}
if (ios_app)
{
changed = changed || retained.ios_app != ios_app;
retained.ios_app = ios_app;
}
#elif defined(__OSX__)
if (osx_view)
{
changed = changed || retained.osx_view != osx_view;
retained.osx_view = osx_view;
}
if (osx_app)
{
changed = changed || retained.osx_app != osx_app;
retained.osx_app = osx_app;
}
#endif
if (changed)
retained_legacy_apple_document_platform_state().services.reset();
}
#endif