The `Game.Window.Resizable` setter on Android causes unexpected screen rotation
Through this issue, we already know that when SDL3Window initializes, it reads the SDL_HINT_ORIENTATIONS instead of RequestedOrientation, which can cause problems.
So, a possible solution is to use SDL.SDL3.SDL_SetHint to pre-assign the orientation we need.
However, this still doesn't avoid another problem: besides during initialization, the Window.Resizable property will call this setOrientationBis method again when its value changes. And I think users might not expect this. For example:
- A user might initially, similar to osu!, not assign a hint and use
RequestedOrientationto set the screen orientation to a specific value. Then, some method (perhaps a cross-platform settings option) tries to change the value ofResizable:Window.Resizable = !Window.Resizable. Then,RequestedOrientationwill suddenly be changed toFullUser. And what's stranger is that executingWindow.Resizable = !Window.Resizableagain will not restore the screen orientation, but will fix the screen to landscape or portrait.class MyGame : Game { [Reslove] AndroidGameActivity activity; [BackgroundDependencyLoader] load() => this.activity.RequestedOrientation = ScreenOrientation.Landscape; // By this action, RequestedOrientation may become `FullUser`, or `SensorLandscape`, or `SensorLandscape` override OnClick() => Window.Resizable = !Window.Resizable; } - Alternatively, a user might use a hint to make the screen display in landscape for things like loading screens. Then, there's an in-game setting to force the program into portrait mode. At this point,
RequestedOrientationmust be used, asSDL_HINT_ORIENTATIONSdoes not notify Android that its status has changed. Then, if an attempt is made to change theResizablevalue while in portrait mode, theSDL_HINT_ORIENTATIONStakes effect again, forcing the screen back to landscape. And changingResizableback to its original value has no effect. I believe users who haven't seen any comments about this would be very confused.class AndroidGameActivity { override OnCreate() => SDL.SDL3.SDL_SetHint(SDL.SDL3.SDL_HINT_ORIENTATIONS, "LandscapeRight"u8); } class MyGame : Game { [Reslove] AndroidGameActivity activity; [BackgroundDependencyLoader] load() => this.activity.RequestedOrientation = ScreenOrientation.Landscape; // By this action, RequestedOrientation will become `ReverseLandscape` override OnClick() => Window.Resizable = !Window.Resizable; }
Here's a sample program. Just install the compiled SampleGame.Android project on your device. You can try clicking some buttons and observe how the screen orientation changes.
So, do we also need additional wiki documentation or comments for Resizable to inform users about this unusual issue? For example, mentioning that changing Resizable in Android can cause unexpected orientation changes, or reminding users to record the value of RequestedOrientation before modifying Resizable in Android and restore it after the call is complete.
By the way, I have a potentially viable solution for the three related issues, which is to override the SetOrientationBis method in AndroidGameActivity. I have already checked the complete call chain. But after asking for others' opinions on Discord, I received the reply, "If it works, then don't touch it." So, whether to solve these problems, or to consider them not to be problems, is entirely up to you guys. I have no other ideas.😕
I have a potentially viable solution for the three related issues, which is to override the SetOrientationBis method in AndroidGameActivity. I have already checked the complete call chain.
flowchart TD
subgraph s1["SDL.android-project"]
n1["SDLActivity.setOrientationBis"]
n2["SDLActivity.setOrientation"]
end
subgraph s2["SDL"]
n4["Android_JNI_SetOrientation"]
n5["Android_CreateWindow"]
n7["SDL_CreateWindowWithProperties"]
n8["SDL_CreateWindow"]
n9["Android_SetWindowResizable"]
n10["SDL_SetWindowResizable"]
end
subgraph s3["osu.Framework"]
n17["AndroidGameActivity.SetOrientationBis"]
n15["SDL3Window.Create"]
n13["SDL3Window.Resizable"]
n14["SDL3Window.UpdateWindowStateAndSize"]
end
subgraph s4["SDL3-CS"]
n16["SDLActivity.SetOrientationBis"]
end
n1 --> n2
n1 -.-> n16
n4 --> n5 & n9
n5 --> n7
n7 --> n8
n9 --> n10
n10 --> n13 & n14
n8 --> n15
n2 --> n4
n16 -.-> n17
n17 o--o n18["Maybe override it here?"]
n1@{ shape: rect}
n18@{ shape: braces}
style n17 stroke-dasharray: 2
click n1 "https://github.com/libsdl-org/SDL/blob/d16371b923fed57e5df676a84435baf1d1061a6a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java#L1125"
click n2 "https://github.com/libsdl-org/SDL/blob/d16371b923fed57e5df676a84435baf1d1061a6a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java#L1115"
click n4 "https://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/core/android/SDL_android.c#L1625"
click n5 "https://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/video/android/SDL_androidwindow.c#L39"
click n7 "https://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/video/SDL_video.c#L2335"
click n8 "http://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/video/SDL_video.c#L2554"
click n9 "https://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/video/android/SDL_androidwindow.c#L171"
click n10 "https://github.com/libsdl-org/SDL/blob/514d96de07c3b1b8603ee4701229bb055a1dd2e3/src/video/SDL_video.c#L2978"
click n17 "https://github.com/ppy/osu-framework/blob/a7815796130dbf24194d76437599464999976f02/osu.Framework.Android/AndroidGameActivity.cs?plain=1#L17C1-L17C60"
click n15 "https://github.com/ppy/osu-framework/blob/a7815796130dbf24194d76437599464999976f02/osu.Framework/Platform/SDL3/SDL3Window.cs?plain=1#L201"
click n13 "https://github.com/ppy/osu-framework/blob/a7815796130dbf24194d76437599464999976f02/osu.Framework/Platform/SDL3/SDL3Window_Windowing.cs?plain=1#L176"
click n14 "https://github.com/ppy/osu-framework/blob/a7815796130dbf24194d76437599464999976f02/osu.Framework/Platform/SDL3/SDL3Window_Windowing.cs?plain=1#L636"