diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/common b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/common deleted file mode 120000 index 9388f34..0000000 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/common +++ /dev/null @@ -1 +0,0 @@ -../../../../../include/common/ \ No newline at end of file diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-activity/native_app_glue/android_native_app_glue.h b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-activity/native_app_glue/android_native_app_glue.h index b0769c5..3cabe73 100644 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-activity/native_app_glue/android_native_app_glue.h +++ b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-activity/native_app_glue/android_native_app_glue.h @@ -201,6 +201,9 @@ struct android_app { /** The ALooper associated with the app's thread. */ ALooper* looper; + /** The ALooper associated with the app's Java main/UI thread. */ + ALooper* mainLooper; + /** When non-NULL, this is the window surface that the app can draw in. */ ANativeWindow* window; @@ -511,6 +514,16 @@ void android_app_clear_motion_events(struct android_input_buffer* inputBuffer); */ void android_app_clear_key_events(struct android_input_buffer* inputBuffer); +/** + * A hook that is called within Activity.onCreate, before the android_main + * thread has been spawned. + * + * This gives the Rust glue code a chance to perform any necessary + * initialization that needs to run from the Java main/UI thread, before the + * android_main thread is started. + */ +extern void _rust_glue_on_create_hook(struct android_app* app); + /** * This is a springboard into the Rust glue layer that wraps calling the * main entry for the app itself. diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-text-input/gametextinput.h b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-text-input/gametextinput.h deleted file mode 120000 index 84e9337..0000000 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/include/game-text-input/gametextinput.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../game-text-input/prefab-src/modules/game-text-input/include/game-text-input/gametextinput.h \ No newline at end of file diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/common/system_utils.cpp b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/common/system_utils.cpp deleted file mode 120000 index 713dcbb..0000000 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/common/system_utils.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../../../../src/common/system_utils.cpp \ No newline at end of file diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-activity/native_app_glue/android_native_app_glue.c b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-activity/native_app_glue/android_native_app_glue.c index 4422ec6..7fd9d39 100644 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-activity/native_app_glue/android_native_app_glue.c +++ b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-activity/native_app_glue/android_native_app_glue.c @@ -224,6 +224,8 @@ static void* android_app_entry(void* param) { android_app->cmdPollSource.app = android_app; android_app->cmdPollSource.process = process_cmd; + _rust_glue_on_create_hook(android_app); + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, &android_app->cmdPollSource); @@ -290,6 +292,13 @@ static struct android_app* android_app_create(GameActivity* activity, memcpy(android_app->savedState, savedState, savedStateSize); } + android_app->mainLooper = ALooper_forThread(); + if (android_app->mainLooper == NULL) { + LOGE("Failed to get main looper"); + return NULL; + } + ALooper_acquire(android_app->mainLooper); + int msgpipe[2]; if (pipe(msgpipe)) { LOGE("could not create pipe: %s", strerror(errno)); @@ -396,8 +405,14 @@ static void android_app_free(struct android_app* android_app) { close(android_app->msgread); close(android_app->msgwrite); + pthread_cond_destroy(&android_app->cond); pthread_mutex_destroy(&android_app->mutex); + + if (android_app->mainLooper != NULL) { + ALooper_release(android_app->mainLooper); + } + free(android_app); } diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.cpp b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.cpp deleted file mode 120000 index 3deaa67..0000000 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.cpp +++ /dev/null @@ -1 +0,0 @@ -../../../../../../game-text-input/prefab-src/modules/game-text-input/src/game-text-input/gametextinput.cpp \ No newline at end of file diff --git a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.h b/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.h deleted file mode 120000 index 84e9337..0000000 --- a/android-activity/android-games-sdk/game-activity/prefab-src/modules/game-activity/src/game-text-input/gametextinput.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../../game-text-input/prefab-src/modules/game-text-input/include/game-text-input/gametextinput.h \ No newline at end of file diff --git a/android-activity/android-games-sdk/game-text-input/prefab-src/modules/game-text-input/include/common b/android-activity/android-games-sdk/game-text-input/prefab-src/modules/game-text-input/include/common deleted file mode 120000 index 9388f34..0000000 --- a/android-activity/android-games-sdk/game-text-input/prefab-src/modules/game-text-input/include/common +++ /dev/null @@ -1 +0,0 @@ -../../../../../include/common/ \ No newline at end of file diff --git a/android-activity/android-games-sdk/import-games-sdk.sh b/android-activity/android-games-sdk/import-games-sdk.sh index 83bdf9f..21351d3 100755 --- a/android-activity/android-games-sdk/import-games-sdk.sh +++ b/android-activity/android-games-sdk/import-games-sdk.sh @@ -42,4 +42,14 @@ cp -av "$SOURCE_DIR/game-activity/prefab-src" "$DEST_DIR/game-activity" cp -av "$SOURCE_DIR/game-text-input/prefab-src" "$DEST_DIR/game-text-input" cp -av "$SOURCE_DIR/include/common/gamesdk_common.h" "$DEST_DIR/include/common" cp -av "$SOURCE_DIR/src/common/system_utils.h" "$DEST_DIR/src/common" -cp -av "$SOURCE_DIR/src/common/system_utils.cpp" "$DEST_DIR/src/common" \ No newline at end of file +cp -av "$SOURCE_DIR/src/common/system_utils.cpp" "$DEST_DIR/src/common" + +# Remove symlinks so the android-activity crate is easily buildable +# from Git on Windows. + +rm "$DEST_DIR/game-activity/prefab-src/modules/game-activity/include/common" +rm -fr "$DEST_DIR/game-activity/prefab-src/modules/game-activity/include/game-text-input" +rm -fr "$DEST_DIR/game-activity/prefab-src/modules/game-activity/src/common" +rm -fr "$DEST_DIR/game-activity/prefab-src/modules/game-activity/src/game-text-input" + +rm "$DEST_DIR/game-text-input/prefab-src/modules/game-text-input/include/common" diff --git a/android-activity/src/game_activity/ffi_aarch64.rs b/android-activity/src/game_activity/ffi_aarch64.rs index 17bf8ca..a755087 100644 --- a/android-activity/src/game_activity/ffi_aarch64.rs +++ b/android-activity/src/game_activity/ffi_aarch64.rs @@ -4675,6 +4675,8 @@ pub struct android_app { pub savedStateSize: usize, #[doc = " The ALooper associated with the app's thread."] pub looper: *mut ALooper, + #[doc = " The ALooper associated with the app's Java main/UI thread."] + pub mainLooper: *mut ALooper, #[doc = " When non-NULL, this is the window surface that the app can draw in."] pub window: *mut ANativeWindow, #[doc = " Current content rectangle of the window; this is the area where the\n window's content should be placed to be seen by the user."] @@ -4714,7 +4716,7 @@ pub struct android_app { } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { - ["Size of android_app"][::std::mem::size_of::() - 400usize]; + ["Size of android_app"][::std::mem::size_of::() - 408usize]; ["Alignment of android_app"][::std::mem::align_of::() - 8usize]; ["Offset of field: android_app::userData"] [::std::mem::offset_of!(android_app, userData) - 0usize]; @@ -4728,55 +4730,57 @@ const _: () = { ["Offset of field: android_app::savedStateSize"] [::std::mem::offset_of!(android_app, savedStateSize) - 40usize]; ["Offset of field: android_app::looper"][::std::mem::offset_of!(android_app, looper) - 48usize]; - ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 56usize]; + ["Offset of field: android_app::mainLooper"] + [::std::mem::offset_of!(android_app, mainLooper) - 56usize]; + ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 64usize]; ["Offset of field: android_app::contentRect"] - [::std::mem::offset_of!(android_app, contentRect) - 64usize]; + [::std::mem::offset_of!(android_app, contentRect) - 72usize]; ["Offset of field: android_app::softwareKeyboardVisible"] - [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 80usize]; + [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 88usize]; ["Offset of field: android_app::editorAction"] - [::std::mem::offset_of!(android_app, editorAction) - 84usize]; + [::std::mem::offset_of!(android_app, editorAction) - 92usize]; ["Offset of field: android_app::pendingEditorAction"] - [::std::mem::offset_of!(android_app, pendingEditorAction) - 88usize]; + [::std::mem::offset_of!(android_app, pendingEditorAction) - 96usize]; ["Offset of field: android_app::activityState"] - [::std::mem::offset_of!(android_app, activityState) - 92usize]; + [::std::mem::offset_of!(android_app, activityState) - 100usize]; ["Offset of field: android_app::destroyRequested"] - [::std::mem::offset_of!(android_app, destroyRequested) - 96usize]; + [::std::mem::offset_of!(android_app, destroyRequested) - 104usize]; ["Offset of field: android_app::inputBuffers"] - [::std::mem::offset_of!(android_app, inputBuffers) - 104usize]; + [::std::mem::offset_of!(android_app, inputBuffers) - 112usize]; ["Offset of field: android_app::currentInputBuffer"] - [::std::mem::offset_of!(android_app, currentInputBuffer) - 200usize]; + [::std::mem::offset_of!(android_app, currentInputBuffer) - 208usize]; ["Offset of field: android_app::textInputState"] - [::std::mem::offset_of!(android_app, textInputState) - 204usize]; - ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 208usize]; - ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 248usize]; + [::std::mem::offset_of!(android_app, textInputState) - 212usize]; + ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 216usize]; + ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 256usize]; ["Offset of field: android_app::msgread"] - [::std::mem::offset_of!(android_app, msgread) - 296usize]; + [::std::mem::offset_of!(android_app, msgread) - 304usize]; ["Offset of field: android_app::msgwrite"] - [::std::mem::offset_of!(android_app, msgwrite) - 300usize]; + [::std::mem::offset_of!(android_app, msgwrite) - 308usize]; ["Offset of field: android_app::thread"] - [::std::mem::offset_of!(android_app, thread) - 304usize]; + [::std::mem::offset_of!(android_app, thread) - 312usize]; ["Offset of field: android_app::cmdPollSource"] - [::std::mem::offset_of!(android_app, cmdPollSource) - 312usize]; + [::std::mem::offset_of!(android_app, cmdPollSource) - 320usize]; ["Offset of field: android_app::running"] - [::std::mem::offset_of!(android_app, running) - 336usize]; + [::std::mem::offset_of!(android_app, running) - 344usize]; ["Offset of field: android_app::stateSaved"] - [::std::mem::offset_of!(android_app, stateSaved) - 340usize]; + [::std::mem::offset_of!(android_app, stateSaved) - 348usize]; ["Offset of field: android_app::destroyed"] - [::std::mem::offset_of!(android_app, destroyed) - 344usize]; + [::std::mem::offset_of!(android_app, destroyed) - 352usize]; ["Offset of field: android_app::redrawNeeded"] - [::std::mem::offset_of!(android_app, redrawNeeded) - 348usize]; + [::std::mem::offset_of!(android_app, redrawNeeded) - 356usize]; ["Offset of field: android_app::pendingWindow"] - [::std::mem::offset_of!(android_app, pendingWindow) - 352usize]; + [::std::mem::offset_of!(android_app, pendingWindow) - 360usize]; ["Offset of field: android_app::pendingContentRect"] - [::std::mem::offset_of!(android_app, pendingContentRect) - 360usize]; + [::std::mem::offset_of!(android_app, pendingContentRect) - 368usize]; ["Offset of field: android_app::keyEventFilter"] - [::std::mem::offset_of!(android_app, keyEventFilter) - 376usize]; + [::std::mem::offset_of!(android_app, keyEventFilter) - 384usize]; ["Offset of field: android_app::motionEventFilter"] - [::std::mem::offset_of!(android_app, motionEventFilter) - 384usize]; + [::std::mem::offset_of!(android_app, motionEventFilter) - 392usize]; ["Offset of field: android_app::inputAvailableWakeUp"] - [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 392usize]; + [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 400usize]; ["Offset of field: android_app::inputSwapPending"] - [::std::mem::offset_of!(android_app, inputSwapPending) - 393usize]; + [::std::mem::offset_of!(android_app, inputSwapPending) - 401usize]; }; #[doc = " Looper data ID of commands coming from the app's main thread, which\n is returned as an identifier from ALooper_pollOnce(). The data for this\n identifier is a pointer to an android_poll_source structure.\n These can be retrieved and processed with android_app_read_cmd()\n and android_app_exec_cmd()."] pub const NativeAppGlueLooperId_LOOPER_ID_MAIN: NativeAppGlueLooperId = 1; @@ -4850,6 +4854,10 @@ unsafe extern "C" { #[doc = " Clear the array of key events that were waiting to be handled, and release\n each of them.\n\n This method should be called after you have processed the key up events in\n your game loop. You should handle events at each iteration of your game loop."] pub fn android_app_clear_key_events(inputBuffer: *mut android_input_buffer); } +unsafe extern "C" { + #[doc = " A hook that is called within Activity.onCreate, before the android_main\n thread has been spawned.\n\n This gives the Rust glue code a chance to perform any necessary\n initialization that needs to run from the Java main/UI thread, before the\n android_main thread is started."] + pub fn _rust_glue_on_create_hook(app: *mut android_app); +} unsafe extern "C" { #[doc = " This is a springboard into the Rust glue layer that wraps calling the\n main entry for the app itself."] pub fn _rust_glue_entry(app: *mut android_app); diff --git a/android-activity/src/game_activity/ffi_arm.rs b/android-activity/src/game_activity/ffi_arm.rs index 5a6cccc..f3b28a9 100644 --- a/android-activity/src/game_activity/ffi_arm.rs +++ b/android-activity/src/game_activity/ffi_arm.rs @@ -5087,6 +5087,8 @@ pub struct android_app { pub savedStateSize: usize, #[doc = " The ALooper associated with the app's thread."] pub looper: *mut ALooper, + #[doc = " The ALooper associated with the app's Java main/UI thread."] + pub mainLooper: *mut ALooper, #[doc = " When non-NULL, this is the window surface that the app can draw in."] pub window: *mut ANativeWindow, #[doc = " Current content rectangle of the window; this is the area where the\n window's content should be placed to be seen by the user."] @@ -5140,19 +5142,21 @@ const _: () = { ["Offset of field: android_app::savedStateSize"] [::std::mem::offset_of!(android_app, savedStateSize) - 20usize]; ["Offset of field: android_app::looper"][::std::mem::offset_of!(android_app, looper) - 24usize]; - ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 28usize]; + ["Offset of field: android_app::mainLooper"] + [::std::mem::offset_of!(android_app, mainLooper) - 28usize]; + ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 32usize]; ["Offset of field: android_app::contentRect"] - [::std::mem::offset_of!(android_app, contentRect) - 32usize]; + [::std::mem::offset_of!(android_app, contentRect) - 36usize]; ["Offset of field: android_app::softwareKeyboardVisible"] - [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 48usize]; + [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 52usize]; ["Offset of field: android_app::editorAction"] - [::std::mem::offset_of!(android_app, editorAction) - 52usize]; + [::std::mem::offset_of!(android_app, editorAction) - 56usize]; ["Offset of field: android_app::pendingEditorAction"] - [::std::mem::offset_of!(android_app, pendingEditorAction) - 56usize]; + [::std::mem::offset_of!(android_app, pendingEditorAction) - 60usize]; ["Offset of field: android_app::activityState"] - [::std::mem::offset_of!(android_app, activityState) - 60usize]; + [::std::mem::offset_of!(android_app, activityState) - 64usize]; ["Offset of field: android_app::destroyRequested"] - [::std::mem::offset_of!(android_app, destroyRequested) - 64usize]; + [::std::mem::offset_of!(android_app, destroyRequested) - 68usize]; ["Offset of field: android_app::inputBuffers"] [::std::mem::offset_of!(android_app, inputBuffers) - 72usize]; ["Offset of field: android_app::currentInputBuffer"] @@ -5262,6 +5266,10 @@ unsafe extern "C" { #[doc = " Clear the array of key events that were waiting to be handled, and release\n each of them.\n\n This method should be called after you have processed the key up events in\n your game loop. You should handle events at each iteration of your game loop."] pub fn android_app_clear_key_events(inputBuffer: *mut android_input_buffer); } +unsafe extern "C" { + #[doc = " A hook that is called within Activity.onCreate, before the android_main\n thread has been spawned.\n\n This gives the Rust glue code a chance to perform any necessary\n initialization that needs to run from the Java main/UI thread, before the\n android_main thread is started."] + pub fn _rust_glue_on_create_hook(app: *mut android_app); +} unsafe extern "C" { #[doc = " This is a springboard into the Rust glue layer that wraps calling the\n main entry for the app itself."] pub fn _rust_glue_entry(app: *mut android_app); diff --git a/android-activity/src/game_activity/ffi_i686.rs b/android-activity/src/game_activity/ffi_i686.rs index b71a13e..7ead1e9 100644 --- a/android-activity/src/game_activity/ffi_i686.rs +++ b/android-activity/src/game_activity/ffi_i686.rs @@ -5127,6 +5127,8 @@ pub struct android_app { pub savedStateSize: usize, #[doc = " The ALooper associated with the app's thread."] pub looper: *mut ALooper, + #[doc = " The ALooper associated with the app's Java main/UI thread."] + pub mainLooper: *mut ALooper, #[doc = " When non-NULL, this is the window surface that the app can draw in."] pub window: *mut ANativeWindow, #[doc = " Current content rectangle of the window; this is the area where the\n window's content should be placed to be seen by the user."] @@ -5166,7 +5168,7 @@ pub struct android_app { } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { - ["Size of android_app"][::std::mem::size_of::() - 236usize]; + ["Size of android_app"][::std::mem::size_of::() - 240usize]; ["Alignment of android_app"][::std::mem::align_of::() - 4usize]; ["Offset of field: android_app::userData"] [::std::mem::offset_of!(android_app, userData) - 0usize]; @@ -5180,55 +5182,57 @@ const _: () = { ["Offset of field: android_app::savedStateSize"] [::std::mem::offset_of!(android_app, savedStateSize) - 20usize]; ["Offset of field: android_app::looper"][::std::mem::offset_of!(android_app, looper) - 24usize]; - ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 28usize]; + ["Offset of field: android_app::mainLooper"] + [::std::mem::offset_of!(android_app, mainLooper) - 28usize]; + ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 32usize]; ["Offset of field: android_app::contentRect"] - [::std::mem::offset_of!(android_app, contentRect) - 32usize]; + [::std::mem::offset_of!(android_app, contentRect) - 36usize]; ["Offset of field: android_app::softwareKeyboardVisible"] - [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 48usize]; + [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 52usize]; ["Offset of field: android_app::editorAction"] - [::std::mem::offset_of!(android_app, editorAction) - 52usize]; + [::std::mem::offset_of!(android_app, editorAction) - 56usize]; ["Offset of field: android_app::pendingEditorAction"] - [::std::mem::offset_of!(android_app, pendingEditorAction) - 56usize]; + [::std::mem::offset_of!(android_app, pendingEditorAction) - 60usize]; ["Offset of field: android_app::activityState"] - [::std::mem::offset_of!(android_app, activityState) - 60usize]; + [::std::mem::offset_of!(android_app, activityState) - 64usize]; ["Offset of field: android_app::destroyRequested"] - [::std::mem::offset_of!(android_app, destroyRequested) - 64usize]; + [::std::mem::offset_of!(android_app, destroyRequested) - 68usize]; ["Offset of field: android_app::inputBuffers"] - [::std::mem::offset_of!(android_app, inputBuffers) - 68usize]; + [::std::mem::offset_of!(android_app, inputBuffers) - 72usize]; ["Offset of field: android_app::currentInputBuffer"] - [::std::mem::offset_of!(android_app, currentInputBuffer) - 148usize]; + [::std::mem::offset_of!(android_app, currentInputBuffer) - 152usize]; ["Offset of field: android_app::textInputState"] - [::std::mem::offset_of!(android_app, textInputState) - 152usize]; - ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 156usize]; - ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 160usize]; + [::std::mem::offset_of!(android_app, textInputState) - 156usize]; + ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 160usize]; + ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 164usize]; ["Offset of field: android_app::msgread"] - [::std::mem::offset_of!(android_app, msgread) - 164usize]; + [::std::mem::offset_of!(android_app, msgread) - 168usize]; ["Offset of field: android_app::msgwrite"] - [::std::mem::offset_of!(android_app, msgwrite) - 168usize]; + [::std::mem::offset_of!(android_app, msgwrite) - 172usize]; ["Offset of field: android_app::thread"] - [::std::mem::offset_of!(android_app, thread) - 172usize]; + [::std::mem::offset_of!(android_app, thread) - 176usize]; ["Offset of field: android_app::cmdPollSource"] - [::std::mem::offset_of!(android_app, cmdPollSource) - 176usize]; + [::std::mem::offset_of!(android_app, cmdPollSource) - 180usize]; ["Offset of field: android_app::running"] - [::std::mem::offset_of!(android_app, running) - 188usize]; + [::std::mem::offset_of!(android_app, running) - 192usize]; ["Offset of field: android_app::stateSaved"] - [::std::mem::offset_of!(android_app, stateSaved) - 192usize]; + [::std::mem::offset_of!(android_app, stateSaved) - 196usize]; ["Offset of field: android_app::destroyed"] - [::std::mem::offset_of!(android_app, destroyed) - 196usize]; + [::std::mem::offset_of!(android_app, destroyed) - 200usize]; ["Offset of field: android_app::redrawNeeded"] - [::std::mem::offset_of!(android_app, redrawNeeded) - 200usize]; + [::std::mem::offset_of!(android_app, redrawNeeded) - 204usize]; ["Offset of field: android_app::pendingWindow"] - [::std::mem::offset_of!(android_app, pendingWindow) - 204usize]; + [::std::mem::offset_of!(android_app, pendingWindow) - 208usize]; ["Offset of field: android_app::pendingContentRect"] - [::std::mem::offset_of!(android_app, pendingContentRect) - 208usize]; + [::std::mem::offset_of!(android_app, pendingContentRect) - 212usize]; ["Offset of field: android_app::keyEventFilter"] - [::std::mem::offset_of!(android_app, keyEventFilter) - 224usize]; + [::std::mem::offset_of!(android_app, keyEventFilter) - 228usize]; ["Offset of field: android_app::motionEventFilter"] - [::std::mem::offset_of!(android_app, motionEventFilter) - 228usize]; + [::std::mem::offset_of!(android_app, motionEventFilter) - 232usize]; ["Offset of field: android_app::inputAvailableWakeUp"] - [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 232usize]; + [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 236usize]; ["Offset of field: android_app::inputSwapPending"] - [::std::mem::offset_of!(android_app, inputSwapPending) - 233usize]; + [::std::mem::offset_of!(android_app, inputSwapPending) - 237usize]; }; #[doc = " Looper data ID of commands coming from the app's main thread, which\n is returned as an identifier from ALooper_pollOnce(). The data for this\n identifier is a pointer to an android_poll_source structure.\n These can be retrieved and processed with android_app_read_cmd()\n and android_app_exec_cmd()."] pub const NativeAppGlueLooperId_LOOPER_ID_MAIN: NativeAppGlueLooperId = 1; @@ -5302,6 +5306,10 @@ unsafe extern "C" { #[doc = " Clear the array of key events that were waiting to be handled, and release\n each of them.\n\n This method should be called after you have processed the key up events in\n your game loop. You should handle events at each iteration of your game loop."] pub fn android_app_clear_key_events(inputBuffer: *mut android_input_buffer); } +unsafe extern "C" { + #[doc = " A hook that is called within Activity.onCreate, before the android_main\n thread has been spawned.\n\n This gives the Rust glue code a chance to perform any necessary\n initialization that needs to run from the Java main/UI thread, before the\n android_main thread is started."] + pub fn _rust_glue_on_create_hook(app: *mut android_app); +} unsafe extern "C" { #[doc = " This is a springboard into the Rust glue layer that wraps calling the\n main entry for the app itself."] pub fn _rust_glue_entry(app: *mut android_app); diff --git a/android-activity/src/game_activity/ffi_x86_64.rs b/android-activity/src/game_activity/ffi_x86_64.rs index 5504712..7224c26 100644 --- a/android-activity/src/game_activity/ffi_x86_64.rs +++ b/android-activity/src/game_activity/ffi_x86_64.rs @@ -5156,6 +5156,8 @@ pub struct android_app { pub savedStateSize: usize, #[doc = " The ALooper associated with the app's thread."] pub looper: *mut ALooper, + #[doc = " The ALooper associated with the app's Java main/UI thread."] + pub mainLooper: *mut ALooper, #[doc = " When non-NULL, this is the window surface that the app can draw in."] pub window: *mut ANativeWindow, #[doc = " Current content rectangle of the window; this is the area where the\n window's content should be placed to be seen by the user."] @@ -5195,7 +5197,7 @@ pub struct android_app { } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { - ["Size of android_app"][::std::mem::size_of::() - 400usize]; + ["Size of android_app"][::std::mem::size_of::() - 408usize]; ["Alignment of android_app"][::std::mem::align_of::() - 8usize]; ["Offset of field: android_app::userData"] [::std::mem::offset_of!(android_app, userData) - 0usize]; @@ -5209,55 +5211,57 @@ const _: () = { ["Offset of field: android_app::savedStateSize"] [::std::mem::offset_of!(android_app, savedStateSize) - 40usize]; ["Offset of field: android_app::looper"][::std::mem::offset_of!(android_app, looper) - 48usize]; - ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 56usize]; + ["Offset of field: android_app::mainLooper"] + [::std::mem::offset_of!(android_app, mainLooper) - 56usize]; + ["Offset of field: android_app::window"][::std::mem::offset_of!(android_app, window) - 64usize]; ["Offset of field: android_app::contentRect"] - [::std::mem::offset_of!(android_app, contentRect) - 64usize]; + [::std::mem::offset_of!(android_app, contentRect) - 72usize]; ["Offset of field: android_app::softwareKeyboardVisible"] - [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 80usize]; + [::std::mem::offset_of!(android_app, softwareKeyboardVisible) - 88usize]; ["Offset of field: android_app::editorAction"] - [::std::mem::offset_of!(android_app, editorAction) - 84usize]; + [::std::mem::offset_of!(android_app, editorAction) - 92usize]; ["Offset of field: android_app::pendingEditorAction"] - [::std::mem::offset_of!(android_app, pendingEditorAction) - 88usize]; + [::std::mem::offset_of!(android_app, pendingEditorAction) - 96usize]; ["Offset of field: android_app::activityState"] - [::std::mem::offset_of!(android_app, activityState) - 92usize]; + [::std::mem::offset_of!(android_app, activityState) - 100usize]; ["Offset of field: android_app::destroyRequested"] - [::std::mem::offset_of!(android_app, destroyRequested) - 96usize]; + [::std::mem::offset_of!(android_app, destroyRequested) - 104usize]; ["Offset of field: android_app::inputBuffers"] - [::std::mem::offset_of!(android_app, inputBuffers) - 104usize]; + [::std::mem::offset_of!(android_app, inputBuffers) - 112usize]; ["Offset of field: android_app::currentInputBuffer"] - [::std::mem::offset_of!(android_app, currentInputBuffer) - 200usize]; + [::std::mem::offset_of!(android_app, currentInputBuffer) - 208usize]; ["Offset of field: android_app::textInputState"] - [::std::mem::offset_of!(android_app, textInputState) - 204usize]; - ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 208usize]; - ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 248usize]; + [::std::mem::offset_of!(android_app, textInputState) - 212usize]; + ["Offset of field: android_app::mutex"][::std::mem::offset_of!(android_app, mutex) - 216usize]; + ["Offset of field: android_app::cond"][::std::mem::offset_of!(android_app, cond) - 256usize]; ["Offset of field: android_app::msgread"] - [::std::mem::offset_of!(android_app, msgread) - 296usize]; + [::std::mem::offset_of!(android_app, msgread) - 304usize]; ["Offset of field: android_app::msgwrite"] - [::std::mem::offset_of!(android_app, msgwrite) - 300usize]; + [::std::mem::offset_of!(android_app, msgwrite) - 308usize]; ["Offset of field: android_app::thread"] - [::std::mem::offset_of!(android_app, thread) - 304usize]; + [::std::mem::offset_of!(android_app, thread) - 312usize]; ["Offset of field: android_app::cmdPollSource"] - [::std::mem::offset_of!(android_app, cmdPollSource) - 312usize]; + [::std::mem::offset_of!(android_app, cmdPollSource) - 320usize]; ["Offset of field: android_app::running"] - [::std::mem::offset_of!(android_app, running) - 336usize]; + [::std::mem::offset_of!(android_app, running) - 344usize]; ["Offset of field: android_app::stateSaved"] - [::std::mem::offset_of!(android_app, stateSaved) - 340usize]; + [::std::mem::offset_of!(android_app, stateSaved) - 348usize]; ["Offset of field: android_app::destroyed"] - [::std::mem::offset_of!(android_app, destroyed) - 344usize]; + [::std::mem::offset_of!(android_app, destroyed) - 352usize]; ["Offset of field: android_app::redrawNeeded"] - [::std::mem::offset_of!(android_app, redrawNeeded) - 348usize]; + [::std::mem::offset_of!(android_app, redrawNeeded) - 356usize]; ["Offset of field: android_app::pendingWindow"] - [::std::mem::offset_of!(android_app, pendingWindow) - 352usize]; + [::std::mem::offset_of!(android_app, pendingWindow) - 360usize]; ["Offset of field: android_app::pendingContentRect"] - [::std::mem::offset_of!(android_app, pendingContentRect) - 360usize]; + [::std::mem::offset_of!(android_app, pendingContentRect) - 368usize]; ["Offset of field: android_app::keyEventFilter"] - [::std::mem::offset_of!(android_app, keyEventFilter) - 376usize]; + [::std::mem::offset_of!(android_app, keyEventFilter) - 384usize]; ["Offset of field: android_app::motionEventFilter"] - [::std::mem::offset_of!(android_app, motionEventFilter) - 384usize]; + [::std::mem::offset_of!(android_app, motionEventFilter) - 392usize]; ["Offset of field: android_app::inputAvailableWakeUp"] - [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 392usize]; + [::std::mem::offset_of!(android_app, inputAvailableWakeUp) - 400usize]; ["Offset of field: android_app::inputSwapPending"] - [::std::mem::offset_of!(android_app, inputSwapPending) - 393usize]; + [::std::mem::offset_of!(android_app, inputSwapPending) - 401usize]; }; #[doc = " Looper data ID of commands coming from the app's main thread, which\n is returned as an identifier from ALooper_pollOnce(). The data for this\n identifier is a pointer to an android_poll_source structure.\n These can be retrieved and processed with android_app_read_cmd()\n and android_app_exec_cmd()."] pub const NativeAppGlueLooperId_LOOPER_ID_MAIN: NativeAppGlueLooperId = 1; @@ -5331,6 +5335,10 @@ unsafe extern "C" { #[doc = " Clear the array of key events that were waiting to be handled, and release\n each of them.\n\n This method should be called after you have processed the key up events in\n your game loop. You should handle events at each iteration of your game loop."] pub fn android_app_clear_key_events(inputBuffer: *mut android_input_buffer); } +unsafe extern "C" { + #[doc = " A hook that is called within Activity.onCreate, before the android_main\n thread has been spawned.\n\n This gives the Rust glue code a chance to perform any necessary\n initialization that needs to run from the Java main/UI thread, before the\n android_main thread is started."] + pub fn _rust_glue_on_create_hook(app: *mut android_app); +} unsafe extern "C" { #[doc = " This is a springboard into the Rust glue layer that wraps calling the\n main entry for the app itself."] pub fn _rust_glue_entry(app: *mut android_app); diff --git a/android-activity/src/game_activity/mod.rs b/android-activity/src/game_activity/mod.rs index 6a43771..1fc4cd0 100644 --- a/android-activity/src/game_activity/mod.rs +++ b/android-activity/src/game_activity/mod.rs @@ -959,8 +959,15 @@ extern "Rust" { pub fn android_main(app: AndroidApp); } +// This is called via `GameActivity.onCreate`, from the Java main/UI thread, +// before spawning an `android_main` thread. +#[no_mangle] +pub unsafe extern "C" fn _rust_glue_on_create_hook(_native_app: *mut ffi::android_app) { + // Noop currently +} + // This is a spring board between android_native_app_glue and the user's -// `app_main` function. This is run on a dedicated thread spawned +// `android_main` function. This is run on a dedicated thread spawned // by android_native_app_glue. #[no_mangle] pub unsafe extern "C" fn _rust_glue_entry(native_app: *mut ffi::android_app) {