axmolengine / axmol

Axmol Engine – A Multi-platform Engine for Desktop, XBOX (UWP) and Mobile games. (A fork of Cocos2d-x-4.0)
https://axmol.dev
MIT License
922 stars 205 forks source link

Android: bug in getSafeAreaRect calculations #1876

Closed crazyhappygame closed 5 months ago

crazyhappygame commented 6 months ago
  1. Draw auto safeAreaRect = _director->getSafeAreaRect();
  2. Bug: safeAreaRect does not take into account corners at the bottom of screen.

Please check screenshots below. Blue rectangle it is safeAreaRect. For Android devices with rounded corners blue is not drawn properly.

Android incorrect: moto G54 (the same issue on other Android devices with rounded corners) WhatsApp Image 2024-05-02 at 22 02 29

IPhone correct: iPhone Max Pro 15 WhatsApp Image 2024-05-02 at 21 58 32

rh101 commented 6 months ago

Have you checked the Rect GLViewImpl::getSafeAreaRect() method in GLViewImpl-android.cpp when running on a device with rounded corners to see what is going on in there? ~~Check if this line is returning true: bool isScreenRound = JniHelper::callStaticBooleanMethod("org/axmol/lib/AxmolEngine", "isScreenRound");~~ Never mind, this is only for wearable devices.

rh101 commented 5 months ago

@crazyhappygame I just had a look at this, and on creating a new project, and displaying this on an Android device with rounded corners, and the result seems correct: image

There is no information in your initial post regarding how you set up the resolution policy, or any sample code, so there is nothing to go off in order to reproduce the issue quickly. The above screenshot was taken with a the resolution policy set to ResolutionPolicy::SHOW_ALL.

rh101 commented 5 months ago

When using ResolutionPolicy::EXACT_FIT, this is the result: image

It does go into the rounded corners on the right, which isn't optimal, but, it turns out that there is currently no way to determine if a device has rounded corners on Android. The left side of that screenshot is inset correctly because of the cutout (where the camera is etc.).

https://stackoverflow.com/a/50205832/1664652 https://developer.android.com/develop/ui/views/layout/display-cutout

The suggestion is that you have a list of device names and adjust the sizing based on that, which you can do in your own project as you come across more devices with the issue.

Alternatively, set a fixed cut-out size so it doesn't go all the way to the edge of the screen, regardless of what type of screen it is, assuming most screen released these days have rounded corners. This is the method I personally use for getting around this issue.

This is not a bug in Axmol.

crazyhappygame commented 5 months ago

I used FIXED_WIDTH. I think that safe area computation should be correct for all resolution policies.

Maybe we can use this: https://developer.android.com/reference/android/view/WindowInsets#getRoundedCorner(int)

rh101 commented 5 months ago

I used FIXED_WIDTH. I think that safe area computation should be correct for all resolution policies.

Maybe we can use this: https://developer.android.com/reference/android/view/WindowInsets#getRoundedCorner(int)

This applies to API31 (Android12) or higher, and it's not as straightforward as it may seem. An attempt to utilize this is in PR #1934, so try it out when you can, and let me know if it works for you. I've tested all ResolutionPolicy types on it, and the safe area is correct on all when using the changes in that PR.