From e2369a834b92dc2ea42933513999c56dd95126a2 Mon Sep 17 00:00:00 2001 From: Anish Kumar Date: Tue, 27 Jan 2026 15:22:27 +0530 Subject: [PATCH] Add device orientation change signal in DisplayServer This PR: - Fixes the orientation detection logic on Android - Adds an orientation_changed signal in DisplayServer Co-Authored-By: bruvzg <7645683+bruvzg@users.noreply.github.com> --- doc/classes/DisplayServer.xml | 10 ++++++++++ drivers/apple_embedded/godot_view_controller.mm | 11 +++++++++++ .../lib/src/main/java/org/godotengine/godot/Godot.kt | 12 +++++++----- .../main/java/org/godotengine/godot/GodotLib.java | 2 +- platform/android/java_godot_lib_jni.cpp | 7 ++++++- platform/android/java_godot_lib_jni.h | 2 +- servers/display/display_server.cpp | 2 ++ 7 files changed, 38 insertions(+), 8 deletions(-) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index d568c96626a..853a8befeac 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -2533,6 +2533,16 @@ + + + + + Emitted when the device orientation changes. [param orientation] is the new orientation. + Returns [code]1[/code] for portrait, [code]2[/code] for landscape, and [code]0[/code] if the orientation is undefined. + [b]Note:[/b] This method is implemented on Android and iOS. + + + Display server supports global menu. This allows the application to display its menu items in the operating system's top bar. [b]macOS[/b] diff --git a/drivers/apple_embedded/godot_view_controller.mm b/drivers/apple_embedded/godot_view_controller.mm index 0134d718cfc..67701631fe0 100644 --- a/drivers/apple_embedded/godot_view_controller.mm +++ b/drivers/apple_embedded/godot_view_controller.mm @@ -253,6 +253,17 @@ if (camera_server) { camera_server->handle_display_rotation_change((int)orientation); } + + DisplayServer *display_server = DisplayServer::get_singleton(); + if (display_server) { + int out = 0; + if (UIInterfaceOrientationIsPortrait(orientation)) { + out = 1; + } else if (UIInterfaceOrientationIsLandscape(orientation)) { + out = 2; + } + display_server->emit_signal("orientation_changed", out); + } }]; } #endif diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt index f467d2c85ca..e72f5c1d2df 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/Godot.kt @@ -175,7 +175,6 @@ class Godot private constructor(val context: Context) { */ private var renderViewInitialized = false private var primaryHost: GodotHost? = null - private var currentConfig = context.resources.configuration /** * Tracks whether we're in the RESUMED lifecycle state. @@ -197,6 +196,7 @@ class Godot private constructor(val context: Context) { private var useDebugOpengl = false private var darkMode = false private var backgroundColor: Int = Color.BLACK + private var orientation = Configuration.ORIENTATION_UNDEFINED internal var containerLayout: FrameLayout? = null var renderView: GodotRenderView? = null @@ -234,7 +234,9 @@ class Godot private constructor(val context: Context) { Log.v(TAG, "InitEngine with params: $commandLineParams") - darkMode = context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES + val config = context.resources.configuration + darkMode = (config.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES + orientation = config.orientation beginBenchmarkMeasure("Startup", "Godot::initEngine") try { @@ -775,12 +777,12 @@ class Godot private constructor(val context: Context) { } } - if (currentConfig.orientation != newConfig.orientation) { + if (orientation != newConfig.orientation) { + orientation = newConfig.orientation runOnRenderThread { - GodotLib.onScreenRotationChange(newConfig.orientation) + GodotLib.onOrientationChange(orientation) } } - currentConfig = newConfig } /** diff --git a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java index 38e32714cf0..5f1265ca0cb 100644 --- a/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/main/java/org/godotengine/godot/GodotLib.java @@ -299,7 +299,7 @@ public class GodotLib { * Invoked when the screen orientation changes. * @param orientation the new screen orientation */ - static native void onScreenRotationChange(int orientation); + static native void onOrientationChange(int orientation); /** * @return true if input must be dispatched from the render thread. If false, input is diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 41f963849a3..0167705a71e 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -630,7 +630,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIE } } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onScreenRotationChange(JNIEnv *env, jclass clazz, jint p_orientation) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onOrientationChange(JNIEnv *env, jclass clazz, jint p_orientation) { if (step.get() <= STEP_SETUP) { return; } @@ -639,6 +639,11 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onScreenRotationChang if (camera_server) { camera_server->handle_display_rotation_change(p_orientation); } + + DisplayServer *display_server = DisplayServer::get_singleton(); + if (display_server) { + display_server->emit_signal("orientation_changed", p_orientation); + } } JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_shouldDispatchInputToRenderThread(JNIEnv *env, jclass clazz) { diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 0df20794164..83ca53ce2f1 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -72,7 +72,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hardwareKeyboardConne JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onScreenRotationChange(JNIEnv *env, jclass clazz, jint p_orientation); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onOrientationChange(JNIEnv *env, jclass clazz, jint p_orientation); JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_shouldDispatchInputToRenderThread(JNIEnv *env, jclass clazz); JNIEXPORT jstring JNICALL Java_org_godotengine_godot_GodotLib_getProjectResourceDir(JNIEnv *env, jclass clazz); JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_isEditorHint(JNIEnv *env, jclass clazz); diff --git a/servers/display/display_server.cpp b/servers/display/display_server.cpp index cfafce58c6e..4e929e31d7b 100644 --- a/servers/display/display_server.cpp +++ b/servers/display/display_server.cpp @@ -1286,6 +1286,8 @@ void DisplayServer::unregister_additional_output(Object *p_object) { } void DisplayServer::_bind_methods() { + ADD_SIGNAL(MethodInfo("orientation_changed", PropertyInfo(Variant::INT, "orientation"))); + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature); ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);